import Authenticator from 'ember-simple-auth/authenticators/oauth2-password-grant'; import RSVP from 'rsvp'; import {assign} from '@ember/polyfills'; import {computed} from '@ember/object'; import {isEmpty} from '@ember/utils'; import {run} from '@ember/runloop'; import {inject as service} from '@ember/service'; import {makeArray as wrap} from '@ember/array'; export default Authenticator.extend({ ajax: service(), session: service(), config: service(), ghostPaths: service(), init() { this._super(...arguments); let handler = run.bind(this, () => { this.onOnline(); }); window.addEventListener('online', handler); }, serverTokenEndpoint: computed('ghostPaths.apiRoot', function () { return `${this.get('ghostPaths.apiRoot')}/authentication/token`; }), // disable general token revocation because the requests will always 401 // (revocation is triggered by invalid access token so it's already invalid) // we have a separate logout procedure that sends revocation requests serverTokenRevocationEndpoint: null, makeRequest(url, data) { /* eslint-disable camelcase */ data.client_id = this.get('config.clientId'); data.client_secret = this.get('config.clientSecret'); /* eslint-enable camelcase */ let options = { data, dataType: 'json', contentType: 'application/x-www-form-urlencoded' }; return this.get('ajax').post(url, options); }, /** * Invoked when "navigator.online" event is trigerred. * This is a helper function to handle intermittent internet connectivity. Token is refreshed * when browser status becomes "online". */ onOnline() { if (this.get('session.isAuthenticated')) { let autoRefresh = this.get('refreshAccessTokens'); if (autoRefresh) { let expiresIn = this.get('session.data.authenticated.expires_in'); let token = this.get('session.data.authenticated.refresh_token'); return this._refreshAccessToken(expiresIn, token); } } }, authenticate(identification, password, scope = [], headers = {}) { return new RSVP.Promise((resolve, reject) => { let data = {grant_type: 'password', username: identification, password}; let serverTokenEndpoint = this.get('serverTokenEndpoint'); let scopesString = wrap(scope).join(' '); if (!isEmpty(scopesString)) { data.scope = scopesString; } this.makeRequest(serverTokenEndpoint, data, headers).then((response) => { run(() => { /* eslint-disable camelcase */ let expiresAt = this._absolutizeExpirationTime(response.expires_in); this._scheduleAccessTokenRefresh(response.expires_in, expiresAt, response.refresh_token); /* eslint-enable camelcase */ if (!isEmpty(expiresAt)) { response = assign(response, {expires_at: expiresAt}); } resolve(response); }); }, (error) => { reject(error); }); }); } });