Skip to content
This repository was archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
feat(authService): optional callback for isAuthenticated
Browse files Browse the repository at this point in the history
  • Loading branch information
doktordirk committed Nov 2, 2016
1 parent 8397cde commit fdbe4b5
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 36 deletions.
8 changes: 7 additions & 1 deletion doc/api_authService.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,18 @@ let currentToken = this.authService.getRefreshToken();

----------

### .isAuthenticated()
### .isAuthenticated(callback)

Checks if there is a (valid) token in storage. If the token is isExpired and BaseConfig.autoUpdateToken===true, it returns true and a new access token automatically requested using the refesh_token. If you use it in a getter, aurelia will dirty check on uodates. Hence, may better either use .authenticated or use the binding signal 'authentication-change' to ensure udpdates.

CAUTION: When you cancel or manually set the timeout, .isAuthenticated and .authenticated could yield different results.

#### Parameters

| Parameter | Type | Description |
| ---------- | -------------------------------- | -------------------------------------------------------- |
| [callback] | (authenticated: boolean) => void | optional callback executed once the status is determined |

#### Returns

`true`, for Non-JWT and unexpired JWT, `false` for no token or expired JWT
Expand Down
24 changes: 21 additions & 3 deletions src/authService.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,21 +279,39 @@ export class AuthService {
/**
* Gets authentication status from storage
*
* @param {[Function]} [callback] optional callback (authenticated: boolean) => void executed once the status is determined
*
* @returns {boolean} For Non-JWT and unexpired JWT: true, else: false
*/
isAuthenticated(): boolean {
isAuthenticated(callback?: (authenticated: boolean) => void): boolean {
this.authentication.responseAnalyzed = false;

let authenticated = this.authentication.isAuthenticated();

// auto-update token?
// auto-update token?
if (!authenticated
&& this.config.autoUpdateToken
&& this.authentication.getAccessToken()
&& this.authentication.getRefreshToken()
) {
this.updateToken().catch(error => logger.warn(error.message));
this.updateToken()
.then(() => {
// has new status now
if (typeof callback === 'function') {
callback(this.authenticated); // eslint-disable-line callback-return
}
})
.catch(error => logger.warn(error.message));

authenticated = true;
} else if (typeof callback === 'function') {
PLATFORM.global.setTimeout(() => {
try {
callback(authenticated); // eslint-disable-line callback-return
} catch(error) {
logger.warn(error.message);
}
}, 1);
}

return authenticated;
Expand Down
88 changes: 56 additions & 32 deletions test/authService.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ import {AuthService} from '../src/authService';
import {Authentication} from '../src/authentication';
import {AuthFilterValueConverter} from '../src/authFilterValueConverter';

const tokenPast = {
payload: {
name : 'tokenPast',
admin: false,
exp : '0460017154'
},
jwt: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidG9rZW5QYXN0IiwiYWRtaW4iOmZhbHNlLCJleHAiOiIwNDYwMDE3MTU0In0.Z7QE185hOWL6xxVDmlFpNEmgA-_Vg2bjV9uDRkkVaQY'
};

const tokenFuture = {
payload: {
name: 'tokenFuture',
name : 'tokenFuture',
admin: true,
exp: '2460017154'
exp : '2460017154'
},
jwt: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidG9rZW5GdXR1cmUiLCJhZG1pbiI6dHJ1ZSwiZXhwIjoiMjQ2MDAxNzE1NCJ9.iHXLzWGY5U9WwVT4IVRLuKTf65XpgrA1Qq_Jlynv6bc'
};
Expand All @@ -30,11 +39,11 @@ function getContainer() {
.setDefaultEndpoint('sx/default');

configure({container: container, globalResources: noop}, {
endpoint: '',
loginRedirect: false,
endpoint : '',
loginRedirect : false,
logoutRedirect: false,
signupRedirect: false,
baseUrl: 'http://localhost:1927/'
baseUrl : 'http://localhost:1927/'
});

return container;
Expand All @@ -43,11 +52,11 @@ function getContainer() {
let oidcProviderConfig = {
providers: {
oidcProvider: {
name: 'oidcProvider',
oauthType: '2.0',
name : 'oidcProvider',
oauthType : '2.0',
postLogoutRedirectUri: 'http://localhost:1927/',
logoutEndpoint: 'http://localhost:54540/connect/logout',
popupOptions: { width: 1028, height: 529 }
logoutEndpoint : 'http://localhost:54540/connect/logout',
popupOptions : {width: 1028, height: 529}
}
}
};
Expand Down Expand Up @@ -79,7 +88,6 @@ describe('AuthService', () => {
});
});


describe('.authenticated', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand All @@ -105,7 +113,6 @@ describe('AuthService', () => {
});
});


describe('.getMe()', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand Down Expand Up @@ -150,7 +157,6 @@ describe('AuthService', () => {
});
});


describe('.updateMe() with PUT', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand Down Expand Up @@ -204,7 +210,6 @@ describe('AuthService', () => {
});
});


describe('.updateMe() with PATCH', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand Down Expand Up @@ -258,7 +263,6 @@ describe('AuthService', () => {
});
});


