UNPKG

fluro

Version:

Promise based HTTP Fluro client for the browser and node.js

1,003 lines (716 loc) 38.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>fluro.auth.js - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav > <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FluroAccess.html">FluroAccess</a><ul class='methods'><li data-type='method'><a href="FluroAccess.html#.addEventListener">addEventListener</a></li><li data-type='method'><a href="FluroAccess.html#.can">can</a></li><li data-type='method'><a href="FluroAccess.html#.canDeleteItem">canDeleteItem</a></li><li data-type='method'><a href="FluroAccess.html#.canEditItem">canEditItem</a></li><li data-type='method'><a href="FluroAccess.html#.canViewItem">canViewItem</a></li><li data-type='method'><a href="FluroAccess.html#.has">has</a></li><li data-type='method'><a href="FluroAccess.html#.isAuthor">isAuthor</a></li><li data-type='method'><a href="FluroAccess.html#.removeAllListeners">removeAllListeners</a></li><li data-type='method'><a href="FluroAccess.html#.removeEventListener">removeEventListener</a></li><li data-type='method'><a href="FluroAccess.html#.retrieveActionableRealms">retrieveActionableRealms</a></li><li data-type='method'><a href="FluroAccess.html#.retrieveCurrentSession">retrieveCurrentSession</a></li><li data-type='method'><a href="FluroAccess.html#.setDefaultApplication">setDefaultApplication</a></li></ul></li><li><a href="FluroAPI.html">FluroAPI</a><ul class='methods'><li data-type='method'><a href="FluroAPI.html#.delete">delete</a></li><li data-type='method'><a href="FluroAPI.html#.get">get</a></li><li data-type='method'><a href="FluroAPI.html#.post">post</a></li><li data-type='method'><a href="FluroAPI.html#.put">put</a></li></ul></li><li><a href="FluroAsset.html">FluroAsset</a><ul class='methods'><li data-type='method'><a href="FluroAsset.html#.avatarUrl">avatarUrl</a></li><li data-type='method'><a href="FluroAsset.html#.downloadUrl">downloadUrl</a></li><li data-type='method'><a href="FluroAsset.html#.filesize">filesize</a></li><li data-type='method'><a href="FluroAsset.html#.getUrl">getUrl</a></li><li data-type='method'><a href="FluroAsset.html#.imageUrl">imageUrl</a></li><li data-type='method'><a href="FluroAsset.html#.playerUrl">playerUrl</a></li><li data-type='method'><a href="FluroAsset.html#.posterUrl">posterUrl</a></li></ul></li><li><a href="FluroAuth.html">FluroAuth</a><ul class='methods'><li data-type='method'><a href="FluroAuth.html#.addEventListener">addEventListener</a></li><li data-type='method'><a href="FluroAuth.html#.changeAccount">changeAccount</a></li><li data-type='method'><a href="FluroAuth.html#.getCurrentToken">getCurrentToken</a></li><li data-type='method'><a href="FluroAuth.html#.getCurrentUser">getCurrentUser</a></li><li data-type='method'><a href="FluroAuth.html#.login">login</a></li><li data-type='method'><a href="FluroAuth.html#.logout">logout</a></li><li data-type='method'><a href="FluroAuth.html#.refreshAccessToken">refreshAccessToken</a></li><li data-type='method'><a href="FluroAuth.html#.removeAllListeners">removeAllListeners</a></li><li data-type='method'><a href="FluroAuth.html#.removeEventListener">removeEventListener</a></li><li data-type='method'><a href="FluroAuth.html#.retrieveUserFromResetToken">retrieveUserFromResetToken</a></li><li data-type='method'><a href="FluroAuth.html#.sendResetPasswordRequest">sendResetPasswordRequest</a></li><li data-type='method'><a href="FluroAuth.html#.set">set</a></li><li data-type='method'><a href="FluroAuth.html#.signup">signup</a></li><li data-type='method'><a href="FluroAuth.html#.sync">sync</a></li><li data-type='method'><a href="FluroAuth.html#.updateUserWithToken">updateUserWithToken</a></li></ul></li><li><a href="FluroCache.html">FluroCache</a><ul class='methods'><li data-type='method'><a href="FluroCache.html#.get">get</a></li><li data-type='method'><a href="FluroCache.html#.reset">reset</a></li></ul></li><li><a href="FluroContent.html">FluroContent</a><ul class='methods'><li data-type='method'><a href="FluroContent.html#.external">external</a></li><li data-type='method'><a href="FluroContent.html#.form">form</a></li><li data-type='method'><a href="FluroContent.html#.get">get</a></li><li data-type='method'><a href="FluroContent.html#.keys">keys</a></li><li data-type='method'><a href="FluroContent.html#.query">query</a></li><li data-type='method'><a href="FluroContent.html#.related">related</a></li><li data-type='method'><a href="FluroContent.html#.retrieve">retrieve</a></li><li data-type='method'><a href="FluroContent.html#.slug">slug</a></li><li data-type='method'><a href="FluroContent.html#.submitInteraction">submitInteraction</a></li><li data-type='method'><a href="FluroContent.html#.submitPost">submitPost</a></li><li data-type='method'><a href="FluroContent.html#.thread">thread</a></li><li data-type='method'><a href="FluroContent.html#.values">values</a></li></ul></li><li><a href="FluroCore.html">FluroCore</a></li><li><a href="FluroDate.html">FluroDate</a><ul class='methods'><li data-type='method'><a href="FluroDate.html#.dateFromID">dateFromID</a></li><li data-type='method'><a href="FluroDate.html#.formatDate">formatDate</a></li><li data-type='method'><a href="FluroDate.html#.isMultiDayEvent">isMultiDayEvent</a></li><li data-type='method'><a href="FluroDate.html#.localDate">localDate</a></li><li data-type='method'><a href="FluroDate.html#.readableEventDate">readableEventDate</a></li><li data-type='method'><a href="FluroDate.html#.readableEventTime">readableEventTime</a></li><li data-type='method'><a href="FluroDate.html#.timeago">timeago</a></li><li data-type='method'><a href="FluroDate.html#.timezones">timezones</a></li></ul></li><li><a href="FluroTypes.html">FluroTypes</a><ul class='methods'><li data-type='method'><a href="FluroTypes.html#.all">all</a></li><li data-type='method'><a href="FluroTypes.html#.get">get</a></li><li data-type='method'><a href="FluroTypes.html#.readable">readable</a></li><li data-type='method'><a href="FluroTypes.html#.reloadTerminology">reloadTerminology</a></li><li data-type='method'><a href="FluroTypes.html#.retrieve">retrieve</a></li></ul></li><li><a href="FluroUtils.html">FluroUtils</a><ul class='methods'><li data-type='method'><a href="FluroUtils.html#.arrayIDs">arrayIDs</a></li><li data-type='method'><a href="FluroUtils.html#.comma">comma</a></li><li data-type='method'><a href="FluroUtils.html#.errorMessage">errorMessage</a></li><li data-type='method'><a href="FluroUtils.html#.getDefaultValueForField">getDefaultValueForField</a></li><li data-type='method'><a href="FluroUtils.html#.getStringID">getStringID</a></li><li data-type='method'><a href="FluroUtils.html#.guid">guid</a></li><li data-type='method'><a href="FluroUtils.html#.hash">hash</a></li><li data-type='method'><a href="FluroUtils.html#.mapParameters">mapParameters</a></li><li data-type='method'><a href="FluroUtils.html#.matchInArray">matchInArray</a></li></ul></li></ul> </nav> <div id="main"> <h1 class="page-title">fluro.auth.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>import axios from 'axios'; import _ from 'lodash'; import { EventDispatcher } from './fluro.utils'; /////////////////////////////////////////////////// /** * Creates a new FluroAsset instance. * This module provides a number of helper functions for authentication, logging in, signing up, generating and refreshing tokens * * @constructor * @param {FluroCore} fluro A reference to the parent instance of the FluroCore module. This module is usually created by a FluroCore instance that passes itself in as the first argument. */ var FluroAuth = function(fluro) { if (!fluro.api) { throw new Error(`Can't Instantiate FluroAuth before FluroAPI exists`); } //Keep track of any refresh requests var inflightRefreshRequest; /////////////////////////////////////////////////// var defaultStore = {}; var store = defaultStore; /////////////////////////////////////////////////// /////////////////////////////////////////////////// var service = {} //Create a new dispatcher var dispatcher = new EventDispatcher(); dispatcher.bootstrap(service); // console.log('New Dispatcher!', dispatcher) /////////////////////////////////////////////////// /////////////////////////////////////////////////// function dispatch() { //Get the current user var user = store.user; //Dispatch the change to the listeners if (service.onChange) { service.onChange(user); } //Dispatch the change event dispatcher.dispatch('change', user); } /////////////////////////////////////////////////// function log(message) { if (service.debug) { console.log(message); } } /////////////////////////////////////////////////// /** * * Sets the current user data, often from localStorage or after new session data * has been generated from the server after signing in * @alias FluroAuth.set * @param {Object} user The user session object * @example * FluroAsset.set({firstName:'Jeff', lastName:'Andrews', ...}) */ service.set = function(user) { store.user = user; log('fluro.auth > user set'); return dispatch() } /////////////////////////////////////////////////// /** * * Deletes the user session object, clears all Fluro caches and tokens * from memory * @alias FluroAuth.logout * @example * FluroAuth.logout() */ service.logout = function() { //Unauthenticated // delete store.token; delete store.user; fluro.cache.reset(); // delete store.refreshToken; // delete store.expires; log('fluro.auth > user logout'); return dispatch() } /////////////////////////////////////////////////// /** * * Retrieves a new session object for a Fluro global user for a specified account * This will only work if the user has a persona in that account * @alias FluroAuth.changeAccount * @param {String} accountID The _id of the account you wish to log in to * @param {Object} options * @param {Object} options.disableAutoAuthenticate By default this function will set the current user session * to account you are changing in to. * If you want to generate the session without affecting your current session you can set disableAutoAuthenticate to true * @return {Promise} Resolves to the user session object, or rejects with the responding error * @example * FluroAuth.changeAccount('5be504eabf33991239599d63').then(function(userSession) { * //New user session will be set automatically * var newUserSession = FluroAuth.getCurrentUser(); * }) * FluroAuth.changeAccount('5be504eabf33991239599d63', {disableAutoAuthenticate:true}).then(function(userSession) { * //Set the session manually * FluroAuth.set(userSession) * }) */ service.changeAccount = function(accountID, options) { //Ensure we just have the ID accountID = fluro.utils.getStringID(accountID); ////////////////////////// if (!options) { options = {}; } ////////////////////////// //Change the users current tokens straight away var autoAuthenticate = true; if (options.disableAutoAuthenticate) { autoAuthenticate = false; } ////////////////////////// var promise = fluro.api.post(`/token/account/${accountID}`) promise.then(function(res) { if (autoAuthenticate) { fluro.cache.reset(); service.set(res.data); } }, function(err) {}); return promise; } /////////////////////////////////////////////////// /** * Logs the user in to Fluro and returns a new user session * @alias FluroAuth.login * @param {Object} credentials * @param {String} credentials.username The email address of the user to login as * @param {String} credentials.password The password for the user * @param {Object} options Extra options and configuration for the request * @param {Object} options.disableAutoAuthenticate Disable automatic authentication, if true, will not set the current user session * @param {Object} options.application Whether to attempt to login to the current application as a managed user persona, if not set will login as a global Fluro user * @return {Promise} Returns a promise that either resolves with the logged in user session, or rejects with the responding error from the server */ service.login = function(credentials, options) { if (!options) { options = {}; } ////////////////////////// //Change the users current tokens straight away var autoAuthenticate = true; if (options.disableAutoAuthenticate) { autoAuthenticate = false; } ////////////////////////////////////// var promise = new Promise(loginCheck) function loginCheck(resolve, reject) { if (!credentials) { return reject({ message: 'Missing credentials!', }) } if (!credentials.username || !credentials.username.length) { return reject({ message: 'Username was not provided', }) } if (!credentials.password || !credentials.password.length) { return reject({ message: 'Password was not provided', }) } ///////////////////////////////////////////// var postOptions = { bypassInterceptor: true } ///////////////////////////////////////////// var url = fluro.apiURL + '/token/login'; ///////////////////////////////////////////// //If we are authenticating as an application if (options.application) { //The url is relative to the domain url = `${fluro.domain || ''}/fluro/application/login`; } ///////////////////////////////////////////// //If we are logging in to a managed account use a different endpoint if (options.managedAccount) { url = fluro.apiURL + '/managed/' + options.managedAccount + '/login'; } //If we have a specified url if (options.url) { url = options.url; } ///////////////////////////////////////////// fluro.api.post(url, credentials, postOptions).then(function(res) { if (autoAuthenticate) { store.user = res.data; dispatch(); // if (service.onChange) { // service.onChange(store.user); // } } resolve(res); }, reject); } ////////////////////////////////////// return promise; } /////////////////////////////////////////////////// /** * Signs up a new user to the current application, this will create a new managed user persona * and automatically log in as that persona in the current application context. This function will * only work when called in context of an application with the 'Application Token' authentication style. * It will create a new user persona in the account of the application and return a session with all of the application's * permissions and application's logged in user permissions * @alias FluroAuth.signup * @param {Object} credentials * @param {String} credentials.firstName The first name for the new user persona * @param {String} credentials.lastName The last name for the new user persona * @param {String} credentials.username The email address for the new persona * @param {String} credentials.password The password to set for the new persona * @param {String} credentials.confirmPassword A double check to confirm the new password for the persona * @param {Object} options Extra options and configuration for the request * @return {Promise} Returns a promise that either resolves to the new authenticated session, or rejects with the responding error from the server */ service.signup = function(credentials, options) { if (!options) { options = {}; } ////////////////////////// //Change the users current tokens straight away var autoAuthenticate = true; if (options.disableAutoAuthenticate) { autoAuthenticate = false; } ////////////////////////////////////// var promise = new Promise(signupCheck) function signupCheck(resolve, reject) { if (!credentials) { return reject({ message: 'No details provided', }) } if (!credentials.firstName || !credentials.firstName.length) { return reject({ message: 'First Name was not provided', }) } if (!credentials.lastName || !credentials.lastName.length) { return reject({ message: 'Last Name was not provided', }) } if (!credentials.username || !credentials.username.length) { return reject({ message: 'Email/Username was not provided', }) } if (!credentials.password || !credentials.password.length) { return reject({ message: 'Password was not provided', }) } if (!credentials.confirmPassword || !credentials.confirmPassword.length) { return reject({ message: 'Confirm Password was not provided', }) } if (credentials.confirmPassword != credentials.password) { return reject({ message: 'Your passwords do not match', }) } ///////////////////////////////////////////// var postOptions = { bypassInterceptor: true } ///////////////////////////////////////////// var url = fluro.apiURL + '/token/signup'; ///////////////////////////////////////////// //If we are authenticating as an application if (options.application) { //The url is relative to the domain url = `${fluro.domain || ''}/fluro/application/signup`; } //If we have a specified url if (options.url) { url = options.url; } ///////////////////////////////////////////// fluro.api.post(url, credentials, postOptions).then(function(res) { if (autoAuthenticate) { store.user = res.data; dispatch(); } resolve(res); }, reject); } ////////////////////////////////////// return promise; } /////////////////////////////////////////////////// /** * Retrieves a user's details by providing a password reset token * @alias FluroAuth.retrieveUserFromResetToken * @param {String} token The password reset token that was sent to the user's email address * @param {Object} options other options for the request * @param {Boolean} options.application If true will retrieve in the context of a managed persona in the same account as the current application. * If not specified or false, will assume it's a Fluro global user that is resetting their password. * @return {Promise} Returns a promise that resolves with the reset session details */ service.retrieveUserFromResetToken = function(token, options) { if (!options) { options = {}; } ////////////////////////////////////// return new Promise(function(resolve, reject) { var postOptions = { bypassInterceptor: true } ///////////////////////////////////////////// //If a full fledged Fluro User //then send directly to the API auth endpoint var url = `${fluro.apiURL}/auth/token/${token}`; ///////////////////////////////////////////// //If we are authenticating as an application if (options.application) { //The url is relative to the domain url = `${fluro.domain || ''}/fluro/application/reset/${token}`; } //If we have a specified url if (options.url) { url = options.url; } ///////////////////////////////////////////// fluro.api.get(url, postOptions).then(function(res) { return resolve(res.data); }, reject); }); } /////////////////////////////////////////////////// /** * Updates a user's details including password by providing a password reset token * @alias FluroAuth.updateUserWithToken * @param {String} token The password reset token that was sent to the user's email address * @param {Object} body The details to change for the user * @param {Object} options other options for the request * @return {Promise} Returns a promise that resolves with the reset session details */ service.updateUserWithToken = function(token, body, options) { if (!options) { options = {}; } ////////////////////////// //Change the users current tokens straight away var autoAuthenticate = true; if (options.disableAutoAuthenticate) { autoAuthenticate = false; } ////////////////////////////////////// return new Promise(function(resolve, reject) { var postOptions = { bypassInterceptor: true } ///////////////////////////////////////////// //If a full fledged Fluro User //then send directly to the API auth endpoint var url = `${fluro.apiURL}/auth/token/${token}`; ///////////////////////////////////////////// //If we are authenticating as an application if (options.application) { //The url is relative to the domain url = `${fluro.domain || ''}/fluro/application/reset/${token}`; } //If we have a specified url if (options.url) { url = options.url; } ///////////////////////////////////////////// fluro.api.post(url, body, postOptions).then(function(res) { //If we should automatically authenticate //once the request is successful //Then clear caches and update the session if (autoAuthenticate) { fluro.cache.reset(); service.set(res.data); } return resolve(res.data); }, reject); }); } /////////////////////////////////////////////////// /** * Triggers a new Reset Password email request to the specified user. * @alias FluroAuth.sendResetPasswordRequest * @param {Object} body * @param {String} body.username The email address of the user to reset the password for * @param {String} body.redirect If the request is in the context of a managed user persona authenticated with an application, then you need to provide the url to direct the user to when they click the reset password link * This is usually something like '/reset' for the current application, when the user clicks the link the reset token will be appended with ?token=RESET_TOKEN and your application should * be ready on that url to handle the token and allow the user to use the token to reset their password * @param {Object} options Extra options and configuration for the request * @param {Boolean} options.application If true will send a reset email from the context of a managed persona in the same account as the current application. * If not specified or false, will send a password reset request for a global Fluro user account. * @return {Promise} Returns a promise that either resolves if the password request was sent, or rejects if an error occurred */ service.sendResetPasswordRequest = function(body, options) { if (!options) { options = {}; } ////////////////////////////////////// var promise = new Promise(signupCheck) function signupCheck(resolve, reject) { if (!body) { return reject({ message: 'No details provided', }) } if (!body.username || !body.username.length) { return reject({ message: 'Email/Username was not provided', }) } //Set username as the email address body.email = body.username; ///////////////////////////////////////////// var postOptions = { bypassInterceptor: true } ///////////////////////////////////////////// //If a full fledged Fluro User //then send directly to the API var url = fluro.apiURL + '/resend'; ///////////////////////////////////////////// //If we are authenticating as an application if (options.application) { //The url is relative to the domain url = `${fluro.domain || ''}/fluro/application/forgot`; } //If we have a specified url if (options.url) { url = options.url; } ///////////////////////////////////////////// fluro.api.post(url, body, postOptions).then(resolve, reject); } ////////////////////////////////////// return promise; } /////////////////////////////////////////////////// var refreshContext = {}; /** * Helper function to refresh an access token for an authenticated user session. This is usually handled automatically * from the FluroAuth service itself * @alias FluroAuth.refreshAccessToken * @param {String} refreshToken The refresh token to reactivate * @param {Boolean} isManagedSession Whether or not the refresh token is for a managed persona session or a global Fluro user session * @return {Promise} A promise that either resolves with the refreshed token details or rejects with the responding error from the server */ service.refreshAccessToken = function(refreshToken, isManagedSession) { //If there is already a request in progress if (refreshContext.inflightRefreshRequest) { //console.log('Use inflight request', refreshContext.inflightRefreshRequest); return refreshContext.inflightRefreshRequest; } ///////////////////////////////////////////////////// //Create an refresh request refreshContext.inflightRefreshRequest = new Promise(function(resolve, reject) { log(`fluro.auth > refresh token ${refreshToken}`); //Bypass the interceptor on all token refresh calls //Because we don't need to add the access token etc onto it fluro.api.post('token/refresh', { refreshToken: refreshToken, managed: isManagedSession, }, { bypassInterceptor: true }) .then(function tokenRefreshComplete(res) { //Update the user with any changes //returned back from the refresh request if (!res) { log('fluro.auth > no res'); refreshContext.inflightRefreshRequest = null; return reject(); } else { if (store.user) { Object.assign(store.user, res.data); } else { store.user = res.data; } log('fluro.auth > token refreshed'); // if (service.onChange) { // service.onChange(store.user); // } dispatch(); // } } //Resolve with the new token resolve(res.data.token); //Remove the inflight request refreshContext.inflightRefreshRequest = null; }, function(err) { //console.log('Refresh request Failed') refreshContext.inflightRefreshRequest = null; reject(err); }); }); //Return the refresh request return refreshContext.inflightRefreshRequest; } /////////////////////////////////////////////////// /** * Helper function to resync the user's session from the server. This is often used when first loading a webpage or app * just to see if the user's permissions have changed since the user first logged in * from the FluroAuth service itself * @alias FluroAuth.sync * @return {Promise} A promise that either resolves with the user session */ service.sync = function() { return fluro.api.get('/session') .then(function(res) { if (res.data) { //Update the user with any changes //returned back from the refresh request if (store.user) { Object.assign(store.user, res.data); } } else { store.user = null; } log('fluro.auth > server session refreshed'); dispatch(); }); } ///////////////////////////////////////////////////// /** * Returns the current user's access token * @alias FluroAuth.getCurrentToken * @return {String} The Fluro access token for the current user session */ service.getCurrentToken = function() { return _.get(store, 'user.token') || fluro.applicationToken; } ///////////////////////////////////////////////////// /** * Returns the current user's session data * @alias FluroAuth.getCurrentUser * @return {Object} The current user session */ service.getCurrentUser = function() { return _.get(store, 'user'); } ///////////////////////////////////////////////////// fluro.api.interceptors.request.use(function(config) { //If we want to bypass the interceptor //then just return the request if (config.bypassInterceptor) { return config; } ////////////////////////////// //Get the original request var originalRequest = config; //If we aren't logged in or don't have a token var token = _.get(store, 'user.token'); var refreshToken = _.get(store, 'user.refreshToken'); ////////////////////////////// //If there is a user token if (token) { //Set the token of the request as the user's access token originalRequest.headers['Authorization'] = 'Bearer ' + token; log('fluro.auth > using user token'); } else if (fluro.applicationToken &amp;&amp; fluro.applicationToken.length) { //If there is a static application token //For example we have logged out from a website //that has public content also originalRequest.headers['Authorization'] = 'Bearer ' + fluro.applicationToken; log('fluro.auth > using app token'); return originalRequest; } else { //Return the original request without a token log('fluro.auth > no token'); return originalRequest; } ///////////////////////////////////////////////////// //If no refresh token if (!refreshToken) { log('fluro.auth > no refresh token'); //Continue with the original request return originalRequest; } ///////////////////////////////////////////////////// //We have a refresh token so we need to check //whether our access token is stale and needs to be refreshed var now = new Date(); //Give us a bit of buffer incase some of our images //are still loading now.setSeconds(now.getSeconds() + 10); var expiryDate = _.get(store, 'user.expires'); var expires = new Date(expiryDate); //If we are not debugging if (!service.debug) { //If the token is still fresh if (now &lt; expires) { //Return the original request return originalRequest; } } ///////////////////////////////////////////////////// var isManagedUser = _.get(store, 'user.accountType') == 'managed'; //The token is stale by this point log('fluro.auth > token expired'); return new Promise(function(resolve, reject) { //Refresh the token service.refreshAccessToken(refreshToken, isManagedUser) .then(function(newToken) { log('fluro.auth > token refreshed', isManagedUser); //Update the original request with our new token originalRequest.headers['Authorization'] = 'Bearer ' + newToken; //And continue onward return resolve(originalRequest); }, function(err) { log('fluro.auth > token refresh rejected', err); return reject(err); }); }); }, function(error) { return Promise.reject(error); }) ///////////////////////////////////////////////////// fluro.api.interceptors.response.use(function(response) { return response; }, function(err) { //Get the response status var status = _.get(err, 'response.status') || err.status; log('fluro.auth > error', status); switch (status) { case 401: //If it's an invalid refresh token //In case it was a mismatch between tabs or sessions //we should try it a second time just in case var data = _.get(err, 'response.data'); if(data == 'invalid_refresh_token') { //Try it again // console.log('Refresh failed but its ok') } else { //Logout and destroy the session service.logout(); } break; default: //Some other error break; } ///////////////////////////////////////////////////// return Promise.reject(err); }) /** * @name FluroAuth.addEventListener * @description Adds a callback that will be triggered whenever the specified event occurs * @function * @param {String} event The event to listen for * @param {Function} callback The function to fire when this event is triggered * @example * //Listen for when the user session changes * FluroAuth.addEventListener('change', function(userSession) {}) */ /** * @name FluroAuth.removeEventListener * @description Removes all a callback from the listener list * @function * @param {String} event The event to stop listening for * @param {Function} callback The function to remove from the listener list * @example * //Stop listening for the change event * FluroAuth.removeEventListener('change', myFunction) */ /** * @name FluroAuth.removeAllListeners * @description Removes all listening callbacks for all events * @function * @example * FluroAuth.removeAllListeners() */ return service; } export default FluroAuth;</code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Sep 05 2019 21:42:53 GMT+1000 (Australian Eastern Standard Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/polyfill.js"></script> <script src="scripts/linenumber.js"></script> </body> </html>