Skip to content

Commit

Permalink
Merge pull request #299 from fenichelar/master
Browse files Browse the repository at this point in the history
Natively get environment config to remove ember-get-config dependency
  • Loading branch information
fenichelar authored Mar 9, 2021
2 parents 12a45fc + cc8c02d commit e6b23e0
Show file tree
Hide file tree
Showing 7 changed files with 16,775 additions and 64 deletions.
42 changes: 37 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ export default Controller.extend({
const credentials = this.getProperties('username', 'password');
const authenticator = 'authenticator:token'; // or 'authenticator:jwt'

this.get('session').authenticate(authenticator, credentials);
this.session.authenticate(authenticator, credentials);
}
}
});
```

#### JSON Web Token Authenticator

The JSON Web Token authenticator will decode the token and look for the expiration time found. The difference in the current time and the token expiration time is calculated. The `refreshLeeway` is subtracted from this value to determine when the automatic token refresh request should be made.
The JSON Web Token authenticator will decode the token and look for the expiration time. The difference in the current time and the token expiration time is calculated. The `refreshLeeway` is subtracted from this value to determine when the automatic token refresh request should be made.

```js
// config/environment.js
Expand Down Expand Up @@ -99,9 +99,41 @@ To debug JSON Web Token issues, see [jwt][jwt].

The JSON Web Token authenticator supports both separate access tokens and refresh tokens. By specifying the `tokenPropertyName` and the `refreshTokenPropertyName` to the same value, the same token will be used for both access and refresh requests. For more information about refresh tokens, see [this blog][blog-refresh-token].

#### Adapter

In order to send the token with all API requests made to the server, set the headers object in the adapter:

```js
// app/adapters/application.js
import DS from 'ember-data';
import { inject } from '@ember/service';
import { computed } from '@ember/object';

export default DS.JSONAPIAdapter.extend({
session: inject('session'),

headers: computed('session.isAuthenticated', 'session.data.authenticated.token', function() {
if (this.session.isAuthenticated) {
return {
Authorization: `Bearer ${this.session.data.authenticated.token}`,
};
} else {
return {};
}
}),

handleResponse(status) {
if (status === 401 && this.session.isAuthenticated) {
this.session.invalidate();
}
return this._super(...arguments);
},
});
```

### Mixins

In order to send the token with all API requests made to the server, the `token-adapter` mixin or `token-authorizer` mixin should be used. When using `ember-simple-auth` >= 3.0.0, use the `token-adapter` mixin. When using `ember-simple-auth` < 3.0.0, use the `token-authorizer` mixin. The mixin will add the header to each API request:
Although no longer recommended, the `token-adapter` mixin or `token-authorizer` mixin can be used in order to send the token with all API requests made to the server. When using `ember-simple-auth` >= 3.0.0, use the `token-adapter` mixin. When using `ember-simple-auth` < 3.0.0, use the `token-authorizer` mixin. The mixin will add the header to each API request:

```
Authorization: Bearer <token>
Expand Down Expand Up @@ -136,7 +168,7 @@ export default DS.JSONAPIAdapter.extend(TokenAuthorizerMixin);
ENV['ember-simple-auth-token'] = {
serverTokenEndpoint: '/api/token-auth/', // Server endpoint to send authenticate request
tokenPropertyName: 'token', // Key in server response that contains the access token
headers: {} // Headers to add to the
headers: {} // Headers to add to the authenticate request
};
```

