Skip to main content
Version: 🚧 Canary

🛣️ Authentication routes

Routes are SDK composers, not Express middleware. Use the common-task map to choose an endpoint and authService to mount the supported API. Try the Bearer workflow before reading individual routes; each route below links its schema and feature so request validation and composition remain visible.

Inventory

RouteMethod / protocolPathSchemaValidatorsSuccess status
registerCredentialsRoutePOST / HTTP/auth/registerregisterCredentialsSchemaNone201
loginWithCredentialsRoutePOST / HTTP/auth/loginloginWithCredentialsSchemaNone200
resendMfaCodeRoutePOST / HTTP/auth/mfa/resendresendMfaCodeSchemaNone200
verifyMfaCodeRoutePOST / HTTP/auth/mfa/verifyverifyMfaCodeSchemaNone200
logoutRoutePOST / HTTP/auth/logoutlogoutCookieSchema or logoutBearerSchemaisAuthenticated()204
refreshTokenRoutePOST / HTTP/auth/token/refreshrefreshTokenCookieSchema or refreshTokenBearerSchemaNone; valid refresh token required by handlerCookie 204; Bearer 200
checkTokenRoutePOST / HTTP/auth/token/checkcheckTokenSchemaNone200
deleteRefreshTokensRouteDELETE / HTTP/auth/:identityId/refresh-tokensdeleteRefreshTokensSchemaisAuthenticated(), some(admin, self)204
loginWithOnetimeTokenRoutePOST / HTTP/auth/ott/loginloginWithOnetimeTokenSchemaNone200
generateOnetimeTokenRoutePOST / HTTP/auth/ott/generateNoneisAuthenticated(), checkIdentityType(['admin'])200
restoreOnetimeTokenRoutePOST / HTTP/auth/ott/restoreNoneisAuthenticated(), checkIdentityType(['admin'])200
invalidateOnetimeTokenRoutePOST / HTTP/auth/ott/invalidateNoneisAuthenticated(), checkIdentityType(['admin'])200
sendVerificationEmailRoutePOST / HTTP/auth/:identityId/send-verification-emailsendVerificationEmailSchemaisAuthenticated(), some(admin, self)204
confirmEmailRoutePOST / HTTP/auth/confirm-emailconfirmEmailSchemaNone204
changeEmailRoutePATCH / HTTP/auth/:identityId/change-emailchangeEmailSchemaisAuthenticated(), some(admin, self)204
confirmNewEmailRoutePOST / HTTP/auth/confirm-new-emailconfirmNewEmailSchemaNone; one-time token required204
sendResetPasswordLinkEmailRoutePOST / HTTP/auth/send-reset-password-link-emailsendResetPasswordLinkEmailSchemaNone204
completePasswordResetRoutePOST / HTTP/auth/reset-passwordcompletePasswordResetSchemaNone; reset token required204
changePasswordRoutePATCH / HTTP/auth/:identityId/change-passwordchangePasswordSchemaisAuthenticated(), some(admin, self)204
deactivateRoutePOST / HTTP/auth/deactivatedeactivateSchemaisAuthenticated(), some(admin, self)204
activateRoutePOST / HTTP/auth/activateactivateSchemaisAuthenticated(), checkIdentityType(['admin'])204
View shared source context
import {ok} from 'neverthrow';
import {identity as noop, pick, tap} from 'ramda';

import {
assertDoesNotMatch,
assertIdentityExists,
assertMatches,
assertValidOneTimeTokenExists,
AuthenticationBadRequestError,
AuthenticationConflictError,
AuthenticationForbiddenError,
AuthenticationInvalidInputError,
AuthenticationInvalidTokenError,
AuthenticationNotFoundError,
AuthenticationUnauthorizedError,
AuthenticationUnexpectedDBError,
AuthenticationUnexpectedDbError,
AuthenticationUnexpectedError,
AuthenticationUnprocessableEntityError,
buildTokenVerification,
buildUpdateIdentityActivatedPayload,
buildUpdateIdentityDeactivatedPayload,
buildUpdateIdentityEmailAndEmailVerifiedPayload,
buildUpdateIdentityPasswordPayload,
checkEmailIsUniqueInIdentities,
checkOneTimeToken,
checkToken as checkTokenBlock,
compareStringAgainstHash,
createMfaCode,
createMfaToken,
extractTokenFromAuthorizationHeader,
generateOneTimeToken,
getChangeEmailTokenTarget,
getFingerprint,
getIdentityIdByEmail,
getMfaChallengeTokenTarget,
getResetPasswordTokenTarget,
hash,
invalidateOneTimeToken,
isEmail,
isEmailVerified,
MfaInvalidCodeError,
MfaUnexpectedError,
normalizeBearerLoginResponse,
normalizeBearerRefreshResponse,
normalizeCookieLoginResponse,
sendEmail,
sendMfaCode,
softDeleteRefreshTokens,
storeOneTimeToken,
verifyMfaCode,
} from '../blocks/authentication';
import {normalizeEmptyBody} from '../blocks/common';
import {getIdentityById, updateIdentity} from '../blocks/identity';
import {
buildAcceptInvitationPayload,
buildCheckConfirmEmailTokenPayload,
buildCheckInvitationTokenPayload,
checkToken,
confirmEmail,
confirmEmailTerminator,
createAccessToken,
createRefreshToken,
generateOnetimeToken,
getInvitationById,
getInvitationIdFromTokenInfo,
invalidateOnetimeToken,
isPendingInvitation,
loginWithCredentials,
loginWithOnetimeToken,
logout,
logoutTerminator,
refreshToken,
registerCredentials,
registerTerminator,
restoreOnetimeToken,
sendVerificationEmail,
sendVerificationEmailTerminator,
setResponseCookie,
updateInvitation,
} from '../handlers';
import {
applyPayloadArgs,
compose,
flatMapAsync,
ifElse,
lift,
mapMatchingErrorToFalse,
match,
orThrow,
RouteHandlerPayload,
withLogging,
withRoute,
} from '../primitives';
import {whenCookieAuth} from '../utils/cookie';
import {checkIdentityType, isAuthenticated, isSelf, some} from '../validators';

