Skip to main content

AdminAuthService

Package: @nauth-toolkit/core Type: Service

Administrative authentication service that provides user management operations including user creation, password management, session control, and user attribute updates.

import { AdminAuthService } from '@nauth-toolkit/nestjs';

Overview

Administrative service for user management operations including user creation, password management, session control, and user attribute updates.

note

Automatically injected by your framework adapter. No manual instantiation required.

Methods

confirmResetPassword()

Complete admin-initiated password reset with a verification code.

async confirmResetPassword(dto: ConfirmAdminResetPasswordDTO): Promise<ConfirmAdminResetPasswordResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not foundundefined
PASSWORD_RESET_CODE_INVALIDCode invalidundefined
PASSWORD_RESET_CODE_EXPIREDCode expiredundefined
PASSWORD_RESET_MAX_ATTEMPTSMax attempts exceeded (code only)undefined
WEAK_PASSWORDPolicy violation{ errors: string[] }
PASSWORD_REUSEDOnly if password.historyCount is configured AND password reusedundefined
SERVICE_UNAVAILABLEPassword reset service missingundefined

WEAK_PASSWORD details

Example strings returned in errors:

{
"errors": [
"Password must be at least 8 characters long",
"Password must contain at least one uppercase letter",
"Password must contain at least one number",
"Password must contain at least one special character !@#$%^&*()_+=[{}|;:,.<>?-]"
]
}

Example

@Post('reset-password/confirm')
async confirmReset(@Body() dto: ConfirmAdminResetPasswordDTO) {
return this.adminAuthService.confirmResetPassword(dto);
}

deleteUser()

Hard delete user with complete cascade cleanup. Permanently removes user and ALL associated data including sessions, verification tokens, MFA devices, trusted devices, social accounts, login attempts, challenge sessions, and audit logs.

async deleteUser(dto: DeleteUserDTO): Promise<DeleteUserResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
USER_NOT_FOUNDUser with sub doesn't existundefined

Example

@Injectable()
export class AdminService {
constructor(private readonly adminAuthService: AdminAuthService) {}

async deleteUser(sub: string) {
const result = await this.adminAuthService.deleteUser({ sub });
console.log(`Deleted ${result.deletedRecords.sessions} sessions`);
return result;
}
}
Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.

Irreversible Operation

This operation permanently deletes all user data and cannot be undone. All associated records (sessions, tokens, devices, etc.) are deleted from the database.


disableUser()

Administrative permanent account locking. Sets permanent lock (lockedUntil=NULL) and immediately revokes all active sessions. Reuses existing rate-limit lock fields.

async disableUser(dto: DisableUserDTO): Promise<DisableUserResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
USER_NOT_FOUNDUser with sub doesn't existundefined

Example

@Injectable()
export class AdminService {
constructor(private readonly adminAuthService: AdminAuthService) {}

async disableUser(sub: string, reason: string) {
const result = await this.adminAuthService.disableUser({ sub, reason });
console.log(`Revoked ${result.revokedSessions} sessions`);
return result;
}
}
Permanent vs Temporary Locks

Rate limiting sets temporary locks with lockedUntil = future date. Admin disableUser() sets lockedUntil = NULL for permanent locks.

Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.


enableUser()

Administrative account unlocking. Clears all lock fields (isLocked, lockReason, lockedAt, lockedUntil) and resets failed login attempts counter. Reverses the effect of disableUser() or rate-limit lockouts.

async enableUser(dto: EnableUserDTO): Promise<EnableUserResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
USER_NOT_FOUNDUser with sub doesn't existundefined

Example

@Injectable()
export class AdminService {
constructor(private readonly adminAuthService: AdminAuthService) {}

async enableUser(sub: string) {
const result = await this.adminAuthService.enableUser({ sub });
console.log(`User unlocked: ${result.user.email}`);
return result;
}
}
Unlocking Accounts

This method clears all lock fields including temporary rate-limit locks. Use this to unlock accounts that were locked by either disableUser() or automatic rate limiting.

Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.


getUserByEmail()

Retrieve user by email address. Returns null if user not found or if requireEmailVerified is true and email is not verified.

async getUserByEmail(dto: GetUserByEmailDTO): Promise<UserResponseDTO | null>

Parameters

Returns

  • UserResponseDTO or null if not found or email verification requirement not met

Errors

Errors: None. This method returns null instead of throwing when user is not found.

Example

const user = await adminAuthService.getUserByEmail({
email: 'user@example.com',
requireEmailVerified: true,
});

getUserById()

Retrieve user by unique identifier (sub). Returns null if user not found.

async getUserById(dto: GetUserByIdDTO): Promise<UserResponseDTO | null>

