Skip to content

Commit

Permalink
add refresh token API endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Szotkowski committed Sep 19, 2023
1 parent a9ea985 commit 5b7bd96
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 6 deletions.
64 changes: 63 additions & 1 deletion src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {authenticate} from '@loopback/authentication';
import {
Credentials,
JWTService,
TokenObject,
UserCredentials,
} from '@loopback/authentication-jwt';
import {inject} from '@loopback/context';
Expand Down Expand Up @@ -112,14 +113,75 @@ export class UserController {
return token;
}

@post('/refresh-token', {
responses: {
'200': {
description: 'Refresh token',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
token: {type: 'string'},
},
},
},
},
},
},
})
async refreshToken(
@requestBody({
content: {
'application/json': {
schema: {
type: 'object',
properties: {
token: {type: 'string'},
},
required: [
'token',
],
},
},
},
})
requestBody: {refreshToken: string},
): Promise<TokenObject> {
try {
const {refreshToken} = requestBody;
if (!refreshToken) {
throw new HttpErrors.Unauthorized(
`Error verifying token: 'refresh token' is null`,
);
}
const userRefreshData = await this.jwtService.verifyToken(refreshToken);
const user = await this.userRepository.findById(
userRefreshData.userId.toString(),
);
const userProfile: UserProfile = this.userService.convertToUserProfile(user);
const token = await this.jwtService.generateToken(userProfile);
return {
accessToken: token,
};
} catch (error) {
throw new HttpErrors.Unauthorized(
`Error verifying token: ${error.message}`,
);
}
}

@post('/signup', {
responses: {
'200': {
description: 'Signup',
content: {
'application/json': {
schema: {
type: 'boolean',
type: 'object',
properties: {
token: {type: 'string'},
},
},
},
},
Expand Down
6 changes: 3 additions & 3 deletions src/repositories/user.repository.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {inject, Getter} from '@loopback/core';
import {Getter, inject} from '@loopback/core';
import {
DefaultCrudRepository,
repository,
HasManyRepositoryFactory,
repository,
} from '@loopback/repository';
import {DbDataSource} from '../datasources';
import {User, UserRelations, Instruction, Progress} from '../models';
import {Instruction, Progress, User, UserRelations} from '../models';
import {InstructionRepository} from './instruction.repository';
import {ProgressRepository} from './progress.repository';

Expand Down
39 changes: 38 additions & 1 deletion src/services/jwt-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@
// License text available at https://opensource.org/licenses/MIT

import {TokenService} from '@loopback/authentication';
import {TokenObject} from '@loopback/authentication-jwt';
import {inject} from '@loopback/core';
import {repository} from '@loopback/repository';
import {HttpErrors} from '@loopback/rest';
import {securityId, UserProfile} from '@loopback/security';
import {promisify} from 'util';
import {
UserRepository
} from '../repositories';
import {MyUserService} from './user-service';

const jwt = require('jsonwebtoken');
const signAsync = promisify(jwt.sign);
const verifyAsync = promisify(jwt.verify);
Expand All @@ -18,7 +25,12 @@ export class JWTService implements TokenService {
private jwtSecret: string,
@inject('authentication.jwt.expiresIn')
private jwtExpiresIn: string,
) {}
@inject('services.user.service')
public userService: MyUserService,
@inject('services.jwt.service')
public jwtService: JWTService,
@repository(UserRepository) protected userRepository: UserRepository,
) { }

async verifyToken(token: string): Promise<UserProfile> {
if (!token) {
Expand Down Expand Up @@ -69,4 +81,29 @@ export class JWTService implements TokenService {
}
return token;
}

async refreshToken(refreshToken: string): Promise<TokenObject> {
try {
if (!refreshToken) {
throw new HttpErrors.Unauthorized(
`Error verifying token : 'refresh token' is null`,
);
}
const userRefreshData = await this.verifyToken(refreshToken);
const user = await this.userRepository.findById(
userRefreshData.userId.toString(),
);
const userProfile: UserProfile =
this.userService.convertToUserProfile(user);
// create a JSON Web Token based on the user profile
const token = await this.jwtService.generateToken(userProfile);
return {
accessToken: token,
};
} catch (error) {
throw new HttpErrors.Unauthorized(
`Error verifying token : ${error.message}`,
);
}
}
}
2 changes: 1 addition & 1 deletion src/services/user-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class MyUserService implements UserService<User, Credentials> {
public userRepository: UserRepository,
@inject('services.hasher')
public hasher: BcryptHasher,
) {}
) { }

async verifyCredentials(credentials: Credentials): Promise<User> {
const foundUser0 = await this.userRepository.findOne({
Expand Down

0 comments on commit 5b7bd96

Please sign in to comment.