Files
dancefinder-app/utils/auth-client/index.js
T

122 lines
3.3 KiB
JavaScript

import auth0 from 'auth0-js';
import {
storeStateAndNonce,
clearStateAndNonce,
getStateAndNonce,
storeAuth,
getIdToken,
getUserInfo,
clear,
getExpiresAt,
getAccessToken,
} from './storage';
export default class AuthenticationClient {
/**
* Instantiates an authentication client.
* You should only need one per app and authentication method.
* @param {Object} auth0Config An auth0 configuration object, as per their API.
*/
constructor(auth0Config) {
this.config = auth0Config;
this.webAuth = new auth0.WebAuth(auth0Config);
}
logout() {
clear();
}
getUserInfo() {
return getUserInfo();
}
isAuthenticated() {
return !!getIdToken();
}
isExpired() {
const expiresAt = getExpiresAt();
return new Date().getTime() > expiresAt && this.isAuthenticated();
}
/**
* Triggers a login by redirecting to auth0.
*/
triggerLogin(state) {
// clear the state and nonce when triggering a login - otherwise hash parsing wont work.
clearStateAndNonce();
this.webAuth.authorize({ state: JSON.stringify(state) });
}
triggerSilentLogin(state) {
if (!state) {
throw new Error('You must specify a state.');
}
const nonce = new Date().getTime().toString();
// before we trigger the silent login - store the state and nonce in localstorage.
storeStateAndNonce(state, nonce);
let url = this.webAuth.client.buildAuthorizeUrl({
...this.config,
nonce,
state: JSON.stringify(state),
});
url += '&prompt=none';
window.location.href = url;
}
checkSession(resolve, reject) {
this.webAuth.checkSession({state: {}}, (err, result) => {
if (err) {
return reject(err || 'Re-authentication failed');
} else {
return this.storeSession(result, resolve, reject);
}
});
}
storeSession(authResult, resolve, reject) {
this.webAuth.client.userInfo(authResult.accessToken, (err, user) => {
if (err) {
// if any error happens when fetching user info - nuke all session info
this.logout();
return reject('Authentication failed');
}
const expiresAt = JSON.stringify(authResult.expiresIn * 1000 + new Date().getTime());
storeAuth({ ...authResult, user, expiresAt });
return resolve(JSON.parse(authResult.state));
});
}
handleAuthentication() {
return new Promise((resolve, reject) => {
// retrieve stored state and nonce from localstorage
const { state, nonce } = getStateAndNonce();
// however, if there is no state and nonce stored - do not provide any param to parseHash.
// Otherwise, the non-silent logins will fail due to invalid state.
const parseHashParam = state && nonce ? { state, nonce } : undefined;
this.webAuth.parseHash(parseHashParam, (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
// If we fail to either set the session or store user info - reject and clear the session.
try {
return this.storeSession(authResult, resolve, reject);
} catch (error) {
return reject(error || 'Authentication failed');
}
} else {
return reject(err || 'Authentication failed');
}
});
});
}
idToken() {
return getIdToken();
}
accessToken() {
return getAccessToken();
}
}