OpenID Connect (OIDC) is a widely-used authentication protocol on top of OAuth 2.0. There are several libraries available that make integrating OIDC into a Vue.js application relatively straightforward. One of the popular libraries for this purpose is @auth0/auth0-spa-js.
Below is a basic guide to setting up an OIDC client for Vue.js using @auth0/auth0-spa-js
:
1. Install the necessary packages:
npm install @auth0/auth0-spa-js
2. Set up Auth0 configuration:
Create a new file named auth.js
inside your src
folder:
// src/auth.js
import Vue from 'vue';
import createAuth0Client from '@auth0/auth0-spa-js';
/** Define a default action to perform after authentication */
const DEFAULT_REDIRECT_CALLBACK = () =>
window.history.replaceState({}, document.title, window.location.pathname);
let instance;
/** Returns the current instance of the SDK */
export const getInstance = () => instance;
/** Creates an instance of the Auth0 SDK. If one has already been created, it returns that instance */
export const useAuth0 = ({
onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
redirectUri = window.location.origin,
...options
}) => {
if (instance) return instance;
// The 'instance' is simply a Vue object
instance = new Vue({
data() {
return {
loading: true,
isAuthenticated: false,
user: {},
auth0Client: null,
popupOpen: false,
error: null
};
},
methods: {
/** Authenticates the user using a popup window */
async loginWithPopup(o) {
this.popupOpen = true;
try {
await this.auth0Client.loginWithPopup(o);
this.user = await this.auth0Client.getUser();
this.isAuthenticated = true;
} catch (e) {
console.error(e);
} finally {
this.popupOpen = false;
}
},
/** Handles the callback when logging in using a redirect */
async handleRedirectCallback() {
this.loading = true;
try {
await this.auth0Client.handleRedirectCallback();
this.user = await this.auth0Client.getUser();
this.isAuthenticated = true;
} catch (e) {
this.error = e;
} finally {
this.loading = false;
}
},
/** Authenticates the user using the redirect method */
loginWithRedirect(o) {
return this.auth0Client.loginWithRedirect(o);
},
/** Returns all the claims present in the ID token */
getIdTokenClaims(o) {
return this.auth0Client.getIdTokenClaims(o);
},
/** Returns the access token. If the token is invalid or missing, a new one is retrieved */
getTokenSilently(o) {
return this.auth0Client.getTokenSilently(o);
},
/** Logs the user out and removes their session on the authorization server */
logout(o) {
return this.auth0Client.logout(o);
}
},
async created() {
// Create a new instance of the Auth0 client
this.auth0Client = await createAuth0Client({
domain: options.domain,
client_id: options.clientId,
audience: options.audience,
redirect_uri: redirectUri
});
try {
// If the user is returning to the app after authentication...
if (
window.location.search.includes('code=') &&
window.location.search.includes('state=')
) {
// handle the redirect and retrieve tokens
const { appState } = await this.auth0Client.handleRedirectCallback();
// Execute the onRedirectCallback now that tokens have been retrieved
onRedirectCallback(appState);
}
} catch (e) {
this.error = e;
} finally {
// Initialize our internal authentication state
this.isAuthenticated = await this.auth0Client.isAuthenticated();
this.user = await this.auth0Client.getUser();
this.loading = false;
}
}
});
return instance;
};
// Create a simple Vue plugin to expose the wrapper object throughout the application
export const Auth0Plugin = {
install(Vue, options) {
Vue.prototype.$auth = useAuth0(options);
}
};
3. Use the Auth0 Plugin in your app:
In your main.js
(or equivalent):
import Vue from 'vue';
import { Auth0Plugin } from './auth';
import App from './App.vue';
Vue.config.productionTip = false;
Vue.use(Auth0Plugin, {
domain: 'YOUR_AUTH0_DOMAIN',
clientId: 'YOUR_AUTH0_CLIENT_ID',
audience: 'YOUR_AUTH0_AUDIENCE',
onRedirectCallback: (appState) => {
router.push(
appState && appState.targetUrl
? appState.targetUrl
: window.location.pathname
);
}
});
new Vue({
render: (h) => h(App),
}).$mount('#app');
4. Authentication in components:
Now, in your Vue components, you can use the authentication methods like so:
<template>
<div v-if="$auth.loading">
Loading...
</div>
<div v-else-if="!$auth.isAuthenticated">
<button @click="$auth.loginWithRedirect()">Log in</button>
</div>
<div v-else>
<p>Welcome, {{ $auth.user.name }}!</p>
<button @click="$auth.logout()">Log out</button>
</div>
</template>
This is a basic setup and should be modified according to your specific needs. Always refer to the official documentation of the library and OIDC provider for more detailed and updated information.
- OIDC Client Library: One popular library used for this purpose is
oidc-client-js
. You can check out its GitHub repository for details on how to set it up: - Vue.js OIDC Plugins: There are plugins built specifically for Vue.js that make integrating OIDC easier:
- vue-auth-oidc: https://github.com/perarnborg/vuex-oidc
- vue-oidc-client: https://github.com/gbvitrano/vue-oidc-client
- Documentation: The OpenID Connect official website provides extensive documentation on how OIDC works, which will be helpful in understanding the flow and integrating it into your application:
- Tutorials & Blogs: Occasionally, developers write tutorials and articles about their experiences integrating OIDC with Vue.js. Websites like Medium, Dev.to, and personal developer blogs are great places to find such content.
- Community: When you run into challenges or have specific questions, communities such as Stack Overflow (https://stackoverflow.com/) can be invaluable. Just ensure your questions are well-framed and provide enough context for others to assist you.
- Vue.js Official Documentation: To ensure compatibility and understand best practices, always consult the Vue.js official documentation when integrating external libraries or plugins.
How to authenticate pages in Vuejs (OIDC)