Skip to content

Commit

Permalink
implement verify token endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeh committed Sep 21, 2024
1 parent 11ba0fe commit 9754211
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 7 deletions.
18 changes: 16 additions & 2 deletions api/src/modules/auth/authentication/authentication.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,23 @@ export class AuthenticationController {
): Promise<ControllerResponse> {
return tsRestHandler(
authContract.requestPasswordRecovery,
async ({ body }) => {
const { email } = body;
async ({ body: { email } }) => {
await this.passwordRecovery.requestPasswordRecovery(email, origin);
return {
body: null,
status: HttpStatus.CREATED,
};
},
);
}

@Public()
@TsRestHandler(authContract.validateToken)
async validateToken(): Promise<ControllerResponse> {
return tsRestHandler(
authContract.validateToken,
async ({ headers: { authorization }, query: { tokenType } }) => {
await this.authService.verifyToken(authorization, tokenType);
return {
body: null,
status: HttpStatus.OK,
Expand Down
14 changes: 14 additions & 0 deletions api/src/modules/auth/authentication/authentication.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import { JwtPayload } from '@api/modules/auth/strategies/jwt.strategy';
import { EventBus } from '@nestjs/cqrs';
import { UserSignedUpEvent } from '@api/modules/events/user-events/user-signed-up.event';
import { UserWithAccessToken } from '@shared/dtos/user.dto';
import { TOKEN_TYPE_ENUM } from '@shared/schemas/auth/token-type.schema';
import { ApiConfigService } from '@api/modules/config/app-config.service';

@Injectable()
export class AuthenticationService {
constructor(
private readonly usersService: UsersService,
private readonly jwt: JwtService,
private readonly apiConfig: ApiConfigService,
private readonly eventBus: EventBus,
) {}
async validateUser(email: string, password: string): Promise<User> {
Expand All @@ -24,6 +27,7 @@ export class AuthenticationService {
throw new UnauthorizedException(`Invalid credentials`);
}

// TODO: Move logic to createUser service
async signUp(signupDto: LoginDto): Promise<void> {
const passwordHash = await bcrypt.hash(signupDto.password, 10);
const newUser = await this.usersService.createUser({
Expand All @@ -38,4 +42,14 @@ export class AuthenticationService {
const accessToken: string = this.jwt.sign(payload);
return { user, accessToken };
}

async verifyToken(token: string, type: TOKEN_TYPE_ENUM): Promise<boolean> {
const { secret } = this.apiConfig.getJWTConfigByType(type);
try {
this.jwt.verify(token, { secret });
return true;
} catch (error) {
return false;
}
}
}
5 changes: 3 additions & 2 deletions api/src/modules/auth/services/password-recovery.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { EventBus } from '@nestjs/cqrs';
import { PasswordRecoveryRequestedEvent } from '@api/modules/events/user-events/password-recovery-requested.event';
import { ApiConfigService } from '@api/modules/config/app-config.service';
import { TOKEN_TYPE_ENUM } from '@shared/schemas/auth/token-type.schema';
import { User } from '@shared/entities/users/user.entity';

@Injectable()
export class PasswordRecoveryService {
Expand All @@ -18,7 +19,7 @@ export class PasswordRecoveryService {
private readonly apiConfig: ApiConfigService,
) {}

async recoverPassword(email: string, origin: string): Promise<void> {
async requestPasswordRecovery(email: string, origin: string): Promise<void> {
const user = await this.users.findByEmail(email);
if (!user) {
this.logger.warn(
Expand All @@ -39,7 +40,7 @@ export class PasswordRecoveryService {
this.eventBus.publish(new PasswordRecoveryRequestedEvent(email, user.id));
}

async resetPassword(token: string, password: string): Promise<void> {
async resetPassword(user: User): Promise<void> {
throw new NotImplementedException();
}
}
4 changes: 3 additions & 1 deletion api/test/e2e/steps/password-recovery.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { IEmailServiceToken } from '@api/modules/notifications/email/email-servi
import { MockEmailService } from 'api/test/utils/mocks/mock-email.service';
import { TestManager } from 'api/test/utils/test-manager';

const feature = loadFeature('./test/e2e/features/password-recovery.feature');
const feature = loadFeature(
'./test/e2e/features/password-recovery-send-email.feature',
);

defineFeature(feature, (test) => {
let testManager: TestManager;
Expand Down
17 changes: 15 additions & 2 deletions shared/config/.env.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,21 @@ DB_PORT=5432
DB_NAME=blc
DB_USERNAME=blue-carbon-cost
DB_PASSWORD=blue-carbon-cost
JWT_SECRET=mysecret
JWT_EXPIRES_IN=1d


# Access Token Configuration
ACCESS_TOKEN_SECRET=access_token_secret
ACCESS_TOKEN_EXPIRES_IN=2h

# Reset Password Token Configuration
RESET_PASSWORD_TOKEN_SECRET=reset_password_token_secret
RESET_PASSWORD_TOKEN_EXPIRES_IN=2h

# Email Confirmation Token Configuration
EMAIL_CONFIRMATION_TOKEN_SECRET=email_confirmation_token_secret
EMAIL_CONFIRMATION_TOKEN_EXPIRES_IN=2h


AWS_SES_ACCESS_KEY_ID=test
AWS_SES_ACCESS_KEY_SECRET=test
AWS_SES_DOMAIN=test
Expand Down
1 change: 1 addition & 0 deletions shared/contracts/auth/auth.contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const authContract = contract.router({
validateToken: {
method: "GET",
path: "/authentication/validate-token",
headers: z.object({ authorization: z.string() }),
responses: {
200: null,
401: null,
Expand Down
11 changes: 11 additions & 0 deletions shared/schemas/auth/token-type.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { z } from "zod";

export enum TOKEN_TYPE_ENUM {
ACCESS = "access",
RESET_PASSWORD = "reset-password",
EMAIL_CONFIRMATION = "email-confirmation",
}

export const TokenTypeSchema = z.object({
tokenType: z.nativeEnum(TOKEN_TYPE_ENUM),
});

0 comments on commit 9754211

Please sign in to comment.