Parameters

Returns

Errors

Errors: None. This method returns null instead of throwing when user is not found.

Example

const user = await adminAuthService.getUserById({
sub: 'a21b654c-2746-4168-acee-c175083a65cd',
});

getUserSessions()

Get all active sessions for a user. Returns session details including device info, location, authentication method, and timestamps. Current session is marked with isCurrent: true.

async getUserSessions(dto: GetUserSessionsDTO): Promise<GetUserSessionsResponseDTO>

Parameters

Returns

Behavior

  • Returns all active sessions for the specified user
  • Current session (if called from authenticated context) is marked with isCurrent: true
  • Includes device information (name, type, platform, browser) when available
  • Includes location information (IP address, country, city) when available
  • Includes authentication method (password, social, admin) and OAuth provider for social logins

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not foundundefined
Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.

Example

@UseGuards(AuthGuard, AdminGuard)
@Get('admin/users/:sub/sessions')
async getUserSessions(@Param('sub') sub: string) {
return this.adminAuthService.getUserSessions({ sub });
}

getUsers()

Get paginated list of users with advanced filtering. Supports pagination, boolean filters, exact match filters, date filters with operators (gt, gte, lt, lte, eq), and flexible sorting.

async getUsers(dto: GetUsersDTO): Promise<GetUsersResponseDTO>

Parameters

Returns

Errors

This method does not throw errors. Returns empty results if no users match filters.

Example

@Injectable()
export class AdminService {
constructor(private readonly adminAuthService: AdminAuthService) {}

async listUsers(page: number, limit: number) {
const result = await this.adminAuthService.getUsers({
page,
limit,
isEmailVerified: true,
sortBy: 'createdAt',
sortOrder: 'DESC',
});
return result;
}
}
Data Privacy

Returns sanitized user data (no passwordHash, secrets, or sensitive fields). All users have access to standard UserResponseDTO fields only.

Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.


logoutAll()

Logout user from all sessions across all devices (global signout). Optionally revokes all trusted devices if forgetDevices is true.

async logoutAll(dto: AdminLogoutAllDTO): Promise<LogoutAllResponseDTO>

Parameters

  • dto - AdminLogoutAllDTO - Contains sub (user identifier) and optional forgetDevices flag

Returns

Behavior

  • Revokes all sessions for the user across all devices
  • If forgetDevices is true and trusted device feature is enabled, also revokes all trusted devices for the user
  • Returns the count of revoked sessions
  • Device revocation errors are non-blocking (logged but operation continues)

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not foundundefined
Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.

Example

@UseGuards(AuthGuard, AdminGuard)
@Post('admin/users/:sub/logout-all')
async adminLogoutAll(@Param('sub') sub: string, @Body() body: { forgetDevices?: boolean }) {
return this.adminAuthService.logoutAll({ sub, forgetDevices: body.forgetDevices });
}

resetPassword()

Admin-only: Initiate code-based password reset workflow with email/SMS delivery.

async resetPassword(dto: AdminResetPasswordDTO): Promise<AdminResetPasswordResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not foundundefined
SERVICE_UNAVAILABLEPassword reset service missingundefined

Example

@Controller('admin')
@UseGuards(AdminGuard)
export class AdminController {
constructor(private adminAuthService: AdminAuthService) {}

@Post('reset-password/initiate')
async initiateReset(@Body() dto: AdminResetPasswordDTO) {
return this.adminAuthService.resetPassword(dto);
}
}
Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.


revokeUserSession()

Logout from a specific session by session ID. Validates session ownership for security. Automatically clears cookies if logging out the current session.

async revokeUserSession(dto: AdminRevokeSessionDTO): Promise<LogoutSessionResponseDTO>

Parameters

Returns

Behavior

  • Revokes the specified session for the user
  • Validates session belongs to user (prevents unauthorized session revocation)
  • Automatically clears cookies if the revoked session was the current session
  • Returns wasCurrentSession: true if the revoked session was the current session

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not foundundefined
SESSION_NOT_FOUNDSession not foundundefined
FORBIDDENSession does not belong to userundefined
Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.

Example

@UseGuards(AuthGuard, AdminGuard)
@Delete('admin/users/:sub/sessions/:sessionId')
async adminRevokeSession(@Param('sub') sub: string, @Param('sessionId') sessionId: string) {
return this.adminAuthService.revokeUserSession({ sub, sessionId });
}

setMustChangePassword()

Force user to change password on next login. Sets the mustChangePassword flag, which triggers a FORCE_CHANGE_PASSWORD challenge on the user's next login attempt.

Note: This operation is only available for users with password authentication. Social-only accounts (users without a password hash) cannot be forced to change password.

