Skip to content

Commit

Permalink
feat(auth): add support for refresh tokens (#390)
Browse files Browse the repository at this point in the history
  • Loading branch information
dizco authored and nnixaa committed Apr 26, 2018
1 parent 44eb8a6 commit dc57c85
Show file tree
Hide file tree
Showing 8 changed files with 437 additions and 8 deletions.
15 changes: 15 additions & 0 deletions src/backend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,21 @@ app.delete('/api/auth/logout', function (req, res) {
});
});

app.post('/api/auth/refresh-token', function (req, res) {
var payload = {
id: users[0].id,
email: users[0].email,
role: 'user',
};
var token = jwt.encode(payload, cfg.jwtSecret);
return res.json({
data: {
message: 'Successfully refreshed token.',
token: token
}
});
});

app.listen(4400, function () {
console.log('ngx-admin sample API is running on 4400');
});
Expand Down
2 changes: 2 additions & 0 deletions src/framework/auth/providers/abstract-auth.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export abstract class NbAbstractAuthProvider {

abstract logout(): Observable<NbAuthResult>;

abstract refreshToken(): Observable<NbAuthResult>;

protected createFailResponse(data?: any): HttpResponse<Object> {
return new HttpResponse<Object>({ body: {}, status: 401 });
}
Expand Down
7 changes: 7 additions & 0 deletions src/framework/auth/providers/dummy-auth.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ export class NbDummyAuthProvider extends NbAbstractAuthProvider {
);
}

refreshToken(data?: any): Observable<NbAuthResult> {
return observableOf(this.createDummyResult(data))
.pipe(
delay(this.getConfigValue('delay')),
);
}

protected createDummyResult(data?: any): NbAuthResult {
if (this.getConfigValue('alwaysFail')) {
// TODO we dont call tokenService clear during logout in case result is not success
Expand Down
1 change: 1 addition & 0 deletions src/framework/auth/providers/email-pass-auth.options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface NgEmailPassAuthProviderConfig {
requestPass?: boolean | NbEmailPassModuleConfig;
resetPass?: boolean | NbEmailPassResetModuleConfig;
logout?: boolean | NbEmailPassResetModuleConfig;
refreshToken?: boolean | NbEmailPassModuleConfig;
token?: {
key?: string;
getter?: Function;
Expand Down
62 changes: 62 additions & 0 deletions src/framework/auth/providers/email-pass-auth.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ import { getDeepFromObject } from '../helpers';
* defaultErrors: ['Something went wrong, please try again.'],
* defaultMessages: ['Your password has been successfully changed.'],
* },
* refreshToken: {
* endpoint: '/api/auth/refresh-token',
* method: 'post',
* redirect: {
* success: null,
* failure: null,
* },
* defaultErrors: ['Something went wrong, please try again.'],
* defaultMessages: ['Your token has been successfully refreshed.'],
* },
* token: {
* key: 'data.token',
* getter: (module: string, res: HttpResponse<Object>) => getDeepFromObject(res.body,
Expand Down Expand Up @@ -170,6 +180,16 @@ export class NbEmailPassAuthProvider extends NbAbstractAuthProvider {
defaultErrors: ['Something went wrong, please try again.'],
defaultMessages: ['Your password has been successfully changed.'],
},
refreshToken: {
endpoint: 'refresh-token',
method: 'post',
redirect: {
success: null,
failure: null,
},
defaultErrors: ['Something went wrong, please try again.'],
defaultMessages: ['Your token has been successfully refreshed.'],
},
token: {
key: 'data.token',
getter: (module: string, res: HttpResponse<Object>) => getDeepFromObject(res.body,
Expand Down Expand Up @@ -403,6 +423,48 @@ export class NbEmailPassAuthProvider extends NbAbstractAuthProvider {
);
}

refreshToken(data?: any): Observable<NbAuthResult> {
const method = this.getConfigValue('refreshToken.method');
const url = this.getActionEndpoint('refreshToken');

return this.http.request(method, url, {body: data, observe: 'response'})
.pipe(
map((res) => {
if (this.getConfigValue('refreshToken.alwaysFail')) {
throw this.createFailResponse(data);
}

return res;
}),
this.validateToken('refreshToken'),
map((res) => {
return new NbAuthResult(
true,
res,
this.getConfigValue('refreshToken.redirect.success'),
[],
this.getConfigValue('messages.getter')('refreshToken', res),
this.getConfigValue('token.getter')('refreshToken', res));
}),
catchError((res) => {
let errors = [];
if (res instanceof HttpErrorResponse) {
errors = this.getConfigValue('errors.getter')('refreshToken', res);
} else {
errors.push('Something went wrong.');
}

return observableOf(
new NbAuthResult(
false,
res,
this.getConfigValue('refreshToken.redirect.failure'),
errors,
));
}),
);
}

protected validateToken (module: string): any {
return map((res) => {
const token = this.getConfigValue('token.getter')(module, res);
Expand Down
Loading

0 comments on commit dc57c85

Please sign in to comment.