Details

registerCredentialsRoute

Implementation

Endpoint: POST /auth/register

Register a credential identity.

Access: Public.

Request: registerCredentialsSchema validates the JSON credentials and optional invitation token.

Pipeline: Invitation-token requests run the Invitation handlers around checkToken and registerCredentials; ordinary requests run registerCredentials directly, then registerTerminator.

Success: 201 with {email, id}.

Failure: 400 missing/failed input, 401 invalid invitation token, 404 missing invitation, 422 duplicate identity, or 500 persistence failure.

View complete source
export const registerCredentialsRoute = withRoute({
handler: compose(
ifElse(
match(Boolean, ['params', 'requestBody', 'token']),
compose(
withLogging(buildCheckInvitationTokenPayload),
flatMapAsync(withLogging(checkToken)),
flatMapAsync(withLogging(getInvitationIdFromTokenInfo)),
flatMapAsync(withLogging(getInvitationById)),
flatMapAsync(withLogging(isPendingInvitation)),
flatMapAsync(withLogging(registerCredentials)),
flatMapAsync(withLogging(buildAcceptInvitationPayload)),
flatMapAsync(withLogging(updateInvitation)),
),
withLogging(registerCredentials),
),
// TODO: flatMapAsync(withLogging(sendRegistrationCompleteEmail)),
lift(withLogging(registerTerminator)),
),
method: 'POST',
path: '/auth/register',
validators: [],
});

loginWithCredentialsRoute

Implementation

Endpoint: POST /auth/login

Sign in with credentials; may initiate MFA.

Access: Public.

Request: loginWithCredentialsSchema validates the JSON email, password, and optional fingerprint.

Pipeline: loginWithCredentials; the MFA branch creates/sends a challenge, while the session branch runs createAccessToken, createRefreshToken, optional setResponseCookie, and a mode-specific normalizer.

Success: 200 with an MFA token, cookie-mode {id} plus cookies, or Bearer {accessToken, id, refreshToken}.

Failure: 401 for locked/wrong credentials; MFA failures are 400 or 500.

View complete source
export const loginWithCredentialsRoute = withRoute({
handler: compose(
ifElse(
match(Boolean, ['context', 'configuration', 'isMfaEnabled']),
compose(
withLogging(loginWithCredentials),
flatMapAsync(
withLogging(applyPayloadArgs(createMfaCode, [['context', 'configuration', 'mfaCodeLength']], 'mfaCode')),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
createMfaToken,
[
['context', 'db', 'onetimetokens'],
['context', 'configuration', 'authSecrets'],
['context', 'configuration', 'onetimeTokenSignOptions'],
['params', 'requestBody', 'fingerprint'],
['context', 'data', 'identity', 'id'],
['context', 'data', 'identity', 'email'],
['context', 'data', 'mfaCode'],
],
'token',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
sendMfaCode,
[
['context', 'mailService'],
['context', 'configuration', 'mfaCodeEmailConfig', 'emailConfig', 'subject'],
['context', 'configuration', 'mfaCodeEmailConfig', 'sender'],
['context', 'configuration', 'mfaCodeEmailConfig', 'emailConfig', 'bodyTemplate'],
['context', 'data', 'identity', 'email'],
['context', 'data', 'mfaCode'],
],
'hasSentMfaCode',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(pick(['token']), [['context', 'data']], 'mfaTokenObj'))),
lift(orThrow([[MfaUnexpectedError, 500]], [['context', 'data', 'mfaTokenObj'], 200])),
),
compose(
withLogging(loginWithCredentials),
flatMapAsync(withLogging(createAccessToken)),
flatMapAsync(withLogging(createRefreshToken)),
flatMapAsync(
withLogging(
whenCookieAuth(
compose(
withLogging(setResponseCookie),
flatMapAsync(
withLogging(applyPayloadArgs(normalizeCookieLoginResponse, [['context', 'data']], 'loginResponse')),
),
),
withLogging(applyPayloadArgs(normalizeBearerLoginResponse, [['context', 'data']], 'loginResponse')),
),
),
),
lift(withLogging(orThrow([], [['context', 'data', 'loginResponse']]))),
),
),
),
method: 'POST',
path: '/auth/login',
validators: [],
});

resendMfaCodeRoute

Implementation

Endpoint: POST /auth/mfa/resend

Issue a replacement MFA challenge.

Access: Public to a caller holding a valid MFA challenge token.

Request: resendMfaCodeSchema validates the token and optional fingerprint.

Pipeline: getFingerprint, getMfaChallengeTokenTarget, checkToken, createMfaCode, createMfaToken, sendMfaCode, then response selection.

