Detecting if the Keycloak Server is available?
flowt-au opened this issue · 5 comments
Hi. Thanks for keeping this package going. :-)
I am trying to work out how best to check if the KC server is available before I try to use it. At present, if the KC endpoint is not reachable my app navigates to the configured endpoint and throws ERR_CONNECTION_REFUSED
.
It would be great to be able to check first, stay on the app's domain and handle the error gracefully in my app, rather than the user being marooned on the KC url.
The KC docs and chatter talks about using messageReceiveTimeout
(defaults to 10secs) which can be set in options. But how to catch that?
Here is my current config (using it with Quasar)
import { vueKeycloak } from '@josempgon/vue-keycloak'
const keycloakServerUrl = httpprotocol + kc_domain + kc_port
const res = await app.use(vueKeycloak, {
initOptions: {
flow: 'standard', // default
checkLoginIframe: false, // default
onLoad: 'login-required', // default
messageReceiveTimeout: 1000
},
config: {
url: keycloakServerUrl,
realm: kc_realm,
clientId: kc_client
}
})
Any suggestions?
Thanks,
Murray
Hi @flowt-au. I think the best approach to check the KC availability before redirecting to keycloak for authentication would be to use the well-known endpoint. Use an HTTP library to issue a GET on that endpoint before initiating the authentication process and you could then handle the KC not available error on your app.
Thank you. Yes, this is what I did and it works well.
const keycloakServerUrl = httpprotocol + kc_domain + kc_port
const keycloakWellKnownUrl = httpprotocol + kc_domain + kc_port + '/realms/' + kc_realm + '/.well-known/openid-configuration'
fetch(keycloakWellKnownUrl)
.then(async response => {
if (response.ok) {
console.log('Keycloak server is up', response);
const res = await app.use(vueKeycloak, {
initOptions: {
flow: 'standard', // default
checkLoginIframe: false, // default
onLoad: 'login-required' // default
},
config: {
// Set in yourappconfig/ServerConfig.js
url: keycloakServerUrl,
realm: kc_realm,
clientId: kc_client
}
})
} else {
console.error('Keycloak server is down', response);
// Take some action...
}
})
.catch(error => {
console.error('Error pinging Keycloak server:', error)
// Take some action...
});
An alternative that does not block your app entry point (e.g. src/main.js
), would be to initialize the vue-keycloak
plugin in a way that it does not trigger an automatic login:
import { vueKeycloak } from '@josempgon/vue-keycloak'
import { kc_url, kc_realm, kc_client } from '<path_to_some_config_file>';
app.use(vueKeycloak, {
initOptions: {
onLoad: null,
},
config: {
url: kc_url,
realm: kc_realm,
clientId: kc_client,
}
})
and then, in your main Vue SFC (e.g. src/App.vue
) you perform the login only if you can reach the well-known endpoint:
<script setup>
import { watch } from 'vue';
import { useKeycloak } from '@josempgon/vue-keycloak';
import { kc_url, kc_realm } from '<path_to_some_config_file>';
const { isAuthenticated, isPending, keycloak } = useKeycloak();
const keycloakWellKnownUrl = kc_url + '/realms/' + kc_realm + '/.well-known/openid-configuration';
watch([isAuthenticated, isPending], ([authenticated, pending]) => {
if (authenticated || pending) return;
fetch(keycloakWellKnownUrl)
.then(response => {
if (response.ok) {
keycloak.login();
} else {
console.error('Keycloak server is not working properly:', response);
// Take some action...
}
})
.catch(error => {
console.error('Keycloak server is unreachable:', error);
// Take some action...
});
});
</script>
Oh, yes, I see. I didn't realise one could defer the authentication like that. Cool! Thanks. :-)
Just a followup:
It turns out that fetching the wellknownurl can cause some flow issues. It worked fine on my local dev machine but for some reason (not yet understood) when used the approach on my server I had the issue below. My Vue app is in a subdomain served by Apache and is using the Vue recommended .htaccess settings.
Wrapping the keycloak initialisation inside the fetch as I was doing (above) caused Keycloak to loop "infinitely" once the user was authenticated. I removed the fetch "wrapper" and all worked well.
Anyway, just a heads-up in case anyone else follows my pattern above.
I will play some more with other approaches (eg the suggested delayed login above) to see how to make this work and report back.
Thanks,
Murray