async setMustChangePassword(dto: SetMustChangePasswordDTO): Promise<SetMustChangePasswordResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not found (by sub identifier)undefined
PASSWORD_CHANGE_NOT_ALLOWEDUser has no password (social-only account, no password hash)undefined

Example

await adminAuthService.setMustChangePassword({
sub: 'a21b654c-2746-4168-acee-c175083a65cd',
});

setPassword()

Admin-only: Reset user password by sub.

async setPassword(dto: AdminSetPasswordDTO): Promise<AdminSetPasswordResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not foundundefined
WEAK_PASSWORDPolicy violation{ errors: string[] }
PASSWORD_REUSEDOnly if password.historyCount is configured AND password reusedundefined

WEAK_PASSWORD details

Example strings returned in errors:

{
"errors": [
"Password must be at least 8 characters long",
"Password must contain at least one uppercase letter",
"Password must contain at least one number",
"Password must contain at least one special character !@#$%^&*()_+=[{}|;:,.<>?-]"
]
}
Social accounts

Admins can also use this method to set the first password for a social-only (social-first) account. This makes the account both password + social enabled.

Example

@Controller('admin')
@UseGuards(AuthGuard)
export class AdminController {
constructor(private adminAuthService: AdminAuthService) {}

@Post('reset-password')
async resetPassword(@Body() dto: AdminSetPasswordDTO) {
return this.adminAuthService.setPassword(dto);
}
}
Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.


signup()

Admin-only: Create user account with override capabilities.

async signup(dto: AdminSignupDTO): Promise<AdminSignupResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
EMAIL_EXISTSEmail already existsundefined
USERNAME_EXISTSUsername already existsundefined
PHONE_EXISTSOnly if signup.allowDuplicatePhones = false AND phone providedundefined
WEAK_PASSWORDPolicy violation OR password missing when generatePassword = falseundefined | { errors: string[] }

WEAK_PASSWORD details

When password validation fails, details includes an array of error strings:

{
"errors": [
"Password must be at least 8 characters long",
"Password must contain at least one uppercase letter",
"Password must contain at least one number",
"Password must contain at least one special character !@#$%^&*()_+=[{}|;:,.<>?-]"
]
}

When generatePassword = false and password is missing, details is undefined.

Admin capabilities
  • Can Bypass email/phone verification requirements by setting isPhoneVerified and isEmailVerified to true
  • Force password change on first login
  • Auto-generate secure passwords
  • Skip signup.enabled check

Example

@Controller('admin')
@UseGuards(AuthGuard)
export class AdminController {
constructor(private adminAuthService: AdminAuthService) {}

@Post('create-user')
async createUser(@Body() dto: AdminSignupDTO) {
return this.adminAuthService.signup(dto);
}
}
Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.


signupSocial()

Admin-only: Import social user from external platform with social account linkage.

async signupSocial(dto: AdminSignupSocialDTO): Promise<AdminSignupSocialResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
EMAIL_EXISTSEmail already existsundefined
USERNAME_EXISTSUsername already existsundefined
PHONE_EXISTSOnly if signup.allowDuplicatePhones = false AND phone providedundefined
SOCIAL_ACCOUNT_EXISTSProvider + providerId combination already existsundefined
SOCIAL_CONFIG_MISSINGSocial auth not configuredundefined
WEAK_PASSWORDPolicy violation (only if password provided)undefined | { errors: string[] }

WEAK_PASSWORD details

When password validation fails (only relevant for hybrid social+password accounts), details includes an array of error strings:

{
"errors": ["Password must be at least 8 characters long", "Password must contain at least one uppercase letter"]
}
Admin capabilities
  • Import social users with pre-linked social accounts
  • Create social-only users (no password) or hybrid users (social + password)
  • Email automatically verified (like normal social signup)
  • Bypass phone verification requirement (optional)
  • Suitable for migrating users from Cognito, Auth0, or other platforms
  • Social account (provider + providerId) must be unique
  • User flags hasSocialAuth and socialProviders automatically updated

Example

@Controller('admin')
@UseGuards(AuthGuard)
export class AdminController {
constructor(private adminAuthService: AdminAuthService) {}

@Post('import-social-user')
async importSocialUser(@Body() dto: AdminSignupSocialDTO) {
return this.adminAuthService.signupSocial(dto);
}
}

Use Case: Cognito Migration

// Migrate Cognito user with Google social login
// Note: Email is automatically verified for social imports (like normal social signup)
const result = await adminAuthService.signupSocial({
email: 'user@example.com',
provider: 'google',
providerId: cognitoUser.identities[0].userId,
providerEmail: cognitoUser.identities[0].providerAttributes.email,
socialMetadata: cognitoUser.identities[0].providerAttributes,
firstName: cognitoUser.given_name,
lastName: cognitoUser.family_name,
});
Authorization

