Skip to content

Commit

Permalink
feat(auth): add OAuth2 strategy
Browse files Browse the repository at this point in the history
basic configuration example:
```
strategies: [
        NbOAuth2AuthStrategy.setup({
          name: 'google',
          clientId: 'YOUR_CLIENT_ID',
          clientSecret: '',
          authorize: {
            endpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
            responseType: NbOAuth2ResponseType.TOKEN,
            scope: 'https://www.googleapis.com/auth/userinfo.profile',
            
            
            redirectUri: 'http://localhost:4100/example/oauth2/callback',
          },
        }),
      ],
```
  • Loading branch information
nnixaa committed Jun 14, 2018
1 parent f7fb11a commit 2f28cbc
Show file tree
Hide file tree
Showing 9 changed files with 1,081 additions and 95 deletions.
1 change: 1 addition & 0 deletions docs/articles/auth-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ You can use the built-in components or create your custom ones.
## Auth Strategies
- `NbDummyAuthStrategy` - simple strategy for testing purposes, could be used to simulate backend responses while API is in the development;
- `NbPasswordAuthStrategy` - the most common email/login/password authentication strategy.
- `NbOAuth2AuthStrategy` - the most popular authentication framework that enables applications to obtain limited access to user accounts on an HTTP service.
<hr>

