Skip to content

Commit

Permalink
refactor: add more tsdocs
Browse files Browse the repository at this point in the history
Signed-off-by: jannyHou <[email protected]>
  • Loading branch information
jannyHou committed Aug 26, 2020
1 parent 79a3b40 commit 3f8e2e1
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe('jwt authentication', () => {
it(`user login and token granted successfully`, async () => {
const credentials = {email: '[email protected]', password: 'opensesame'};
const res = await client
.post('/users/refresh-token')
.post('/users/refresh-login')
.send(credentials)
.expect(200);
refreshToken = res.body.refreshToken;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import {get, post, requestBody} from '@loopback/rest';
import {SecurityBindings, securityId, UserProfile} from '@loopback/security';
import {genSalt, hash} from 'bcryptjs';
import {
RefreshGrant,
RefreshGrantRequestBody,
RefreshTokenServiceBindings,
TokenObject,
TokenServiceBindings,
Expand All @@ -26,6 +24,32 @@ import {UserRepository} from '../../../repositories';
import {Credentials} from '../../../services/user.service';
import {RefreshTokenService} from '../../../types';

// Describes the type of grant object taken in by method "refresh"
type RefreshGrant = {
refreshToken: string;
};

// Describes the schema of grant object
const RefreshGrantSchema = {
type: 'object',
required: ['refreshToken'],
properties: {
refreshToken: {
type: 'string',
},
},
};

// Describes the request body of grant object
const RefreshGrantRequestBody = {
description: 'Reissuing Acess Token',
required: true,
content: {
'application/json': {schema: RefreshGrantSchema},
},
};

// Describe the schema of user credentials
const CredentialsSchema = {
type: 'object',
required: ['email', 'password'],
Expand Down Expand Up @@ -105,6 +129,11 @@ export class UserController {
return savedUser;
}

/**
* A login function that returns an access token. After login, include the token
* in the next requests to verify your identity.
* @param credentials User email and password
*/
@post('/users/login', {
responses: {
'200': {
Expand Down Expand Up @@ -153,8 +182,11 @@ export class UserController {
async whoAmI(): Promise<string> {
return this.user[securityId];
}
// Routes using refreshtoken
@post('/users/refresh-token', {
/**
* A login function that returns refresh token and access token.
* @param credentials User email and password
*/
@post('/users/refresh-login', {
responses: {
'200': {
description: 'Token',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ import {
inject,
} from '@loopback/core';
import {
RefreshTokenConstants,
RefreshTokenServiceBindings,
TokenServiceBindings,
TokenServiceConstants,
UserServiceBindings,
RefreshTokenConstants,
RefreshTokenServiceBindings,
} from './keys';
import {
RefreshTokenRepository,
UserCredentialsRepository,
UserRepository,
RefreshTokenRepository,
} from './repositories';
import {MyUserService, RefreshtokenService} from './services';
import {JWTAuthenticationStrategy} from './services/jwt.auth.strategy';
Expand Down
24 changes: 24 additions & 0 deletions extensions/authentication-jwt/src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,29 @@ export namespace UserServiceBindings {
export const USER_CREDENTIALS_REPOSITORY =
'repositories.UserCredentialsRepository';
}

/**
* Constant values used when generating refresh token.
*/
export namespace RefreshTokenConstants {
/**
* The default secret used when generating refresh token.
*/
export const REFRESH_SECRET_VALUE = 'r3fr35htok3n';
/**
* The default expiration time for refresh token.
*/
export const REFRESH_EXPIRES_IN_VALUE = '216000';
/**
* The default issure used when generating refresh token.
*/
export const REFRESH_ISSURE_VALUE = 'loopback4';
}

/**
* Bindings related to token refresh service. The omitted explanation can be
* found in namespace `RefreshTokenConstants`.
*/
export namespace RefreshTokenServiceBindings {
export const REFRESH_TOKEN_SERVICE = BindingKey.create<RefreshTokenService>(
'services.authentication.jwt.refresh.tokenservice',
Expand All @@ -54,6 +71,13 @@ export namespace RefreshTokenServiceBindings {
export const REFRESH_ISSURE = BindingKey.create<string>(
'authentication.jwt.referesh.issure',
);
/**
* The backend datasource for refresh token's persistency.
*/
export const DATASOURCE_NAME = 'refreshdb';
/**
* Key for the repository that stores the refresh token and its bound user
* information
*/
export const REFRESH_REPOSITORY = 'repositories.RefreshTokenRepository';
}
22 changes: 13 additions & 9 deletions extensions/authentication-jwt/src/services/refreshtoken.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ import {
TokenServiceBindings,
UserServiceBindings,
} from '../keys';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import {RefreshToken, RefereshTokenWithRelations} from '../models';
import {RefreshTokenRepository} from '../repositories';
import {TokenObject} from '../types';
import {MyUserService} from './user.service';
/* eslint-disable*/

import {RefreshToken, RefreshTokenRelations} from '../models';
/* eslint-enable */
const jwt = require('jsonwebtoken');
const signAsync = promisify(jwt.sign);
const verifyAsync = promisify(jwt.verify);
Expand All @@ -34,9 +32,9 @@ export class RefreshtokenService {
@inject(UserServiceBindings.USER_SERVICE) public userService: MyUserService,
@inject(TokenServiceBindings.TOKEN_SERVICE) public jwtService: TokenService,
) {}
/*
* Generate Refresh Token
* UserProfile and roken generated by JWTService
/**
* Generate a refresh token, bind it with the given user profile + access
* token, then store them in backend.
*/
async generateToken(
userProfile: UserProfile,
Expand All @@ -59,9 +57,9 @@ export class RefreshtokenService {
});
return result;
}

/*
* Refresh JWT Token
* Issued refreshToken
* Refresh the access token bound with the given refresh token.
*/
async refreshToken(refreshToken: string): Promise<TokenObject> {
try {
Expand Down Expand Up @@ -90,6 +88,7 @@ export class RefreshtokenService {
);
}
}

/*
* [TODO] test and endpoint
*/
Expand All @@ -102,6 +101,11 @@ export class RefreshtokenService {
// ignore
}
}

/**
* Verify the validity of a refresh token, and make sure it exists in backend.
* @param refreshToken
*/
async verifyToken(refreshToken: string) {
try {
await verifyAsync(refreshToken, this.refreshSecret);
Expand Down
36 changes: 12 additions & 24 deletions extensions/authentication-jwt/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,29 @@

import {UserProfile} from '@loopback/security';

export type RefreshGrant = {
refreshToken: string;
};

export const RefreshGrantSchema = {
type: 'object',
required: ['refreshToken'],
properties: {
refreshToken: {
type: 'string',
},
},
};
export const RefreshGrantRequestBody = {
description: 'Reissuing Acess Token',
required: true,
content: {
'application/json': {schema: RefreshGrantSchema},
},
};

/**
* Describes the token object that returned by the refresh token service functions.
*/
export type TokenObject = {
accessToken: string;
expiresIn?: string | undefined;
refreshToken?: string | undefined;
};

/**
* The token refresh service. An access token expires in limited time. Therefore
* token refresh service is needed to keep replacing the old access token with
* a new one periodically.
*/
export interface RefreshTokenService {
/**
* Generate Token and return the Token Object
* Generate a refresh token, bind it with the given user profile + access
* token, then store them in backend.
*/
generateToken(userProfile: UserProfile, token: string): Promise<TokenObject>;

/**
* Verifies the validity of a token string and returns a new Token
*
* Refresh the access token bound with the given refresh token.
*/
refreshToken(refreshToken: string): Promise<TokenObject>;
}

0 comments on commit 3f8e2e1

Please sign in to comment.