Success: 200 with the replacement challenge token.

Failure: 400 invalid token/code input, 401 failed token validation, or 500 token/database/mail failure.

View complete source
export const resendMfaCodeRoute = withRoute({
handler: compose(
withLogging(applyPayloadArgs(getMfaChallengeTokenTarget, [], 'target')),
flatMapAsync(withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
checkOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'data', 'target'],
['params', 'requestBody', 'token'],
],
'tokenInfo',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
assertValidOneTimeTokenExists,
[
['context', 'db', 'onetimetokens'],
['params', 'requestBody', 'token'],
],
'doesOneTimeTokenExist',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
invalidateOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['params', 'requestBody', 'token'],
],
'isInvalidatedSuccessfully',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
getIdentityById,
[
['context', 'db', 'identities'],
['context', 'data', 'tokenInfo', 'data', 'identityId'],
],
'identity',
),
),
),
flatMapAsync(
withLogging(applyPayloadArgs(createMfaCode, [['context', 'configuration', 'mfaCodeLength']], 'mfaCode')),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
createMfaToken,
[
['context', 'db', 'onetimetokens'],
['context', 'configuration', 'authSecrets'],
['context', 'configuration', 'onetimeTokenSignOptions'],
['params', 'requestBody', 'fingerprint'],
['context', 'data', 'identity', 'id'],
['context', 'data', 'identity', 'email'],
['context', 'data', 'mfaCode'],
],
'token',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
sendMfaCode,
[
['context', 'mailService'],
['context', 'configuration', 'mfaCodeEmailConfig', 'emailConfig', 'subject'],
['context', 'configuration', 'mfaCodeEmailConfig', 'sender'],
['context', 'configuration', 'mfaCodeEmailConfig', 'emailConfig', 'bodyTemplate'],
['context', 'data', 'identity', 'email'],
['context', 'data', 'mfaCode'],
],
'hasSentMfaCode',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(pick(['token']), [['context', 'data']], 'mfaTokenObj'))),
lift(
orThrow(
[
[MfaInvalidCodeError, 400],
[MfaUnexpectedError, 500],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationInvalidInputError, 400],
[AuthenticationNotFoundError, 404],
[AuthenticationUnexpectedError, 500],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnprocessableEntityError, 422],
],
[['context', 'data', 'mfaTokenObj'], 200],
),
),
),
method: 'POST',
path: '/auth/mfa/resend',
validators: [],
});

verifyMfaCodeRoute

Implementation

Endpoint: POST /auth/mfa/verify

Verify an MFA challenge.

Access: Public to a caller holding the challenge token and code.

Request: verifyMfaCodeSchema validates token, code, and fingerprint.

Pipeline: Target/fingerprint/token checks, token invalidation, verifyMfaCode, identity lookup, createAccessToken, createRefreshToken, optional setResponseCookie, then a mode-specific normalizer.

Success: 200 with cookie-mode {id} plus cookies or Bearer session tokens.

Failure: 400 invalid code/input, 401 invalid token, 403 invalidated token, 404 missing identity, or 500 persistence/session failure.

View complete source
export const verifyMfaCodeRoute = withRoute({
handler: compose(
applyPayloadArgs(getMfaChallengeTokenTarget, [], 'target'),
flatMapAsync(withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
checkOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'data', 'target'],
['params', 'requestBody', 'token'],
],
'tokenInfo',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
assertValidOneTimeTokenExists,
[
['context', 'db', 'onetimetokens'],
['params', 'requestBody', 'token'],
],
'doesOneTimeTokenExist',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
invalidateOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['params', 'requestBody', 'token'],
],
'isInvalidatedSuccessfully',
),
),
),

flatMapAsync(
withLogging(
applyPayloadArgs(
verifyMfaCode,
[
['params', 'requestBody', 'code'],
['context', 'data', 'tokenInfo', 'data', 'code'],
],
'isCodeValid',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
getIdentityById,
[
['context', 'db', 'identities'],
['context', 'data', 'tokenInfo', 'data', 'identityId'],
],
'identity',
),
),
),
flatMapAsync(withLogging(createAccessToken)),
flatMapAsync(withLogging(createRefreshToken)),
lift(
tap(
withLogging(
orThrow([
[MfaInvalidCodeError, 400],
[MfaUnexpectedError, 500],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationInvalidInputError, 400],
[AuthenticationNotFoundError, 404],
[AuthenticationUnexpectedError, 500],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnprocessableEntityError, 422],
]),
),
),
),
flatMapAsync(
withLogging(
whenCookieAuth(
compose(
withLogging(setResponseCookie),
flatMapAsync(
withLogging(applyPayloadArgs(normalizeCookieLoginResponse, [['context', 'data']], 'loginResponse')),
),
),
withLogging(applyPayloadArgs(normalizeBearerLoginResponse, [['context', 'data']], 'loginResponse')),
),
),
),
lift(withLogging(orThrow([], [['context', 'data', 'loginResponse']]))),
),
method: 'POST',
path: '/auth/mfa/verify',
validators: [],
});

logoutRoute

Implementation

Endpoint: POST /auth/logout

Revoke the current session.

Access: Authenticated through isAuthenticated().

Request: Mode-selected logoutCookieSchema or logoutBearerSchema.

Pipeline: logout, then logoutTerminator.

Success: 204; cookies are cleared and a valid presented refresh record is revoked.

