Playing with vuetify in this project I came across v-text-field
and the validation.
The documentation shows only very little information in that regard and if you need more conditional validation, how would you do that?
Continue reading “vuetify v-text-field validation if length 0 and length greater than x”
Keycloak-js client with Quasar (now updated for v2)
So you’d like to use openid-connect (oidc), especially keycloak (kc) in your Quasar app.
There’s a package, @dsb-norge/vue-keycloak-js . I’d recommend you fork it and create your own version with the keycloak-js version that matches your Keycloak server. However it also works with just the version used in this git repository.
The git repository is available at
https://github.com/dsb-norge/vue-keycloak-js
This is for Quasar v1
Alright let’s get started.
1. Create a file named silent-check-sso.html
with the following content:
1 2 3 4 5 6 7 |
<html> <body> <script> parent.postMessage(location.href, location.origin) </script> </body> </html> |
Put that file in the public
directory as its path is
public/silent-check-sso.html
.
2. Create boot/keycloak.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import VueKeyCloak from '@dsb-norge/vue-keycloak-js' import axios from 'axios' export default async ({ Vue, router, store, app }) => { async function tokenInterceptor () { axios.interceptors.request.use(config => { config.headers.Authorization = `Bearer ${Vue.prototype.$keycloak.token}` return config }, error => { return Promise.reject(error) }) } return new Promise(resolve => { Vue.use(VueKeyCloak, { init: { onLoad: 'login-required', // or 'check-sso' flow: 'standard', pkceMethod: 'S256', silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html', checkLoginIframe: false // otherwise it would reload the window every so seconds }, config: { url: 'https://your.keycloak.installation/auth', realm: 'your-realm-name', clientId: 'your-client-id' }, onReady: (keycloak) => { tokenInterceptor() resolve() } }) }) } |
3. Reference the created boot file in quasar.conf.js
1 2 3 4 5 6 7 |
// ... boot: [ 'i18n', 'axios', 'keycloak' ], // ... |
And that’s really all there is to it.
After this is done you can access the keycloak object via $keycloak
in your template.
This is for Qusasar v2:
Thanks a bunch to Excel1 and yusufkandemir for figuring it out.
First you have to upgrade or use the v2 branch of @dsb-norge/vue-keycloak-js
.
e.g. npm i @dsb-norge/vue-keycloak-js@2
or use your own fork
But essentially you do whatever you would do for v1 only the boot/keycloak.js file is different
The boot/keycloak.js file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import { boot } from 'quasar/wrappers' import VueKeyCloak from '@dsb-norge/vue-keycloak-js' import axios from 'axios' export default boot(async ({ app, router, store }) => { async function tokenInterceptor () { axios.interceptors.request.use(config => { config.headers.Authorization = `Bearer ${app.config.globalProperties.$keycloak.token}` return config }, error => { return Promise.reject(error) }) } return new Promise(resolve => { app.use(VueKeyCloak, { init: { onLoad: 'login-required', // or 'check-sso' flow: 'standard', pkceMethod: 'S256', silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html', checkLoginIframe: false }, config: { url: 'https://my.keylcoak.domain/auth', realm: 'my.realm', clientId: 'my-client_id' }, onReady: (keycloak) => { tokenInterceptor() resolve() } }) }) }) |
and of course don’t forget to add it to the boot array in quasar.conf.js
vue dev server with nginx
The Nginx conf is the same for any sock-js site. It can be used for Vue and Angular and Svelte, not sure about React but I’d guess it uses sock-js as well.
My dev domain is qxdsladmin.local in this example.
/etc/nginx/conf.d/qxdsladmin.local.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
server { listen 80; listen [::]:80; server_name qxdsladmin.local; root /home/darko/WebProjects/qxdsladmin/public/; index index.html; error_log /var/log/nginx/qxdsladmin.local.error; location / { proxy_pass http://localhost:4201; proxy_read_timeout 30; proxy_connect_timeout 30; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /sockjs-node/ { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; rewrite ^/(.*)$ /$1 break; proxy_set_header Host localhost; proxy_pass http://localhost:4201/; } location ~ ^/api/v1/.* { proxy_pass http://unix:/tmp/qxdsl-proxy.sock; proxy_read_timeout 30; proxy_connect_timeout 30; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } |
This location ~ ^/api/v1/.*
is a mountpoint for the backend http api, which in my case is a RESTful Go API.
The vue part, create a file named vue.config.js in the project’s root dir.
So if you used vue create vxdsladmin
it’s the directory you go to when doing cd vxdsladmin
.
1 2 3 4 5 6 7 8 |
module.exports = { devServer: { disableHostCheck: true, host: '0.0.0.0', port: 4201, public: 'qxdsladmin.local' } } |
This works for me, but maybe it can be improved. Let me know if that’s the case.