Skip to content

Change password

Let signed-in users change their password.

This guide adds the change-password feature.

The change-password feature lets signed-in users update their password by providing their current password and a new password.

Add the feature

Run the CLI command:

Terminal window
brkpt auth add change-password

The CLI adds a new features/change-password/ folder.

Validate the DTO

The change password feature uses a fixed request shape. This guide has already enabled ValidationPipe, so add validation decorators to the generated DTO.

src/brkpt-auth/features/change-password/dto/change.dto.ts
import { IsString, MinLength } from 'class-validator';
export class ChangeDto {
@IsString()
currentPassword!: string;
@IsString()
@MinLength(6)
newPassword!: string;
}

Implement ChangePasswordAdapter

The change password adapter finds the signed-in user from the access token payload, validates the current password, and updates the stored password.

Create change-password.adapter.ts:

  • Directorysrc/
    • Directorybrkpt-auth/
      • Directoryadapters/
        • change-password.adapter.ts
src/brkpt-auth/adapters/change-password.adapter.ts
import { Injectable } from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { User } from '../../../generated/prisma/client';
import { PrismaService } from '../../prisma/prisma.service';
import { ChangePasswordPort } from '../features/change-password/change-password.port';
import { AuthJwtPayload } from './types';
@Injectable()
export class ChangePasswordAdapter implements ChangePasswordPort<User> {
constructor(private readonly prisma: PrismaService) {}
findUserByJwtPayload(payload: AuthJwtPayload): Promise<User | null> {
return this.prisma.user.findUnique({
where: {
id: payload.sub,
},
});
}
validatePassword(user: User, currentPassword: string): Promise<boolean> {
return bcrypt.compare(currentPassword, user.password);
}
async updatePassword(user: User, newPassword: string): Promise<void> {
const password = await bcrypt.hash(newPassword, 10);
await this.prisma.user.update({
where: { id: user.id },
data: { password },
});
}
extractUserIdFromJwtPayload(payload: AuthJwtPayload): number {
return payload.sub;
}
}

Register the feature

Update features.ts and pass ChangePasswordAdapter to changePasswordFeature:

src/brkpt-auth/features.ts
import { BlacklistAdapter } from './adapters/blacklist.adapter';
import { ChangePasswordAdapter } from './adapters/change-password.adapter';
import { CoreAdapter } from './adapters/core.adapter';
import { CredentialsAdapter } from './adapters/credentials.adapter';
import { MagicLinkAdapter } from './adapters/magic-link.adapter';
import { OAuthAdapter } from './adapters/oauth.adapter';
import { OtpAdapter } from './adapters/otp.adapter';
import { SessionAdapter } from './adapters/session.adapter';
import { FeatureConfig } from './common/interfaces';
import { blacklistFeature } from './features/blacklist/blacklist.feature';
import { changePasswordFeature } from './features/change-password/change-password.feature';
import { coreFeature } from './features/core/core.feature';
import { credentialsFeature } from './features/credentials/credentials.feature';
import { EmailMagicLinkDriver } from './features/magic-link/drivers/email.driver';
import { magicLinkFeature } from './features/magic-link/magic-link.feature';
import { GithubOAuthDriver } from './features/oauth/drivers/github.driver';
import { GoogleOAuthDriver } from './features/oauth/drivers/google.driver';
import { oauthFeature } from './features/oauth/oauth.feature';
import { EmailOtpDriver } from './features/otp/drivers/email.driver';
import { otpFeature } from './features/otp/otp.feature';
import { sessionFeature } from './features/session/session.feature';
export const features: FeatureConfig[] = [
coreFeature(CoreAdapter),
blacklistFeature(BlacklistAdapter),
credentialsFeature(CredentialsAdapter),
sessionFeature(SessionAdapter),
oauthFeature(OAuthAdapter, GoogleOAuthDriver, GithubOAuthDriver),
otpFeature(OtpAdapter, EmailOtpDriver),
magicLinkFeature(MagicLinkAdapter, EmailMagicLinkDriver),
changePasswordFeature(ChangePasswordAdapter),
];

Start the application:

Terminal window
pnpm start:dev

The change-password feature adds one endpoint:

Method Path Description
POST /auth/change-password Change the signed-in user’s password

Change the password

Use an access token from any sign-in method, then send the current password and the new password:

POST /auth/change-password
Authorization: Bearer <access-token>
Content-Type: application/json
{
"currentPassword": "password",
"newPassword": "123456"
}

A successful request changes the password for the signed-in user.

The current session remains active after the password is changed. If the session feature is enabled, other sessions for the same user are revoked.