Failure: Authentication failure, 401 identity mismatch, or 500 revocation failure.

View complete source
export const logoutRoute = withRoute({
handler: compose(withLogging(logout), lift(withLogging(logoutTerminator))),
method: 'POST',
path: '/auth/logout',
validators: [isAuthenticated()],
});

refreshTokenRoute

Implementation

Endpoint: POST /auth/token/refresh

Rotate an access/refresh token pair.

Access: Possession of a valid refresh token; there is no route validator.

Request: refreshTokenCookieSchema reads the cookie transport; refreshTokenBearerSchema requires the body token.

Pipeline: refreshToken, optional setResponseCookie, then cookie empty-body or Bearer token normalization.

Success: Cookie mode returns 204 and rotated cookies; Bearer mode returns 200 with {accessToken, refreshToken}.

Failure: 401 invalid/reused token, 422 missing token, 400 failed revocation, or 500 persistence failure.

View complete source
export const refreshTokenRoute = withRoute({
handler: whenCookieAuth(
compose(
withLogging(refreshToken),
flatMapAsync(withLogging(setResponseCookie)),
flatMapAsync(withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'refreshResponse'))),
lift(withLogging(orThrow([], [['context', 'data', 'refreshResponse'], 204]))),
),
compose(
withLogging(refreshToken),
flatMapAsync(
withLogging(applyPayloadArgs(normalizeBearerRefreshResponse, [['context', 'data']], 'refreshResponse')),
),
lift(withLogging(orThrow([], [['context', 'data', 'refreshResponse']]))),
),
),
method: 'POST',
path: '/auth/token/refresh',
validators: [],
});

checkTokenRoute

Implementation

Endpoint: POST /auth/token/check

Validate an access or one-time token.

Access: Public; validity is established from the body token.

Request: checkTokenSchema validates token and optional target.

Pipeline: checkToken (the block, not the handler), then orThrow.

Success: 200 with the validated tokenInfo; a valid one-time token is consumed.

Failure: 400 invalid/security-check-failing token, 401 failed validation, or 500 one-time-token database failure.

View complete source
export const checkTokenRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(checkTokenBlock, [
['context', 'db', 'onetimetokens'],
['context', 'configuration', 'authSecrets'],
['context', 'request'],
['params', 'requestBody', 'token'],
['params', 'requestBody', 'target'],
]),
),
lift(
withLogging(
orThrow(
[
[AuthenticationInvalidTokenError, 400],
[AuthenticationUnauthorizedError, 401],
[AuthenticationUnexpectedDBError, 500],
],
[['context', 'data', 'tokenInfo']],
),
),
),
),
method: 'POST',
path: '/auth/token/check',
validators: [],
});

deleteRefreshTokensRoute

Implementation

Endpoint: DELETE /auth/:identityId/refresh-tokens

Revoke an identity refresh-token records.

Access: Authenticated administrator or matching identity.

Request: deleteRefreshTokensSchema validates the identityId path parameter.

Pipeline: softDeleteRefreshTokens, empty-body normalization, then orThrow.

Success: 204, including when no active refresh records match.

Failure: Authentication/authorization failure or 500 database failure.

View complete source
export const deleteRefreshTokensRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
softDeleteRefreshTokens,
[
['context', 'db', 'refreshtokens'],
['params', 'requestParams', 'identityId'],
],
'hasSoftDeletedRefreshTokens',
),
),
lift(orThrow([[AuthenticationUnexpectedDbError, 500]], [['context', 'data', 'hasSoftDeletedRefreshTokens'], 204])),
),
method: 'DELETE',
path: '/auth/:identityId/refresh-tokens',
validators: [
isAuthenticated(),
some(checkIdentityType(['admin']), isSelf(['params', 'requestParams', 'identityId'])),
],
});

loginWithOnetimeTokenRoute

Implementation

Endpoint: POST /auth/ott/login

Complete passwordless login.

Access: Public to a caller holding an active login-target one-time token.

Request: loginWithOnetimeTokenSchema validates the body token and fingerprint.

Pipeline: loginWithOnetimeToken, token invalidation, createAccessToken, createRefreshToken, optional setResponseCookie, then mode-specific normalization.

Success: 200 with cookie-mode {id} plus cookies or a Bearer session body.

Failure: 401 verification failure, 403 wrong/invalid token, 404 missing identity, or session-generation failure.

View complete source
export const loginWithOnetimeTokenRoute = withRoute({
handler: compose(
withLogging(loginWithOnetimeToken),
flatMapAsync(
withLogging(
applyPayloadArgs(
invalidateOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['params', 'requestBody', 'token'],
],
'isInvalidatedSuccessfully',
),
),
),
flatMapAsync(withLogging(createAccessToken)),
flatMapAsync(withLogging(createRefreshToken)),
flatMapAsync(
withLogging(
whenCookieAuth(
compose(
withLogging(setResponseCookie),
flatMapAsync(
withLogging(applyPayloadArgs(normalizeCookieLoginResponse, [['context', 'data']], 'loginResponse')),
),
),
withLogging(applyPayloadArgs(normalizeBearerLoginResponse, [['context', 'data']], 'loginResponse')),
),
),
),
lift(withLogging(orThrow([], [['context', 'data', 'loginResponse']]))),
),
method: 'POST',
path: '/auth/ott/login',
validators: [],
});

generateOnetimeTokenRoute

Implementation

