Skip to content
This repository has been archived by the owner on Oct 24, 2024. It is now read-only.

Commit

Permalink
fix[react]: staled token state (#826)
Browse files Browse the repository at this point in the history
* fix[react]: staled token state

* test: add test for authService.on

Co-authored-by: Vijet M <[email protected]>
  • Loading branch information
shuowu and vijetmahabaleshwar-okta authored Jul 16, 2020
1 parent 63f3b37 commit ba8a5b9
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 28 deletions.
6 changes: 6 additions & 0 deletions packages/okta-react/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 3.0.3

### Bug Fixes

- [#826](https://github.com/okta/okta-oidc-js/pull/826) Fix stale `authState` in React context by listening on `expired` event from `authJs.tokenManager`, then update the `authState` in context properly.

# 3.0.2

### Bug Fixes
Expand Down
4 changes: 3 additions & 1 deletion packages/okta-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"start": "yarn --cwd test/e2e/harness start",
"test": "yarn lint && yarn test:unit && yarn test:e2e",
"test:e2e": "yarn --cwd test/e2e/harness test",
"test:unit": "jest"
"test:unit": "jest",
"dev": "babel src -wd dist"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -68,6 +69,7 @@
"react-router-dom": "^5.1.0",
"rimraf": "^2.6.2",
"styled-components": "^2.1.2",
"tiny-emitter": "^2.1.0",
"webdriver-manager": "^12.1.4"
},
"resolutions": {
Expand Down
20 changes: 9 additions & 11 deletions packages/okta-react/src/AuthService.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class AuthService {
this._oktaAuth = new OktaAuth(authConfig);
this._oktaAuth.userAgent = `${packageInfo.name}/${packageInfo.version} ${this._oktaAuth.userAgent}`;
this._config = authConfig; // use normalized config
this._listeners = {};
this._pending = {}; // manage overlapping async calls

this.handleAuthentication = this.handleAuthentication.bind(this);
Expand All @@ -59,9 +58,11 @@ class AuthService {
this.emit = this.emit.bind(this);
this.on = this.on.bind(this);

this._subscriberCount = 0;

this.clearAuthState();

// Remove expired token or renew token if autoRenew is true
// This process will keep authState synced with states in tokenManager
this.on('expired', this.updateAuthState);
}

getTokenManager() {
Expand Down Expand Up @@ -256,17 +257,14 @@ class AuthService {
}

on( event, callback ) {
const subscriberId = this._subscriberCount++;
this._listeners[event] = this._listeners[event] || {};
this._listeners[event][subscriberId] = callback;
return () => {
delete this._listeners[event][subscriberId];
}
this._oktaAuth.emitter.on(event, callback, this._oktaAuth.emitter);
return () => {
this._oktaAuth.emitter.off(event, callback);
};
}

emit(event, message ) {
this._listeners[event] = this._listeners[event] || {};
Object.values(this._listeners[event]).forEach( listener => listener(message) );
this._oktaAuth.emitter.emit(event, message);
}

}
Expand Down
51 changes: 35 additions & 16 deletions packages/okta-react/test/jest/authService.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import AuthService from '../../src/AuthService';
import AuthJS from '@okta/okta-auth-js'
import Emitter from 'tiny-emitter';

const pkg = require('../../package.json');

jest.mock('@okta/okta-auth-js');

describe('AuthService configuration', () => {
let mockAuthJsInstance;

beforeEach(() => {
mockAuthJsInstance = {
userAgent: 'okta-auth-js',
emitter: new Emitter()
};
AuthJS.mockImplementation(() => {
return mockAuthJsInstance
});
})

it('should throw if no issuer is provided', () => {
function createInstance () {
Expand Down Expand Up @@ -164,6 +176,7 @@ describe('AuthService', () => {
};
mockAuthJsInstance = {
userAgent: 'okta-auth-js',
emitter: new Emitter(),
tokenManager: {
add: jest.fn(),
get: jest.fn().mockImplementation(tokenName => {
Expand All @@ -174,7 +187,7 @@ describe('AuthService', () => {
} else {
throw new Error('Unknown token name: ' + tokenName);
}
}),
})
},
token: {
getWithRedirect: jest.fn(),
Expand Down Expand Up @@ -506,34 +519,40 @@ describe('AuthService', () => {

describe('AuthState tracking', () => {

it('has an authState of pending initially', async () => {
it('should call updateAuthState method when expired event happen', () => {
jest.spyOn(AuthService.prototype, 'updateAuthState');
const authService = new AuthService(validConfig);
authService.emit('expired');
expect(AuthService.prototype.updateAuthState).toHaveBeenCalled();
});

it('should trigger registered callback when "authStateChange" event triggered', () => {
expect.assertions(1);
const mockState = 'mock state';
const authService = new AuthService({
issuer: 'https://foo/oauth2/default',
clientId: 'foo',
redirectUri: 'https://foo/redirect',
});

expect(authService._authState).toEqual({
isPending: true,
isAuthenticated: null,
idToken: null,
accessToken: null,
authService.on('authStateChange', (state) => {
expect(state).toEqual(mockState);
});
authService.emit('authStateChange', mockState);
});

it('allows subscribing to an "authStateChange" event', async () => {
it('has an authState of pending initially', async () => {
const authService = new AuthService({
issuer: 'https://foo/oauth2/default',
clientId: 'foo',
redirectUri: 'https://foo/redirect',
});
const callback = jest.fn();

expect(Object.values(authService._listeners.authStateChange).length).toBe(0);
authService.on('authStateChange', callback);
expect(Object.values(authService._listeners.authStateChange).length).toBe(1);
authService.emit('authStateChange');
expect(callback).toHaveBeenCalled();

expect(authService._authState).toEqual({
isPending: true,
isAuthenticated: null,
idToken: null,
accessToken: null,
});
});

it('emits an "authStateChange" event when updateAuthState() is called', async () => {
Expand Down
5 changes: 5 additions & 0 deletions packages/okta-react/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5076,6 +5076,11 @@ [email protected]:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-1.1.0.tgz#ab405a21ffed814a76c19739648093d70654fecb"

tiny-emitter@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==

tiny-invariant@^1.0.2:
version "1.0.6"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73"
Expand Down

0 comments on commit ba8a5b9

Please sign in to comment.