Please ensure you implement Admin authorization as required. This method does not check admin status - protect routes with your own permission guards.


updateUserAttributes()

Update user profile information (firstName, lastName, username, email, phone, metadata, preferredMfaMethod).

Important behaviors:

  • When email changes: Email verification is reset (unless retainVerification: true), and all Email MFA devices are deleted
  • When phone changes: Phone verification is reset (unless retainVerification: true), and all SMS MFA devices are deleted
  • If deleted MFA devices were the only active methods, MFA is automatically disabled
  • Metadata is merged with existing metadata (set key to null to delete)
async updateUserAttributes(dto: AdminUpdateUserAttributesDTO): Promise<UserResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not found (by sub identifier) or user not found after updateundefined
VALIDATION_FAILEDUniqueness violation (email, phone, or username already exists for another user){ conflicts: string[] }

VALIDATION_FAILED details

When uniqueness constraints are violated, details includes a conflicts array:

{
"conflicts": ["Email already exists", "Phone number already exists", "Username already exists"]
}

Example

// Update basic profile fields
const updatedUser = await adminAuthService.updateUserAttributes({
sub: 'a21b654c-2746-4168-acee-c175083a65cd',
username: 'newusername',
firstName: 'John',
lastName: 'Doe',
});

// Add or update metadata
await adminAuthService.updateUserAttributes({
sub: 'user-uuid',
metadata: {
department: 'Engineering',
role: 'Senior Developer',
},
});

// Delete metadata keys by setting to null
await adminAuthService.updateUserAttributes({
sub: 'user-uuid',
metadata: {
temporaryField: null,
oldKey: null,
},
});

// Mix profile updates with metadata operations
await adminAuthService.updateUserAttributes({
sub: 'user-uuid',
firstName: 'Jane',
metadata: {
department: 'Product',
oldDepartment: null,
},
});
MFA Device Deletion

When updating email or phone, associated MFA devices are automatically deleted (cannot be reactivated):

  • Email change: All Email MFA devices are permanently deleted (requires re-setup)
  • Phone change: All SMS MFA devices with the old number are permanently deleted (requires re-setup)

If the deleted device(s) were the only MFA method(s), MFA is disabled for the user. They will need to set up MFA again at next login if MFA is required.

Audit events are logged for all device deletions with reason email_changed or phone_changed.

Best Practices

  • Set retainVerification: true only when transferring between trusted systems
  • Notify users when their MFA devices are removed due to profile changes
  • Guide users through MFA setup after email/phone changes if MFA is required

updateVerifiedStatus()

Update email and/or phone verification status directly. Intended for admin use cases such as migration or offline validation.

Important behaviors:

  • Cannot set isEmailVerified: true if user does not have an email address
  • Cannot set isPhoneVerified: true if user does not have a phone number
  • Can set verification to false even if email/phone doesn't exist (default state)
  • Only updates provided fields (partial update)
  • Records audit events with performedBy from authenticated admin context
async updateVerifiedStatus(dto: UpdateVerifiedStatusRequestDTO): Promise<UserResponseDTO>

Parameters

Returns

Errors

Throws NAuthException with the codes listed below.

CodeWhenDetails
NOT_FOUNDUser not found (by sub identifier) or user not found after updateundefined
VALIDATION_FAILEDTrying to set isEmailVerified: true when user has no email, or isPhoneVerified: true when user has no phoneundefined

Example

// Update email verification only
const updatedUser = await adminAuthService.updateVerifiedStatus({
sub: 'user-uuid',
isEmailVerified: true,
});

// Update both email and phone verification
const updatedUser = await adminAuthService.updateVerifiedStatus({
sub: 'user-uuid',
isEmailVerified: true,
isPhoneVerified: false,
});

// Set verification to false (allowed even if email/phone doesn't exist)
const updatedUser = await adminAuthService.updateVerifiedStatus({
sub: 'user-uuid',
isEmailVerified: false,
});
Admin Use Case

This method is intended for administrative operations such as:

  • Migrating users from external systems with pre-verified emails/phones
  • Offline validation workflows
  • Manual verification status corrections

The performedBy field in audit events is automatically populated from the authenticated admin's context.

Audit Events

  • EMAIL_VERIFIED - When isEmailVerified is updated
  • PHONE_VERIFIED - When isPhoneVerified is updated

Both events include metadata:

  • previousStatus - Previous verification status
  • newStatus - New verification status
  • updateMethod: 'admin_direct' - Indicates admin-initiated update