Endpoint: POST /auth/ott/generate

Generate a one-time token for a custom flow.

Access: Authenticated administrator.

Request: No schema is composed; runtime expects JSON tokenData as an object and accepts target and fingerprint.

Pipeline: generateOnetimeToken.

Success: Default 200 with the handler’s successful Result<RouteHandlerPayload>; this legacy route has no terminator and is not mounted by authService.

Failure: 400 invalid data/insert result or 500 generation/database failure.

View complete source
export const generateOnetimeTokenRoute = withRoute({
handler: compose(withLogging(generateOnetimeToken)),
method: 'POST',
path: '/auth/ott/generate',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

restoreOnetimeTokenRoute

Implementation

Endpoint: POST /auth/ott/restore

Restore an invalidated one-time token.

Access: Authenticated administrator.

Request: No schema is composed; runtime reads body token.

Pipeline: restoreOnetimeToken.

Success: Default 200 with the handler’s successful Result<RouteHandlerPayload>; zero matching records still succeed.

Failure: 401 undecodable token, 422 non-stateful token, or 500 update failure.

View complete source
export const restoreOnetimeTokenRoute = withRoute({
handler: compose(withLogging(restoreOnetimeToken)),
method: 'POST',
path: '/auth/ott/restore',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

invalidateOnetimeTokenRoute

Implementation

Endpoint: POST /auth/ott/invalidate

Invalidate a one-time token.

Access: Authenticated administrator.

Request: No schema is composed; runtime reads token and fingerprint from pipeline context or body.

Pipeline: invalidateOnetimeToken.

Success: Default 200 with the handler’s successful Result<RouteHandlerPayload>; zero matching records still succeed.

Failure: 422 missing/invalid/non-stateful input or 500 update failure.

View complete source
export const invalidateOnetimeTokenRoute = withRoute({
handler: compose(withLogging(invalidateOnetimeToken)),
method: 'POST',
path: '/auth/ott/invalidate',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

sendVerificationEmailRoute

Implementation

Endpoint: POST /auth/:identityId/send-verification-email

Send a verification email.

Access: Authenticated administrator or matching identity.

Request: sendVerificationEmailSchema validates the identity path and an optional body fingerprint.

Pipeline: sendVerificationEmail, then sendVerificationEmailTerminator.

Success: 204 after token storage and successful mail delivery.

Failure: 400 disabled/missing configuration or email, 404 missing identity, 501 token generation failure, or 500 storage/mail failure.

View complete source
export const sendVerificationEmailRoute = withRoute({
handler: compose(withLogging(sendVerificationEmail), lift(withLogging(sendVerificationEmailTerminator))),
method: 'POST',
path: '/auth/:identityId/send-verification-email',
validators: [
isAuthenticated(),
some(checkIdentityType(['admin']), isSelf(['params', 'requestParams', 'identityId'])),
],
});

confirmEmailRoute

Implementation

Endpoint: POST /auth/confirm-email

Confirm an email-verification token.

Access: Public to a caller holding the confirmation token.

Request: confirmEmailSchema validates the body token.

Pipeline: buildCheckConfirmEmailTokenPayload, handler checkToken, confirmEmail, then confirmEmailTerminator.

Success: 204; the stored token is consumed and the identity becomes verified.

Failure: 400 invalid token, 401 failed validation, 403 bad token data, 404 missing identity, 409 already verified, or 500 persistence failure.

View complete source
export const confirmEmailRoute = withRoute({
handler: compose(
withLogging(buildCheckConfirmEmailTokenPayload),
flatMapAsync(withLogging(checkToken)),
flatMapAsync(withLogging(confirmEmail)),
lift(withLogging(confirmEmailTerminator)),
),
method: 'POST',
path: '/auth/confirm-email',
validators: [],
});

changeEmailRoute

Implementation

Endpoint: PATCH /auth/:identityId/change-email

Start an email-change flow.

Access: Authenticated administrator or matching identity.

Request: changeEmailSchema validates the path identity and new email.

Pipeline: Identity/uniqueness checks, target and request-security construction, token generation/storage, sendEmail, empty-body normalization, then orThrow.

Success: 204 after the confirmation token is mailed.

Failure: Mapped Authentication errors from 400 through 500, including 404 identity, 409 email conflict, and 422 fingerprint format.

View complete source
export const changeEmailRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
assertIdentityExists,
[
['context', 'db', 'identities'],
['params', 'requestParams', 'identityId'],
],
'doesIdentityExist',
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
mapMatchingErrorToFalse(checkEmailIsUniqueInIdentities, [AuthenticationConflictError]),
[
['context', 'db', 'identities'],
['params', 'requestBody', 'email'],
],
'isEmailUnique',
),
),
),
flatMapAsync(
ifElse(
match(Boolean, ['context', 'data', 'isEmailUnique']),
compose(
applyPayloadArgs(getChangeEmailTokenTarget, [], 'target'),
flatMapAsync(
withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint')),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildTokenVerification,
[
['context', 'request'],
['context', 'data', 'target'],
['context', 'data', 'fingerprint'],
],
'tokenVerification',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
generateOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'configuration', 'onetimeTokenSignOptions'],
['context', 'data', 'tokenVerification'],
['params', 'requestParams', 'identityId'],
['params', 'requestBody', 'email'],
],
'token',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
storeOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['context', 'data', 'token'],
],
'isStoredOneTimeToken',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
sendEmail,
[
['context', 'mailService'],
['context', 'configuration', 'verifyEmailConfig', 'sender'],
['context', 'configuration', 'verifyEmailConfig', 'emailConfig'],
['params', 'requestBody', 'email'],
['context', 'data', 'token'],
],
'hasSentEmail',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))),
),
applyPayloadArgs(noop, [[]]),
),
),
lift(
withLogging(
orThrow(
[
[AuthenticationInvalidInputError, 400],
[AuthenticationBadRequestError, 400],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationNotFoundError, 404],
[AuthenticationConflictError, 409],
[AuthenticationUnprocessableEntityError, 422],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnexpectedError, 500],
],
[['context', 'data', 'normalizedBody'], 204],
),
),
),
),
method: 'PATCH',
path: '/auth/:identityId/change-email',
validators: [
isAuthenticated(),
some(checkIdentityType(['admin']), isSelf(['params', 'requestParams', 'identityId'])),
],
});

