Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Auth refresh token #594

Merged
merged 1 commit into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions apps/api-gateway/src/authz/authz.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { CustomExceptionFilter } from 'apps/api-gateway/common/exception-handler
import { ResetPasswordDto } from './dtos/reset-password.dto';
import { ForgotPasswordDto } from './dtos/forgot-password.dto';
import { ResetTokenPasswordDto } from './dtos/reset-token-password';
import { RefreshTokenDto } from './dtos/refresh-token.dto';


@Controller('auth')
Expand Down Expand Up @@ -176,5 +177,24 @@ export class AuthzController {

}

@Post('/refresh-token')
@ApiOperation({
summary: 'Token from refresh token',
description: 'Get a new token from a refresh token'
})
@ApiResponse({ status: HttpStatus.OK, description: 'Success', type: ApiResponseDto })
async refreshToken(
@Body() refreshTokenDto: RefreshTokenDto,
@Res() res: Response): Promise<Response> {
const tokenData = await this.authzService.refreshToken(refreshTokenDto.refreshToken);
const finalResponse: IResponseType = {
statusCode: HttpStatus.OK,
message: ResponseMessages.user.success.refreshToken,
data: tokenData
};

return res.status(HttpStatus.OK).json(finalResponse);

}

}
4 changes: 4 additions & 0 deletions apps/api-gateway/src/authz/authz.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ export class AuthzService extends BaseService {
return this.sendNatsMessage(this.authServiceProxy, 'user-set-token-password', resetTokenPasswordDto);
}

async refreshToken(refreshToken: string): Promise<ISignInUser> {
return this.sendNatsMessage(this.authServiceProxy, 'refresh-token-details', refreshToken);
}

async addUserDetails(userInfo: AddUserDetailsDto): Promise<string> {
const payload = { userInfo };
return this.sendNatsMessage(this.authServiceProxy, 'add-user', payload);
Expand Down
14 changes: 14 additions & 0 deletions apps/api-gateway/src/authz/dtos/refresh-token.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { IsNotEmpty } from 'class-validator';

import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { trim } from '@credebl/common/cast.helper';

export class RefreshTokenDto {

@ApiProperty()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'refreshToken is required.' })
refreshToken: string;

}
5 changes: 5 additions & 0 deletions apps/user/src/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export class UserController {
return loginRes;
}

@MessagePattern({ cmd: 'refresh-token-details' })
async refreshTokenDetails(refreshToken: string): Promise<ISignInUser> {
return this.userService.refreshTokenDetails(refreshToken);
}

@MessagePattern({ cmd: 'user-reset-password' })
async resetPassword(payload: IUserResetPassword): Promise<IResetPasswordResponse> {
return this.userService.resetPassword(payload);
Expand Down
17 changes: 17 additions & 0 deletions apps/user/src/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,23 @@ export class UserService {
}
}

async refreshTokenDetails(refreshToken: string): Promise<ISignInUser> {

try {
try {
const tokenResponse = await this.clientRegistrationService.getAccessToken(refreshToken);
return tokenResponse;
} catch (error) {
throw new BadRequestException(ResponseMessages.user.error.invalidRefreshToken);
}

} catch (error) {
this.logger.error(`In refreshTokenDetails : ${JSON.stringify(error)}`);
throw new RpcException(error.response ? error.response : error);

}
}

async updateFidoVerifiedUser(email: string, isFidoVerified: boolean, password: string): Promise<boolean> {
if (isFidoVerified) {
await this.userRepository.addUserPassword(email.toLowerCase(), password);
Expand Down
12 changes: 4 additions & 8 deletions libs/client-registration/src/client-registration.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -787,10 +787,6 @@ export class ClientRegistrationService {
payload.refresh_token = refreshToken;
payload.client_secret = process.env.KEYCLOAK_MANAGEMENT_CLIENT_SECRET;


this.logger.log(`access Token for platform Payload: ${JSON.stringify(payload)}`);


if (
'refresh_token' !== payload.grant_type ||
!payload.client_id ||
Expand All @@ -801,23 +797,23 @@ export class ClientRegistrationService {
throw new Error('Invalid inputs while getting token.');
}

const strURL = await this.keycloakUrlService.GetSATURL('credebl-platform');
this.logger.log(`getToken URL: ${strURL}`);
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};

const tokenResponse = await this.commonService.httpPost(
await this.keycloakUrlService.GetSATURL('credebl-platform'),
await this.keycloakUrlService.GetSATURL(process.env.KEYCLOAK_REALM),
qs.stringify(payload)
, config);

return tokenResponse;

} catch (error) {

this.logger.error(
`Error in getAccessToken ${JSON.stringify(error)}`
);
throw error;
}
}
Expand Down
6 changes: 4 additions & 2 deletions libs/common/src/response-messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export const ResponseMessages = {
updateUserProfile:'User profile updated successfully',
resetPassword: 'Password reset successfully',
degreeCertificate: 'Degree Certificate shared successfully',
resetPasswordLink: 'Reset password link has been sent to your mail'
resetPasswordLink: 'Reset password link has been sent to your mail',
refreshToken: 'Token details fetched successfully'
},
error: {
exists: 'User already exists',
Expand Down Expand Up @@ -60,7 +61,8 @@ export const ResponseMessages = {
resetSamePassword: 'New password should not be the current password',
resetPasswordLink: 'Unable to create reset password token',
invalidResetLink: 'Invalid or expired reset password link',
invalidAccessToken: 'Authentication failed'
invalidAccessToken: 'Authentication failed',
invalidRefreshToken: 'Invalid refreshToken provided'
}
},
organisation: {
Expand Down