Expand All @@ -157,7 +189,7 @@ ENV['ember-simple-auth-token'] = {
};
```

#### Token Authenticator
#### Mixins

In addition to `tokenPropertyName` from the authenticator:

Expand Down
20 changes: 11 additions & 9 deletions addon/authenticators/jwt.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* global FastBoot */

import EmberObject, { get } from '@ember/object';
import { getOwner } from '@ember/application';
import { assign } from '@ember/polyfills';
import { Promise, resolve } from 'rsvp';
import { isEmpty } from '@ember/utils';
import { cancel, later } from '@ember/runloop';
import TokenAuthenticator from './token';
import config from 'ember-get-config';

const decode = str => {
if (typeof atob === 'function') {
Expand Down Expand Up @@ -41,14 +41,16 @@ export default TokenAuthenticator.extend({
*/
init() {
this._super(...arguments);
const conf = config['ember-simple-auth-token'] || {};
this.tokenDataPropertyName = conf.tokenDataPropertyName || 'tokenData';
this.refreshAccessTokens = conf.refreshAccessTokens === false ? false : true;
this.tokenExpirationInvalidateSession = conf.tokenExpirationInvalidateSession === false ? false : true;
this.serverTokenRefreshEndpoint = conf.serverTokenRefreshEndpoint || '/api/token-refresh/';
this.refreshTokenPropertyName = conf.refreshTokenPropertyName || 'refresh_token';
this.tokenExpireName = conf.tokenExpireName || 'exp';
this.refreshLeeway = conf.refreshLeeway || 0;
const owner = getOwner(this);
const environment = owner ? owner.resolveRegistration('config:environment') || {} : {};
const config = environment['ember-simple-auth-token'] || {};
this.tokenDataPropertyName = config.tokenDataPropertyName || 'tokenData';
this.refreshAccessTokens = config.refreshAccessTokens === false ? false : true;
this.tokenExpirationInvalidateSession = config.tokenExpirationInvalidateSession === false ? false : true;
this.serverTokenRefreshEndpoint = config.serverTokenRefreshEndpoint || '/api/token-refresh/';
this.refreshTokenPropertyName = config.refreshTokenPropertyName || 'refresh_token';
this.tokenExpireName = config.tokenExpireName || 'exp';
this.refreshLeeway = config.refreshLeeway || 0;
},

/**
Expand Down
12 changes: 7 additions & 5 deletions addon/authenticators/token.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import EmberObject from '@ember/object';
import { getOwner } from '@ember/application';
import fetch from 'fetch';
import { assign } from '@ember/polyfills';
import { Promise, reject, resolve } from 'rsvp';
import { isEmpty } from '@ember/utils';
import Base from 'ember-simple-auth/authenticators/base';
import config from 'ember-get-config';

/**
Authenticator that works with token-based authentication like JWT.
Expand All @@ -22,10 +22,12 @@ export default Base.extend({
*/
init() {
this._super(...arguments);
const conf = config['ember-simple-auth-token'] || {};
this.serverTokenEndpoint = conf.serverTokenEndpoint || '/api/token-auth/';
this.tokenPropertyName = conf.tokenPropertyName || 'token';
this.headers = conf.headers || {};
const owner = getOwner(this);
const environment = owner ? owner.resolveRegistration('config:environment') || {} : {};
const config = environment['ember-simple-auth-token'] || {};
this.serverTokenEndpoint = config.serverTokenEndpoint || '/api/token-auth/';
this.tokenPropertyName = config.tokenPropertyName || 'token';
this.headers = config.headers || {};
},

/**
Expand Down
32 changes: 23 additions & 9 deletions addon/mixins/token-adapter.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import Mixin from '@ember/object/mixin';
import { getOwner } from '@ember/application';
import { inject } from '@ember/service';
import { get, computed } from '@ember/object';
import { isEmpty } from '@ember/utils';
import config from 'ember-get-config';
import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';

/**
Adapter Mixin that works with token-based authentication like JWT.
Expand All @@ -12,22 +11,24 @@ import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';
@module ember-simple-auth-token/mixins/token-adapter
@extends Ember.Mixin
*/
export default Mixin.create(DataAdapterMixin, {
export default Mixin.create({
session: inject('session'),

/**
@method init
*/
init() {
this._super(...arguments);
const conf = config['ember-simple-auth-token'] || {};
this.tokenPropertyName = conf.tokenPropertyName || 'token';
this.authorizationHeaderName = conf.authorizationHeaderName || 'Authorization';
this.authorizationPrefix = conf.authorizationPrefix === '' ? '' : conf.authorizationPrefix || 'Bearer ';
const owner = getOwner(this);
const environment = owner ? owner.resolveRegistration('config:environment') || {} : {};
const config = environment['ember-simple-auth-token'] || {};
this.tokenPropertyName = config.tokenPropertyName || 'token';
this.authorizationHeaderName = config.authorizationHeaderName || 'Authorization';
this.authorizationPrefix = config.authorizationPrefix === '' ? '' : config.authorizationPrefix || 'Bearer ';
},

/*
Adds the `token` property from the session to the `authorizationHeaderName`:
Adds the `token` property from the session to the `authorizationHeaderName`.
*/
headers: computed('session.data.authenticated', function() {
const data = this.get('session.data.authenticated');
Expand All @@ -42,5 +43,18 @@ export default Mixin.create(DataAdapterMixin, {
} else {
return {};
}
})
}),

/**
Handles response from server.
@method authorize
@param {Number} status
*/
handleResponse(status) {
if (status === 401 && this.get('session.isAuthenticated')) {
this.get('session').invalidate();
}
return this._super(...arguments);
}
});
28 changes: 21 additions & 7 deletions addon/mixins/token-authorizer.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import Mixin from '@ember/object/mixin';
import { getOwner } from '@ember/application';
import { inject } from '@ember/service';
import { get } from '@ember/object';
import { isEmpty } from '@ember/utils';
import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';
import config from 'ember-get-config';

/**
Authorizer Mixin that works with token-based authentication like JWT by sending the `token` properties from the session in the `Authorization` header.
Expand All @@ -12,18 +11,20 @@ import config from 'ember-get-config';
@module ember-simple-auth-token/mixins/token-authorizer
@extends Ember.Mixin
*/
export default Mixin.create(DataAdapterMixin, {
export default Mixin.create({
session: inject('session'),

/**
@method init
*/
init() {
this._super(...arguments);
const conf = config['ember-simple-auth-token'] || {};
this.tokenPropertyName = conf.tokenPropertyName || 'token';
this.authorizationHeaderName = conf.authorizationHeaderName || 'Authorization';
this.authorizationPrefix = conf.authorizationPrefix === '' ? '' : conf.authorizationPrefix || 'Bearer ';
const owner = getOwner(this);
const environment = owner ? owner.resolveRegistration('config:environment') || {} : {};
const config = environment['ember-simple-auth-token'] || {};
this.tokenPropertyName = config.tokenPropertyName || 'token';
this.authorizationHeaderName = config.authorizationHeaderName || 'Authorization';
this.authorizationPrefix = config.authorizationPrefix === '' ? '' : config.authorizationPrefix || 'Bearer ';
},

/**
Expand All @@ -45,5 +46,18 @@ export default Mixin.create(DataAdapterMixin, {
if (this.get('session.isAuthenticated') && !isEmpty(token)) {
xhr.setRequestHeader(header, prefix + token);
}
},

/**
Handles response from server.
@method authorize
@param {Number} status
*/
handleResponse(status) {
if (status === 401 && this.get('session.isAuthenticated')) {
this.get('session').invalidate();
}
return this._super(...arguments);
}
});
Loading

0 comments on commit e6b23e0

Please sign in to comment.