confirmNewEmailRoute

Implementation

Endpoint: POST /auth/confirm-new-email

Confirm a new email address.

Access: Public to a caller holding the change-email token.

Request: confirmNewEmailSchema validates token and fingerprint.

Pipeline: Token target/security checks, one-time-token validation and invalidation, email uniqueness/format checks, identity update, empty-body normalization, then orThrow.

Success: 204.

Failure: Mapped Authentication errors from 400 through 500, notably 401 verification, 403 inactive token, 409 email conflict, and 404 identity.

View complete source
export const confirmNewEmailRoute = withRoute({
handler: compose(
applyPayloadArgs(getChangeEmailTokenTarget, [], 'target'),
flatMapAsync(withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildTokenVerification,
[
['context', 'request'],
['context', 'data', 'target'],
['context', 'data', 'fingerprint'],
],
'tokenVerification',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
checkOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'data', 'target'],
['params', 'requestBody', 'token'],
],
'tokenInfo',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
assertValidOneTimeTokenExists,
[
['context', 'db', 'onetimetokens'],
['params', 'requestBody', 'token'],
],
'doesOneTimeTokenExist',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
invalidateOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['params', 'requestBody', 'token'],
],
'isInvalidatedSuccessfully',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
checkEmailIsUniqueInIdentities,
[
['context', 'db', 'identities'],
['context', 'data', 'tokenInfo', 'data', 'email'],
],
'isEmailUnique',
),
),
),
flatMapAsync(
withLogging(applyPayloadArgs(isEmail, [['context', 'data', 'tokenInfo', 'data', 'email']], 'isEmail')),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildUpdateIdentityEmailAndEmailVerifiedPayload,
[['context', 'data', 'tokenInfo', 'data', 'email']],
'identityFieldsToUpdate',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
updateIdentity,
[
['context', 'db', 'identities'],
['context', 'data', 'tokenInfo', 'data', 'identityId'],
['context', 'data', 'identityFieldsToUpdate'],
],
'hasUpdatedIdentity',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))),
lift(
withLogging(
orThrow(
[
[AuthenticationInvalidInputError, 400],
[AuthenticationBadRequestError, 400],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationNotFoundError, 404],
[AuthenticationConflictError, 409],
[AuthenticationUnprocessableEntityError, 422],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnexpectedError, 500],
],
[['context', 'data', 'normalizedBody'], 204],
),
),
),
),
method: 'POST',
path: '/auth/confirm-new-email',
validators: [],
});

sendResetPasswordLinkEmailRoute

Implementation

Endpoint: POST /auth/send-reset-password-link-email

Send a password-reset link.

Access: Public.

Request: sendResetPasswordLinkEmailSchema validates the email and request-security headers.

Pipeline: Identity lookup, reset target/fingerprint/security construction, token generation/storage, sendEmail, empty-body normalization, then orThrow.

Success: 204.

Failure: Mapped Authentication errors including 404 unknown email, 422 malformed fingerprint, and 500 generation/storage/mail failure.

View complete source
export const sendResetPasswordLinkEmailRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
getIdentityIdByEmail,
[
['context', 'db', 'identities'],
['params', 'requestBody', 'email'],
],
'identityId',
),
),
flatMapAsync(applyPayloadArgs(getResetPasswordTokenTarget, [], 'target')),
flatMapAsync(withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildTokenVerification,
[
['context', 'request'],
['context', 'data', 'target'],
['context', 'data', 'fingerprint'],
],
'tokenVerification',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
generateOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'configuration', 'onetimeTokenSignOptions'],
['context', 'data', 'tokenVerification'],
['context', 'data', 'identityId'],
],
'token',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
storeOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['context', 'data', 'token'],
],
'isStoredOneTimeToken',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
sendEmail,
[
['context', 'mailService'],
['context', 'configuration', 'sendResetPasswordEmailConfig', 'sender'],
['context', 'configuration', 'sendResetPasswordEmailConfig', 'emailConfig'],
['params', 'requestBody', 'email'],
['context', 'data', 'token'],
],
'hasSentEmail',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))),
lift(
withLogging(
orThrow(
[
[AuthenticationInvalidInputError, 400],
[AuthenticationBadRequestError, 400],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationNotFoundError, 404],
[AuthenticationConflictError, 409],
[AuthenticationUnprocessableEntityError, 422],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnexpectedError, 500],
],
[['context', 'data', 'normalizedBody'], 204],
),
),
),
),
method: 'POST',
path: '/auth/send-reset-password-link-email',
validators: [],
});

