import { createAuth0Client, Auth0Client, GetTokenSilentlyOptions, IdToken, LogoutOptions, RedirectLoginOptions, User } from '@auth0/auth0-spa-js' import { Ref, ref } from 'vue' /** Define a default action to perform after authentication */ const DEFAULT_REDIRECT_CALLBACK = (_: any) => window.history.replaceState({}, document.title, window.location.pathname) interface Client { loading: Ref isAuthenticated: Ref user: Ref auth0Client?: Promise error: Ref handleRedirectCallback: () => Promise loginWithRedirect: (o: RedirectLoginOptions) => Promise getIdTokenClaims: () => Promise getTokenSilently: (o: GetTokenSilentlyOptions) => Promise logout: (o: LogoutOptions) => Promise } let instance: Client const params = (new URL(window.location.href)).searchParams const domain = params.get('domain') || 'unbound.eu.auth0.com' export const useAuth = (onRedirectCallback: (appState?: any) => void = DEFAULT_REDIRECT_CALLBACK) => { if (instance) { return instance } const options = { domain, clientId: 'orQfnvCPUR5C3mJkKoiWLQHOVQsBn60e', authorizationParams: { audience: 'http://dancefinder.unbound.se', redirect_uri: window.location.origin } } instance = { loading: ref(true), isAuthenticated: ref(false), user: ref(undefined), auth0Client: undefined, error: ref(null), /** Handles the callback when logging in using a redirect */ handleRedirectCallback: () => { instance.loading.value = true return instance.auth0Client!.then(client => client.handleRedirectCallback()) .then(() => { return instance.auth0Client?.then(client => client.getUser()) .then((user) => { instance.user.value = user instance.isAuthenticated.value = true instance.error.value = null } ) }) .catch((e) => { instance.error.value = e }) .finally(() => { instance.loading.value = false }) }, /** Authenticates the user using the redirect method */ loginWithRedirect: (o: RedirectLoginOptions) => { return instance.auth0Client!.then(client => client.loginWithRedirect(o)) .catch((e) => { instance.error.value = e }) }, /** Returns all the claims present in the ID token */ getIdTokenClaims: () => { return instance.auth0Client!.then(client => client.getIdTokenClaims()) }, /** Returns the access token. If the token is invalid or missing, a new one is retrieved */ getTokenSilently: (o: GetTokenSilentlyOptions) => { return instance.auth0Client!.then((client) => { return client.getTokenSilently(o).catch((e) => { instance.error.value = e }) }) }, /** Logs the user out and removes their session on the authorization server */ logout: (o: LogoutOptions) => { return instance.auth0Client!.then(client => client.logout(o)) } } const fetchUser = () => { return instance.auth0Client!.then(client => client.isAuthenticated()) .then((a) => { instance.auth0Client?.then(client => client.getUser() .then((u) => { instance.isAuthenticated.value = a instance.user.value = u instance.error.value = null })) }) } // Create a new instance of the SDK client using members of the given options object instance.auth0Client = createAuth0Client(options) instance.auth0Client .then((client) => { instance.loading.value = true // If the user is returning to the app after authentication.. if ( window.location.search.includes('state=') && ( window.location.search.includes('code=') || window.location.search.includes('error=') ) ) { // handle the redirect and retrieve tokens return client.handleRedirectCallback() .then((result) => { // Notify subscribers that the redirect callback has happened, passing the appState // (useful for retrieving any pre-authentication state) onRedirectCallback(result.appState) // Initialize our internal authentication state return fetchUser() }) } else { return fetchUser() } }) .catch((e) => { instance.error.value = e }) .finally(() => { instance.loading.value = false }) return instance }