describe('.setTimeout()', () => {
const container = new Container();
let authService = container.get(AuthService);
Expand All @@ -285,7 +289,7 @@ describe('AuthService', () => {
setTimeout(done, 10);
});

it('Should not have timeeout', () => {
it('Should not have timeout', () => {
expect(authService.timeoutID).not.toBe(0);
});

Expand All @@ -304,7 +308,7 @@ describe('AuthService', () => {
};
let lookupFunctions = {
bindingBehaviors: name => bindingBehaviors[name],
valueConverters: name => valueConverters[name]
valueConverters : name => valueConverters[name]
};
let bindingSignaler = container.get(BindingSignaler);

Expand Down Expand Up @@ -343,7 +347,7 @@ describe('AuthService', () => {

// process signal from authService.setTimeout
expect(authService.timeoutID).not.toBe(0);
setTimeout( function() {
setTimeout(function() {
expect(authService.timeoutID).toBe(0);
expect(target.innerHTML).toBe('false');
done();
Expand Down Expand Up @@ -440,7 +444,6 @@ describe('AuthService', () => {
});
});


describe('.getAccessToken()', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand All @@ -454,7 +457,6 @@ describe('AuthService', () => {
});
});


describe('.getRefreshToken()', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand Down Expand Up @@ -482,6 +484,10 @@ describe('AuthService', () => {
const container = getContainer();
const authService = container.get(AuthService);

authService.config.client = {
post: () => new Promise(resolve => setTimeout(() => resolve({token: tokenPast.jwt}), 10))
};

beforeEach(() => {
authService.config.useRefreshToken = true;
authService.config.autoUpdateToken = true;
Expand Down Expand Up @@ -524,6 +530,30 @@ describe('AuthService', () => {
});
});

describe('with callback', () => {
it('should return true and call with callback(true)', done => {
authService.setResponseObject({access_token: tokenFuture.jwt, refresh_token: tokenFuture.jwt});

let authenticated = authService.isAuthenticated(updatedAuthenticated => {
expect(updatedAuthenticated).toBe(true);
done();
});

expect(authenticated).toBe(true);
});

it('should return true and call with callback(false) after refreshing', done => {
authService.setResponseObject({access_token: tokenPast.jwt, refresh_token: tokenFuture.jwt});

let authenticated = authService.isAuthenticated(updatedAuthenticated => {
expect(updatedAuthenticated).toBe(false);
done();
});

expect(authenticated).toBe(true);
});
});

describe('with autoUpdateToken=true', () => {
it('should return boolean true', () => {
authService.setResponseObject({token: 'some', refresh_token: 'another'});
Expand Down Expand Up @@ -552,7 +582,6 @@ describe('AuthService', () => {
});
});


describe('.isTokenExpired()', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand All @@ -566,7 +595,6 @@ describe('AuthService', () => {
});
});


describe('.getTokenPayload()', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand All @@ -580,7 +608,6 @@ describe('AuthService', () => {
});
});


describe('.updateToken()', () => {
const container = new Container();
const authService = container.get(AuthService);
Expand Down Expand Up @@ -678,7 +705,6 @@ describe('AuthService', () => {
});
});


describe('.signup()', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand Down Expand Up @@ -797,7 +823,6 @@ describe('AuthService', () => {
});
});


describe('.logout()', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand Down Expand Up @@ -840,7 +865,7 @@ describe('AuthService', () => {
});

it('should call oAuth2.close() if logoutEndpoint defined', done => {
spyOn(authService.authentication.oAuth2, 'close').and.returnValue(Promise.resolve({ state: 'ThisIsTheState' }));
spyOn(authService.authentication.oAuth2, 'close').and.returnValue(Promise.resolve({state: 'ThisIsTheState'}));
authService.config.logoutRedirect = false;
authService.authentication.storage.set('oidcProvider_state', 'ThisIsTheState');
authService.logout(0, undefined, 'oidcProvider')
Expand All @@ -854,8 +879,8 @@ describe('AuthService', () => {
});

it('return reject Promise if states differ', done => {
spyOn(authService.authentication.oAuth2, 'close').and.callFake( () => {
return Promise.resolve({ state: 'ThisIsTheState' });
spyOn(authService.authentication.oAuth2, 'close').and.callFake(() => {
return Promise.resolve({state: 'ThisIsTheState'});
});
authService.authentication.storage.set('oidcProvider_state', 'ThisIsNotTheState');
authService.logout(0, undefined, 'oidcProvider')
Expand All @@ -874,14 +899,14 @@ describe('AuthService', () => {
const authService = container.get(AuthService);

authService.authentication.oAuth1.open = (provider, userData) => Promise.resolve({
provider: provider,
userData: userData,
provider : provider,
userData : userData,
access_token: 'oauth1'
});

authService.authentication.oAuth2.open = (provider, userData) => Promise.resolve({
provider: provider,
userData: userData,
provider : provider,
userData : userData,
access_token: 'oauth2'
});

Expand Down Expand Up @@ -935,7 +960,6 @@ describe('AuthService', () => {
});
});


describe('.unlink()', () => {
const container = getContainer();
const authService = container.get(AuthService);
Expand Down

0 comments on commit fdbe4b5

Please sign in to comment.