completePasswordResetRoute

Implementation

Endpoint: POST /auth/reset-password

Complete password reset with a token.

Access: Public to a caller holding a valid reset token.

Request: completePasswordResetSchema validates the replacement password. Runtime also reads the reset token from the Authorization header, but that source parameter is currently commented out of the schema.

Pipeline: Token extraction/checks, identity and password comparisons, token invalidation, password hashing/update, notification email, empty-body normalization, then orThrow.

Success: 204.

Failure: Mapped Authentication errors from 400 through 500, including 401 token failure, 403 inactive token, and 404 identity.

View complete source
export const completePasswordResetRoute = withRoute({
handler: compose(
applyPayloadArgs(getResetPasswordTokenTarget, [], 'target'),
flatMapAsync(withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildTokenVerification,
[
['context', 'request'],
['context', 'data', 'target'],
['context', 'data', 'fingerprint'],
],
'tokenVerification',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
extractTokenFromAuthorizationHeader,
[['context', 'request', 'headers', 'authorization']],
'oneTimeToken',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
checkOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'data', 'target'],
['context', 'data', 'oneTimeToken'],
],
'tokenInfo',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
assertValidOneTimeTokenExists,
[
['context', 'db', 'onetimetokens'],
['context', 'data', 'oneTimeToken'],
],
'doesOneTimeTokenExist',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
getIdentityById,
[
['context', 'db', 'identities'],
['context', 'data', 'tokenInfo', 'data', 'identityId'],
],
'identity',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
compareStringAgainstHash,
[
['context', 'data', 'identity', 'password'],
['params', 'requestBody', 'password'],
],
'newValueMatches',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(assertDoesNotMatch, [['context', 'data', 'newValueMatches']], 'newValueDoesNotMatch'),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
invalidateOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['context', 'data', 'oneTimeToken'],
],
'isInvalidatedSuccessfully',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(hash, [['params', 'requestBody', 'password']], 'hashedPassword'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildUpdateIdentityPasswordPayload,
[['context', 'data', 'hashedPassword']],
'identityFieldsToUpdate',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
updateIdentity,
[
['context', 'db', 'identities'],
['context', 'data', 'tokenInfo', 'data', 'identityId'],
['context', 'data', 'identityFieldsToUpdate'],
],
'identityId',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
softDeleteRefreshTokens,
[
['context', 'db', 'refreshtokens'],
['context', 'data', 'tokenInfo', 'data', 'identityId'],
],
'hasSoftDeletedRefreshTokens',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
sendEmail,
[
['context', 'mailService'],
['context', 'configuration', 'resetPasswordSuccessConfig', 'sender'],
['context', 'configuration', 'resetPasswordSuccessConfig', 'emailConfig'],
['context', 'data', 'identity', 'email'],
],
'hasSentEmail',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))),
lift(
withLogging(
orThrow(
[
[AuthenticationInvalidInputError, 400],
[AuthenticationBadRequestError, 400],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationNotFoundError, 404],
[AuthenticationConflictError, 409],
[AuthenticationUnprocessableEntityError, 422],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnexpectedError, 500],
],
[['context', 'data', 'normalizedBody'], 204],
),
),
),
),
method: 'POST',
path: '/auth/reset-password',
validators: [],
});

changePasswordRoute

Implementation

Endpoint: PATCH /auth/:identityId/change-password

Change an authenticated identity password.

Access: Authenticated administrator or matching identity.

Request: changePasswordSchema validates path ID and current/replacement passwords.

Pipeline: Identity lookup, current/new password comparisons, hashing/update, refresh-token revocation, sendEmail, empty-body normalization, then orThrow.

Success: 204.

Failure: Mapped Authentication errors from 400 through 500, including invalid current/reused password and missing identity.

View complete source
export const changePasswordRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
getIdentityById,
[
['context', 'db', 'identities'],
['params', 'requestParams', 'identityId'],
],
'identity',
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
compareStringAgainstHash,
[
['context', 'data', 'identity', 'password'],
['params', 'requestBody', 'password'],
],
'oldValueMatches',
),
),
),
flatMapAsync(
withLogging(applyPayloadArgs(assertMatches, [['context', 'data', 'oldValueMatches']], 'assertOldValueMatches')),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
compareStringAgainstHash,
[
['context', 'data', 'identity', 'password'],
['params', 'requestBody', 'newPassword'],
],
'newValueMatches',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(assertDoesNotMatch, [['context', 'data', 'newValueMatches']], 'newValueDoesNotMatch'),
),
),
flatMapAsync(withLogging(applyPayloadArgs(hash, [['params', 'requestBody', 'newPassword']], 'hashedPassword'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildUpdateIdentityPasswordPayload,
[['context', 'data', 'hashedPassword']],
'identityFieldsToUpdate',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
updateIdentity,
[
['context', 'db', 'identities'],
['params', 'requestParams', 'identityId'],
['context', 'data', 'identityFieldsToUpdate'],
],
'identityId',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
softDeleteRefreshTokens,
[
['context', 'db', 'refreshtokens'],
['params', 'requestParams', 'identityId'],
],
'hasSoftDeletedRefreshTokens',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
sendEmail,
[
['context', 'mailService'],
['context', 'configuration', 'changePasswordConfig', 'sender'],
['context', 'configuration', 'changePasswordConfig', 'emailConfig'],
['context', 'data', 'identity', 'email'],
],
'hasSentEmail',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))),
lift(
withLogging(
orThrow(
[
[AuthenticationInvalidInputError, 400],
[AuthenticationBadRequestError, 400],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationNotFoundError, 404],
[AuthenticationConflictError, 409],
[AuthenticationUnprocessableEntityError, 422],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnexpectedError, 500],
],
[['context', 'data', 'normalizedBody'], 204],
),
),
),
),
method: 'PATCH',
path: '/auth/:identityId/change-password',
validators: [
isAuthenticated(),
some(checkIdentityType(['admin']), isSelf(['params', 'requestParams', 'identityId'])),
],
});

