Skip to content

Commit 436daca

Browse files
authored
Merge pull request #16 from cobuildlab/feature/token-validation
improve token validation
2 parents 22bd572 + 444f022 commit 436daca

6 files changed

Lines changed: 92 additions & 14 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ const CREDENTIALS_HANDLER = {
4141
await AsyncStorage.removeItem('credentials_store');
4242
apolloClient.resetStore();
4343
},
44+
// You can specify a what token the library will validate
45+
tokenToValidate: 'accessToken',
46+
// or pass a function that validate it
4447
validateToken: (credentials) => {
4548
const { exp } = jwtDecode(credentials.idToken) as { exp: number };
4649

package-lock.json

Lines changed: 15 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cobuildlab/react-native-auth0",
3-
"version": "0.3.0",
3+
"version": "0.3.1",
44
"description": "Todo",
55
"main": "lib/index.js",
66
"types": "./lib/index.d.ts",
@@ -62,5 +62,8 @@
6262
"prettier --write",
6363
"eslint --fix"
6464
]
65+
},
66+
"dependencies": {
67+
"jwt-decode": "^3.1.2"
6568
}
6669
}

src/client.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,48 @@
11
import Auth0, {
22
AuthorizeOptions,
33
Credentials as Auth0Credentials,
4-
Options,
54
} from 'react-native-auth0';
6-
import { Credentials, CredentialsHandlersInput, ErrorCases } from './types';
7-
import { ErrorPublisher } from './utils';
5+
import {
6+
Credentials,
7+
CredentialsHandlersInput,
8+
ErrorCases,
9+
Options,
10+
tokenToValidateType,
11+
} from './types';
12+
import { ErrorPublisher, validateToken } from './utils';
813

914
export class Auth0Native extends Auth0 {
1015
private credentials: Credentials | null = null;
16+
private audience: string;
1117

1218
private saveCredentials: CredentialsHandlersInput['save'];
1319
private getCredentials: CredentialsHandlersInput['get'];
1420
private clearCredentials: CredentialsHandlersInput['clear'];
15-
private validateToken: CredentialsHandlersInput['validateToken'];
16-
21+
private validateToken?: CredentialsHandlersInput['validateToken'];
22+
private tokenToValidate?: tokenToValidateType;
1723
private errors: Record<ErrorCases, ErrorPublisher> = {
1824
AUTHORIZATION: new ErrorPublisher(),
1925
CLEAR_SESSION: new ErrorPublisher(),
2026
REFRESH_TOKEN: new ErrorPublisher(),
2127
SAVE_CREDENTIALS: new ErrorPublisher(),
2228
};
2329

30+
/**
31+
* Create a client to used to authenticate with auth0 platform and manage that auth state.
32+
*
33+
* @param {Options} options - Options.
34+
* @param {CredentialsHandlersInput} credentialsHandlers - Options to handle the credentials and token validations.
35+
*/
2436
constructor(options: Options, credentialsHandlers: CredentialsHandlersInput) {
2537
super(options);
2638
this.saveCredentials = credentialsHandlers.save;
2739
this.getCredentials = credentialsHandlers.get;
2840
this.clearCredentials = credentialsHandlers.clear;
2941
this.validateToken = credentialsHandlers.validateToken;
42+
this.tokenToValidate = credentialsHandlers.tokenToValidate;
43+
44+
// set a default audience if the options is undefined
45+
this.audience = options.audience || `https://${options.domain}/api/v2/`;
3046
}
3147

3248
async handleCredentials(data: Auth0Credentials): Promise<Credentials> {
@@ -49,8 +65,8 @@ export class Auth0Native extends Auth0 {
4965
/**
5066
*
5167
* @param {string} scope - Scopes requested for the issued tokens. E.g. `openid profile`.
52-
* @param {object} options - Options to pass to the auth endpoint.
53-
* @returns {object} The auth0 credentials.
68+
* @param {AuthorizeOptions} options - Options to pass to the auth endpoint.
69+
* @returns {Promise<Credentials | undefined>} The auth0 credentials.
5470
*/
5571
async authorize(
5672
scope: string,
@@ -60,6 +76,7 @@ export class Auth0Native extends Auth0 {
6076
const result = await this.webAuth.authorize(
6177
{
6278
scope,
79+
audience: this.audience,
6380
},
6481
options,
6582
);
@@ -90,8 +107,20 @@ export class Auth0Native extends Auth0 {
90107
if (!credentials) {
91108
return false;
92109
}
110+
let valid = false;
111+
112+
if (this.validateToken && this.validateToken(credentials)) {
113+
valid = true;
114+
}
115+
116+
if (
117+
this.tokenToValidate &&
118+
validateToken(credentials[this.tokenToValidate])
119+
) {
120+
valid = true;
121+
}
93122

94-
if (this.validateToken(credentials)) {
123+
if (valid) {
95124
this.credentials = credentials;
96125
return true;
97126
}

src/types.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,36 @@
11
import {
22
AuthorizeOptions,
33
Credentials as Auth0Credentials,
4+
Options as Auth0Options,
45
} from 'react-native-auth0';
56

67
export interface Credentials extends Auth0Credentials {
78
issuedAt?: number;
89
}
910

10-
export type CredentialsHandlersInput = {
11+
export interface Options extends Auth0Options {
12+
audience?: string;
13+
}
14+
export type tokenToValidateType = keyof Pick<
15+
Credentials,
16+
'idToken' | 'accessToken'
17+
>;
18+
interface CredentialsHandlersInputBase {
1119
save: (data: Credentials) => void | Promise<void>;
1220
clear: () => void | Promise<void>;
1321
get: () => (Credentials | null) | Promise<Credentials | null>;
14-
validateToken: (data: Credentials) => boolean;
15-
};
22+
}
23+
export type CredentialsHandlersInput = CredentialsHandlersInputBase &
24+
(
25+
| {
26+
validateToken: (data: Credentials) => boolean;
27+
tokenToValidate?: tokenToValidateType;
28+
}
29+
| {
30+
tokenToValidate: tokenToValidateType;
31+
validateToken?: (data: Credentials) => boolean;
32+
}
33+
);
1634

1735
export interface AuthClientContextType {
1836
authorize: (args: {

src/utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import jwtDecode from 'jwt-decode';
12
import { ErrorCallbackType } from './types';
23

34
/**.
@@ -9,6 +10,17 @@ export function getTimestamp(): number {
910
return Math.round(new Date().getTime() / 1000);
1011
}
1112

13+
/**
14+
* @param {string} token - Token to validate.
15+
* @returns {boolean} Boolean if the token is valid.
16+
*/
17+
export function validateToken(token: string): boolean {
18+
const tokenObj = jwtDecode<{
19+
exp: number;
20+
}>(token);
21+
22+
return tokenObj.exp > getTimestamp();
23+
}
1224
export class ErrorPublisher {
1325
private subscribers: Set<ErrorCallbackType> = new Set();
1426

0 commit comments

Comments
 (0)