## Other helper services
Expand Down
11 changes: 11 additions & 0 deletions docs/structure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,17 @@ export const structure = [
},
],
},
{
type: 'page',
name: 'NbOAuth2AuthStrategy',
children: [
{
type: 'block',
block: 'component',
source: 'NbOAuth2AuthStrategy',
},
],
},
{
type: 'page',
name: 'NbDummyAuthStrategy',
Expand Down
258 changes: 175 additions & 83 deletions src/framework/auth/services/token/token.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,90 +4,182 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

import { NbAuthJWTToken, NbAuthSimpleToken } from './token';


describe('auth JWT token', () => {
// tslint:disable
const simpleToken = new NbAuthSimpleToken('token');
const validJWTToken = new NbAuthJWTToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjI1MTczMTQwNjYxNzUsIm5hbWUiOiJDaHJpcyBTZXZpbGxlamEiLCJhZG1pbiI6dHJ1ZX0=.03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773');
const emptyJWTToken = new NbAuthJWTToken('..');
const invalidBase64JWTToken = new NbAuthJWTToken('h%2BHY.h%2BHY.h%2BHY');

const invalidJWTToken = new NbAuthJWTToken('.');

const noExpJWTToken = new NbAuthJWTToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY290Y2guaW8iLCJuYW1lIjoiQ2hyaXMgU2V2aWxsZWphIiwiYWRtaW4iOnRydWV9.03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773');

const expiredJWTToken = new NbAuthJWTToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjEzMDA4MTkzODAsIm5hbWUiOiJDaHJpcyBTZXZpbGxlamEiLCJhZG1pbiI6dHJ1ZX0.03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773');
// tslint:enable

it('getPayload success', () => {
expect(validJWTToken.getPayload())
.toEqual(JSON.parse('{"iss":"scotch.io","exp":2517314066175,"name":"Chris Sevilleja","admin":true}'));
});

it('getPayload, not valid JWT token, must consist of three parts', () => {
expect(() => {
invalidJWTToken.getPayload();
})
.toThrow(new Error(
`The token ${invalidJWTToken.getValue()} is not valid JWT token and must consist of three parts.`));
});

it('getPayload, not valid JWT token, cannot be decoded', () => {
expect(() => {
emptyJWTToken.getPayload();
})
.toThrow(new Error(
`The token ${emptyJWTToken.getValue()} is not valid JWT token and cannot be decoded.`));
});

it('getPayload, not valid base64 in JWT token, cannot be decoded', () => {
expect(() => {
invalidBase64JWTToken.getPayload();
})
.toThrow(new Error(
`The token ${invalidBase64JWTToken.getValue()} is not valid JWT token and cannot be parsed.`));
});

it('getTokenExpDate success', () => {
const date = new Date(0);
date.setUTCSeconds(2517314066175);
expect(validJWTToken.getTokenExpDate()).toEqual(date);
});

it('getTokenExpDate is empty', () => {
expect(noExpJWTToken.getTokenExpDate()).toBeNull();
});

it('no exp date token is valid', () => {
expect(noExpJWTToken.isValid()).toEqual(true);
});

it('isValid success', () => {
expect(validJWTToken.isValid()).toEqual(true);
});

it('isValid fail', () => {
// without token
expect(new NbAuthJWTToken('').isValid()).toBeFalsy();

// expired date
expect(expiredJWTToken.isValid()).toBeFalsy();
});

it('NbAuthJWTToken name', () => {
// without token
expect(NbAuthJWTToken.NAME).toEqual(validJWTToken.getName());
});

it('NbAuthSimpleToken name', () => {
// without token
expect(NbAuthSimpleToken.NAME).toEqual(simpleToken.getName());
import { NbAuthOAuth2Token, NbAuthJWTToken, NbAuthSimpleToken } from './token';


describe('auth token', () => {
describe('NbAuthJWTToken', () => {
// tslint:disable
const simpleToken = new NbAuthSimpleToken('token');
const validJWTToken = new NbAuthJWTToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjI1MTczMTQwNjYxNzUsIm5hbWUiOiJDaHJpcyBTZXZpbGxlamEiLCJhZG1pbiI6dHJ1ZX0=.03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773');
const emptyJWTToken = new NbAuthJWTToken('..');
const invalidBase64JWTToken = new NbAuthJWTToken('h%2BHY.h%2BHY.h%2BHY');

const invalidJWTToken = new NbAuthJWTToken('.');

const noExpJWTToken = new NbAuthJWTToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY290Y2guaW8iLCJuYW1lIjoiQ2hyaXMgU2V2aWxsZWphIiwiYWRtaW4iOnRydWV9.03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773');

const expiredJWTToken = new NbAuthJWTToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjEzMDA4MTkzODAsIm5hbWUiOiJDaHJpcyBTZXZpbGxlamEiLCJhZG1pbiI6dHJ1ZX0.03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773');
// tslint:enable

it('getPayload success', () => {
expect(validJWTToken.getPayload())
.toEqual(JSON.parse('{"iss":"scotch.io","exp":2517314066175,"name":"Chris Sevilleja","admin":true}'));
});

it('getPayload, not valid JWT token, must consist of three parts', () => {
expect(() => {
invalidJWTToken.getPayload();
})
.toThrow(new Error(
`The token ${invalidJWTToken.getValue()} is not valid JWT token and must consist of three parts.`));
});

it('getPayload, not valid JWT token, cannot be decoded', () => {
expect(() => {
emptyJWTToken.getPayload();
})
.toThrow(new Error(
`The token ${emptyJWTToken.getValue()} is not valid JWT token and cannot be decoded.`));
});

it('getPayload, not valid base64 in JWT token, cannot be decoded', () => {
expect(() => {
invalidBase64JWTToken.getPayload();
})
.toThrow(new Error(
`The token ${invalidBase64JWTToken.getValue()} is not valid JWT token and cannot be parsed.`));
});

it('getTokenExpDate success', () => {
const date = new Date(0);
date.setUTCSeconds(2517314066175);
expect(validJWTToken.getTokenExpDate()).toEqual(date);
});

it('getTokenExpDate is empty', () => {
expect(noExpJWTToken.getTokenExpDate()).toBeNull();
});

it('no exp date token is valid', () => {
expect(noExpJWTToken.isValid()).toEqual(true);
});

it('isValid success', () => {
expect(validJWTToken.isValid()).toEqual(true);
});

it('isValid fail', () => {
// without token
expect(new NbAuthJWTToken('').isValid()).toBeFalsy();

// expired date
expect(expiredJWTToken.isValid()).toBeFalsy();
});

it('NbAuthJWTToken name', () => {
// without token
expect(NbAuthJWTToken.NAME).toEqual(validJWTToken.getName());
});

it('NbAuthSimpleToken name', () => {
// without token
expect(NbAuthSimpleToken.NAME).toEqual(simpleToken.getName());
});

it('NbAuthSimpleToken has payload', () => {
// without token
expect(simpleToken.getPayload()).toEqual(null);
});

it('getPayload success', () => {
expect(validJWTToken.getPayload())
.toEqual(JSON.parse('{"iss":"scotch.io","exp":2517314066175,"name":"Chris Sevilleja","admin":true}'));
});

it('NbAuthJWTToken name', () => {
// without token
expect(NbAuthJWTToken.NAME).toEqual(validJWTToken.getName());
});

it('NbAuthSimpleToken name', () => {
// without token
expect(NbAuthSimpleToken.NAME).toEqual(simpleToken.getName());
});

it('NbAuthSimpleToken has payload', () => {
// without token
expect(simpleToken.getPayload()).toEqual(null);
});
});

it('NbAuthSimpleToken has payload', () => {
// without token
expect(simpleToken.getPayload()).toEqual(null);
describe('NbAuthOAuth2Token', () => {

const token = {
access_token: '2YotnFZFEjr1zCsicMWpAA',
expires_in: 3600,
refresh_token: 'tGzv3JOkF0XG5Qx2TlKWIA',
token_type: 'bearer',
example_parameter: 'example_value',
};

const validToken = new NbAuthOAuth2Token(token);
const emptyToken = new NbAuthOAuth2Token({});

const noExpToken = new NbAuthOAuth2Token({
access_token: '2YotnFZFEjr1zCsicMWpAA',
refresh_token: 'tGzv3JOkF0XG5Qx2TlKWIA',
example_parameter: 'example_value',
});

it('getPayload success', () => {
expect(validToken.getPayload()).toEqual(token);
});

it('getPayload, not valid token, cannot be decoded', () => {
expect(() => {
emptyToken.getPayload();
})
.toThrow(new Error(
`Cannot extract payload from an empty token.`));
});

it('getTokenExpDate success', () => {
const date = new Date();
date.setUTCSeconds(date.getUTCSeconds() + 3600);
expect(validToken.getTokenExpDate().getFullYear()).toEqual(date.getFullYear());
expect(validToken.getTokenExpDate().getDate()).toEqual(date.getDate());
expect(validToken.getTokenExpDate().getMonth()).toEqual(date.getMonth());
expect(validToken.getTokenExpDate().getMinutes()).toEqual(date.getMinutes());
expect(validToken.getTokenExpDate().getSeconds()).toEqual(date.getSeconds());
});

it('getTokenExpDate is empty', () => {
expect(noExpToken.getTokenExpDate()).toBeNull();
});

it('toString is json', () => {
expect(String(validToken)).toEqual(JSON.stringify(token));
});

it('getTokenExpDate is empty', () => {
expect(validToken.getType()).toEqual(token.token_type);
});

it('getTokenExpDate is empty', () => {
expect(noExpToken.getRefreshToken()).toEqual(token.refresh_token);
});

it('no exp date token is valid', () => {
expect(noExpToken.isValid()).toEqual(true);
});

it('isValid success', () => {
expect(validToken.isValid()).toEqual(true);
});

it('name', () => {
expect(NbAuthOAuth2Token.NAME).toEqual(validToken.getName());
});
});
});
Loading

0 comments on commit 2f28cbc

Please sign in to comment.