mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-28 05:14:12 +03:00
ae759d39ea
no issue - disabled Ember Simple Auth's default token revocation - we trigger session invalidation on a 401 which means our token isn't valid so the revoke requests will also fail - renamed application route's `invalidateSession` to `logout` in order to distinguish it from any ESA methods - added the token revocation requests to this action, we can be fairly sure at this point that the current tokens will be valid so the requests will succeed - added check to `ajax.handleResponse` so that we don't invalidate the session for requests to external services - removed pointless assertion from the ajax integration test
92 lines
3.3 KiB
JavaScript
92 lines
3.3 KiB
JavaScript
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);
|
|
});
|
|
});
|
|
}
|
|
});
|