PhoneVerificationService
Package: @nauth-toolkit/core
Type: Service
Phone verification service that handles sending verification SMS codes, verifying phones with codes, and resending with rate limiting.
- NestJS
- Express
- Fastify
import { PhoneVerificationService } from '@nauth-toolkit/nestjs';
import { PhoneVerificationService } from '@nauth-toolkit/core';
// Access via nauth.phoneVerificationService after NAuth.create()
import { PhoneVerificationService } from '@nauth-toolkit/core';
// Access via nauth.phoneVerificationService after NAuth.create()
Overview
Handles phone verification workflow including code generation, SMS delivery, verification with code, and resend operations with rate limiting.
Auto-injected by framework. No manual instantiation required.
Methods
resendVerificationSMS()
Resend verification SMS with rate limiting. Supports identification by user sub or phone number.
async resendVerificationSMS(dto: ResendVerificationSMSDTO): Promise<ResendVerificationSMSResponseDTO>
Parameters
dto-ResendVerificationSMSDTO- Request DTOsub-string(optional) - User identifier (UUID v4)phone-string(optional) - User phone number (E.164 format)
Either sub or phone must be provided (not both).
Returns
ResendVerificationSMSResponseDTO- Response with token IDtokenId-number- Verification token ID (internal)
Errors
| Code | When | Details |
|---|---|---|
ALREADY_VERIFIED | Phone already verified | {} |
NOT_FOUND | User not found | { userId?: string } |
PHONE_REQUIRED | No phone on account | {} |
RATE_LIMIT_RESEND | Resend delay not met | { retryAfter: number, resendDelay: number } |
RATE_LIMIT_SMS | Too many requests | { retryAfter: number, currentCount: number } |
VALIDATION_FAILED | Neither sub nor phone | { message: string } |
Example
- NestJS
- Express
- Fastify
import { ResendVerificationSMSDTO } from '@nauth-toolkit/nestjs';
@Injectable()
export class MyService {
constructor(private phoneVerificationService: PhoneVerificationService) {}
async resendBySub() {
const dto: ResendVerificationSMSDTO = {
sub: 'a21b654c-2746-4168-acee-c175083a65cd',
};
await this.phoneVerificationService.resendVerificationSMS(dto);
}
async resendByPhone() {
const dto: ResendVerificationSMSDTO = {
phone: '+1234567890',
};
await this.phoneVerificationService.resendVerificationSMS(dto);
}
}
import { ResendVerificationSMSDTO } from '@nauth-toolkit/core';
// Resend by sub
app.post('/resend-sms', async (req, res) => {
const dto: ResendVerificationSMSDTO = {
sub: req.body.sub,
};
await nauth.phoneVerificationService.resendVerificationSMS(dto);
res.json({ success: true });
});
// Resend by phone
app.post('/resend-sms-phone', async (req, res) => {
const dto: ResendVerificationSMSDTO = {
phone: req.body.phone,
};
await nauth.phoneVerificationService.resendVerificationSMS(dto);
res.json({ success: true });
});
import { ResendVerificationSMSDTO } from '@nauth-toolkit/core';
// Resend by sub
fastify.post(
'/resend-sms',
nauth.adapter.wrapRouteHandler(async (req, reply) => {
const dto: ResendVerificationSMSDTO = {
sub: req.body.sub,
};
await nauth.phoneVerificationService.resendVerificationSMS(dto);
return { success: true };
}),
);
// Resend by phone
fastify.post(
'/resend-sms-phone',
nauth.adapter.wrapRouteHandler(async (req, reply) => {
const dto: ResendVerificationSMSDTO = {
phone: req.body.phone,
};
await nauth.phoneVerificationService.resendVerificationSMS(dto);
return { success: true };
}),
);
sendVerificationSMS()
Send verification SMS to user with code.
async sendVerificationSMS(dto: SendVerificationSMSDTO): Promise<SendVerificationSMSResponseDTO>
Parameters
dto-SendVerificationSMSDTO- Request DTOsub-string- User identifier (UUID v4)skipAlreadyVerifiedCheck-boolean(optional) - Skip already verified check (for MFA)challengeSessionId-number(optional) - Challenge session ID to link the verification token to a specific session
Returns
SendVerificationSMSResponseDTO- Response with token IDtokenId-number- Verification token ID (internal)
Errors
| Code | When | Details |
|---|---|---|
ALREADY_VERIFIED | Phone already verified | {} |
NOT_FOUND | User not found | { userId: string } |
PHONE_REQUIRED | No phone on account | {} |
RATE_LIMIT_RESEND | Resend delay not met | { retryAfter: number, resendDelay: number } |
RATE_LIMIT_SMS | Too many requests | { retryAfter: number, currentCount: number } |
Example
- NestJS
- Express
- Fastify
import { SendVerificationSMSDTO } from '@nauth-toolkit/nestjs';
@Injectable()
export class MyService {
constructor(private phoneVerificationService: PhoneVerificationService) {}
async sendCode() {
const dto: SendVerificationSMSDTO = {
sub: 'a21b654c-2746-4168-acee-c175083a65cd',
skipAlreadyVerifiedCheck: false,
};
const result = await this.phoneVerificationService.sendVerificationSMS(dto);
console.log('Token ID:', result.tokenId);
}
}
import { SendVerificationSMSDTO } from '@nauth-toolkit/core';
app.post('/send-sms', async (req, res) => {
const dto: SendVerificationSMSDTO = {
sub: req.body.sub,
};
const result = await nauth.phoneVerificationService.sendVerificationSMS(dto);
res.json({ tokenId: result.tokenId });
});
import { SendVerificationSMSDTO } from '@nauth-toolkit/core';
fastify.post(
'/send-sms',
nauth.adapter.wrapRouteHandler(async (req, reply) => {
const dto: SendVerificationSMSDTO = {
sub: req.body.sub,
};
const result = await nauth.phoneVerificationService.sendVerificationSMS(dto);
return { tokenId: result.tokenId };
}),
);
verifyPhoneWithCode()
Verify phone number using 6-digit code.
async verifyPhoneWithCode(dto: VerifyPhoneWithCodeDTO): Promise<VerifyPhoneResponseDTO>
Parameters
dto-VerifyPhoneWithCodeDTO- Request DTOphone-string- Phone number (E.164 format)code-string- 6-digit verification codechallengeSessionId-number(optional) - Restrict validation to a specific challenge session
Returns
VerifyPhoneResponseDTO- Response with success messagemessage-string- Success message
Errors
| Code | When | Details |
|---|---|---|
VERIFICATION_CODE_EXPIRED | Code expired | {} |
VERIFICATION_CODE_INVALID | Invalid or expired code | { attemptsRemaining?: number } |
VERIFICATION_TOO_MANY_ATTEMPTS | Too many attempts | {} |
Example
- NestJS
- Express
- Fastify
import { VerifyPhoneWithCodeDTO } from '@nauth-toolkit/nestjs';
@Injectable()
export class MyService {
constructor(private phoneVerificationService: PhoneVerificationService) {}
async verify() {
const dto: VerifyPhoneWithCodeDTO = {
phone: '+1234567890',
code: '123456',
};
const result = await this.phoneVerificationService.verifyPhoneWithCode(dto);
console.log(result.message);
}
}
import { VerifyPhoneWithCodeDTO } from '@nauth-toolkit/core';
app.post('/verify-phone', async (req, res) => {
const dto: VerifyPhoneWithCodeDTO = {
phone: req.body.phone,
code: req.body.code,
};
const result = await nauth.phoneVerificationService.verifyPhoneWithCode(dto);
res.json({ message: result.message });
});
import { VerifyPhoneWithCodeDTO } from '@nauth-toolkit/core';
fastify.post(
'/verify-phone',
nauth.adapter.wrapRouteHandler(async (req, reply) => {
const dto: VerifyPhoneWithCodeDTO = {
phone: req.body.phone,
code: req.body.code,
};
const result = await nauth.phoneVerificationService.verifyPhoneWithCode(dto);
return { message: result.message };
}),
);
verifyPhoneWithCodeBySub()
Verify phone using user sub and 6-digit code.
async verifyPhoneWithCodeBySub(dto: VerifyPhoneWithCodeBySubDTO): Promise<VerifyPhoneResponseDTO>
Parameters
dto-VerifyPhoneWithCodeBySubDTO- Request DTOsub-string- User identifier (UUID v4)code-string- 6-digit verification codechallengeSessionId-number(optional) - Restrict validation to a specific challenge session
Returns
VerifyPhoneResponseDTO- Response with success messagemessage-string- Success message
Errors
| Code | When | Details |
|---|---|---|
NOT_FOUND | User not found | { userId?: string } |
PHONE_REQUIRED | No phone on account | {} |
VERIFICATION_CODE_EXPIRED | Code expired | {} |
VERIFICATION_CODE_INVALID | Invalid or expired code | { attemptsRemaining?: number } |
VERIFICATION_TOO_MANY_ATTEMPTS | Too many attempts | {} |
Example
- NestJS
- Express
- Fastify
import { VerifyPhoneWithCodeBySubDTO } from '@nauth-toolkit/nestjs';
@Injectable()
export class MyService {
constructor(private phoneVerificationService: PhoneVerificationService) {}
async verifyBySub() {
const dto: VerifyPhoneWithCodeBySubDTO = {
sub: 'a21b654c-2746-4168-acee-c175083a65cd',
code: '123456',
};
const result = await this.phoneVerificationService.verifyPhoneWithCodeBySub(dto);
console.log(result.message);
}
}
import { VerifyPhoneWithCodeBySubDTO } from '@nauth-toolkit/core';
app.post('/verify-phone-by-sub', async (req, res) => {
const dto: VerifyPhoneWithCodeBySubDTO = {
sub: req.body.sub,
code: req.body.code,
};
const result = await nauth.phoneVerificationService.verifyPhoneWithCodeBySub(dto);
res.json({ message: result.message });
});
import { VerifyPhoneWithCodeBySubDTO } from '@nauth-toolkit/core';
fastify.post(
'/verify-phone-by-sub',
nauth.adapter.wrapRouteHandler(async (req, reply) => {
const dto: VerifyPhoneWithCodeBySubDTO = {
sub: req.body.sub,
code: req.body.code,
};
const result = await nauth.phoneVerificationService.verifyPhoneWithCodeBySub(dto);
return { message: result.message };
}),
);