diff --git a/README.md b/README.md index 4f6c9b0..9278bf9 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,15 @@ This library uses HttpClient to send http requests. Click [here](https://embed.plnkr.co/qstWVYDhzfY4L4YF5Pxp?p=preview) to find a working demo. +## Available Functionality + +1. Basic authentication (Login, logout, check status) +1. Http interceptor to append tokens +1. Can extend the authentication flow (via setAuth function) +1. Decode and get token value (This will decode the token and return the requested value) +1. User permissions to manage access +1. Refresh tokens workflow + ## Add library to your project ```bash @@ -45,9 +54,9 @@ export interface AuthConfig { refreshTokenUrl?: string; getPermissionUrl?: string; permissionDataSet?: UserPermissions[]; - tokenGetter: (tokenName: string) => Promise; - tokenSetter: (tokenName: string, token: string) => Promise; - tokenRemover: (tokenName: string) => Promise; + tokenGetter?: (tokenName: string) => Promise; + tokenSetter?: (tokenName: string, token: string) => Promise; + tokenRemover?: (tokenName: string) => Promise; } ``` @@ -118,7 +127,12 @@ export const DEFAULT_ADDITIONAL_AUTH_CONFIG: AuthConfigAdditional = { 1. accessTokenExpiredResponseStatus - Response status when access token expired. (used to retry the response) 1. accessTokenExpiredErrorCode - You need to send error code inside the access token expired response. (used to retry the response) ->Note: Token interceptor will check error response for above conditions and retry the response. +>Note: Token interceptor will check error response for above conditions and retry the response. If refresh token not enabled user will logout + +1. refreshTokenExpiredResponseStatus - Response status when refresh token expired +2. refreshTokenExpiredErrorCode - You need to send error code inside the refresh token expired response. + +>Note: If a refresh token expired response received the user will logout. 1. accessTokenHeaderName - Header name use when appending access token in each request. 1. accessTokenPrefix - Prefix used when appending token (eg: Bearer {access-token}) diff --git a/package.json b/package.json index 1bd26c6..e82a5d0 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,12 @@ "name": "simple-angular-jwt-auth", "description": "authentication package for angular 5 using HttpClientModule", "author": "randil.fernando@outlook.com", - "version": "0.0.8", + "version": "0.0.9", "license": "MIT", "scripts": { "build": "ng-packagr -p ng-package.json", - "pack": "npm run build && cd ./dist && npm pack" + "pack": "npm run build && cd ./dist && npm pack", + "lint": "tslint --project ./" }, "repository": { "type": "git", diff --git a/src/modules/auth/providers/auth/auth.provider.ts b/src/modules/auth/providers/auth/auth.provider.ts index d7523d0..3702d2e 100644 --- a/src/modules/auth/providers/auth/auth.provider.ts +++ b/src/modules/auth/providers/auth/auth.provider.ts @@ -83,6 +83,14 @@ export class AuthProvider { } } + public getValueInToken(key: string): T { + if (this.accessToken) { + return (TokenDecoderHelper.DecodeToken(this.accessToken)[key]); + } else { + return null; + } + } + private async setAccessToken(token: string, persist: boolean = true): Promise { const condition = token !== null && typeof token === 'string' && token.length > 0; @@ -109,14 +117,6 @@ export class AuthProvider { return condition; } - public getValueInToken(key: string): T { - if (this.accessToken) { - return (TokenDecoderHelper.DecodeToken(this.accessToken)[key]); - } else { - return null; - } - } - private async getAuth(): Promise { if (!this.accessToken && this.authConfig.persistTokensEnabled) { const accessTokenPromise = this.authConfig.tokenGetter(this.authConfig.accessTokenStorageKey); diff --git a/src/modules/auth/providers/token/token.interceptor.ts b/src/modules/auth/providers/token/token.interceptor.ts index 3bc8c7c..642cf5f 100644 --- a/src/modules/auth/providers/token/token.interceptor.ts +++ b/src/modules/auth/providers/token/token.interceptor.ts @@ -7,7 +7,6 @@ import 'rxjs/add/operator/mergeMap'; import 'rxjs/add/observable/throw'; import {AuthProvider} from '../auth/auth.provider'; -import {ApiError} from '../../types/api-error.type'; import {AuthConfig} from '../../types/auth-config.type'; import {AuthConfigAdditional} from '../../types/auth-config-additional.type'; import {AuthConfigProvider} from '../auth-config/auth-config.provider'; @@ -28,13 +27,22 @@ export class TokenInterceptor implements HttpInterceptor { private handleError(error: HttpErrorResponse | any, request: HttpRequest, next: HttpHandler) { const errorBody = this.authConfig.convertToApiErrorType(error.error); - if (this.authConfig.refreshTokenEnabled && error.status === this.authConfig.accessTokenExpiredResponseStatus && + const authProvider = this.injector.get(AuthProvider); + + if (error.status === this.authConfig.accessTokenExpiredResponseStatus && errorBody.errorCode === this.authConfig.accessTokenExpiredErrorCode) { - const authProvider = this.injector.get(AuthProvider); - return Observable.fromPromise(authProvider.refresh()).mergeMap((status) => { - const authenticatedRequest = this.authenticate(request); - return next.handle(authenticatedRequest); - }); + + if (this.authConfig.refreshTokenEnabled) { + return Observable.fromPromise(authProvider.refresh()).mergeMap(() => { + const authenticatedRequest = this.authenticate(request); + return next.handle(authenticatedRequest); + }); + } else { + authProvider.logOut(); + } + } else if (error.status === this.authConfig.refreshTokenExpiredResponseStatus && + errorBody.errorCode === this.authConfig.refreshTokenExpiredErrorCode) { + authProvider.logOut(); } return Observable.throw(new Error(`${errorBody.errorMessage} error occurred. error code is ${errorBody.errorCode}`));