deactivateRoute

Implementation

Endpoint: POST /auth/deactivate

Deactivate an identity.

Access: Authenticated administrator or the body identityId.

Request: deactivateSchema validates the JSON identity ID.

Pipeline: Identity lookup and verified-email guard, deactivation update, refresh-token revocation, mode-selected access-token validation, conditional email, empty-body normalization, then orThrow.

Success: 204.

Failure: Authentication/authorization failure or mapped Authentication errors from 400 through 500.

View complete source
export const deactivateRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
getIdentityById,
[
['context', 'db', 'identities'],
['params', 'requestBody', 'identityId'],
],
'identity',
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(isEmailVerified, [['context', 'data', 'identity', 'emailVerified']], 'isEmailVerified'),
),
),
flatMapAsync(withLogging(applyPayloadArgs(buildUpdateIdentityDeactivatedPayload, [], 'identityFieldsToUpdate'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
updateIdentity,
[
['context', 'db', 'identities'],
['params', 'requestBody', 'identityId'],
['context', 'data', 'identityFieldsToUpdate'],
],
'identityId',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
softDeleteRefreshTokens,
[
['context', 'db', 'refreshtokens'],
['params', 'requestBody', 'identityId'],
],
'hasSoftDeletedRefreshTokens',
),
),
),
flatMapAsync(
withLogging(
whenCookieAuth(
withLogging(applyPayloadArgs(noop, [['context', 'request', 'cookies', 'accessToken']], 'accessToken')),
withLogging(
applyPayloadArgs(
extractTokenFromAuthorizationHeader,
[['context', 'request', 'headers', 'authorization']],
'accessToken',
),
),
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
checkTokenBlock,
[
['context', 'db', 'onetimetokens'],
['context', 'configuration', 'authSecrets'],
['context', 'request'],
['context', 'data', 'accessToken'],
],
'checkTokenResult',
),
),
),
flatMapAsync(
ifElse(
(input: RouteHandlerPayload) =>
input?.params?.requestBody?.identityId === input?.context?.data?.checkTokenResult?.tokenInfo?.identityId,
compose(
withLogging(
applyPayloadArgs(
sendEmail,
[
['context', 'mailService'],
['context', 'configuration', 'deactivateIdentityEmailConfig', 'sender'],
['context', 'configuration', 'deactivateIdentityEmailConfig', 'emailConfig'],
['context', 'data', 'identity', 'email'],
],
'hasSentEmail',
),
),
),
async (input) => ok(input),
),
),
flatMapAsync(withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))),
lift(
withLogging(
orThrow(
[
[AuthenticationInvalidInputError, 400],
[AuthenticationBadRequestError, 400],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationNotFoundError, 404],
[AuthenticationConflictError, 409],
[AuthenticationUnprocessableEntityError, 422],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnexpectedError, 500],
],
[['context', 'data', 'normalizedBody'], 204],
),
),
),
),
method: 'POST',
path: '/auth/deactivate',
validators: [isAuthenticated(), some(checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'identityId']))],
});

activateRoute

Implementation

Endpoint: POST /auth/activate

Reactivate an identity.

Access: Authenticated administrator.

Request: activateSchema validates the JSON identity ID.

Pipeline: Identity lookup, verified-email guard, activation update, empty-body normalization, then orThrow.

Success: 204.

Failure: Authentication/administrator failure or mapped Authentication errors from 400 through 500.

View complete source
export const activateRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
getIdentityById,
[
['context', 'db', 'identities'],
['params', 'requestBody', 'identityId'],
],
'identity',
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(isEmailVerified, [['context', 'data', 'identity', 'emailVerified']], 'isEmailVerified'),
),
),
flatMapAsync(withLogging(applyPayloadArgs(buildUpdateIdentityActivatedPayload, [], 'identityFieldsToUpdate'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
updateIdentity,
[
['context', 'db', 'identities'],
['params', 'requestBody', 'identityId'],
['context', 'data', 'identityFieldsToUpdate'],
],
'identityId',
),
),
),
flatMapAsync(withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))),
lift(
withLogging(
orThrow(
[
[AuthenticationInvalidInputError, 400],
[AuthenticationBadRequestError, 400],
[AuthenticationUnauthorizedError, 401],
[AuthenticationForbiddenError, 403],
[AuthenticationNotFoundError, 404],
[AuthenticationConflictError, 409],
[AuthenticationUnprocessableEntityError, 422],
[AuthenticationUnexpectedDbError, 500],
[AuthenticationUnexpectedError, 500],
],
[['context', 'data', 'normalizedBody'], 204],
),
),
),
),
method: 'POST',
path: '/auth/activate',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});