@ackplus/nest-auth 1.1.22 → 1.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/lib/admin-console/static/index.html +3 -2
- package/src/lib/auth/auth.module.d.ts.map +1 -1
- package/src/lib/auth/auth.module.js +2 -0
- package/src/lib/auth/guards/auth.guard.d.ts.map +1 -1
- package/src/lib/auth/guards/auth.guard.js +24 -1
- package/src/lib/auth/services/auth-session-event-listener.service.d.ts +16 -0
- package/src/lib/auth/services/auth-session-event-listener.service.d.ts.map +1 -0
- package/src/lib/auth/services/auth-session-event-listener.service.js +52 -0
- package/src/lib/auth/services/auth.service.d.ts.map +1 -1
- package/src/lib/auth/services/auth.service.js +37 -27
- package/src/lib/core/providers/apple-auth.provider.d.ts +1 -1
- package/src/lib/core/providers/apple-auth.provider.d.ts.map +1 -1
- package/src/lib/core/providers/apple-auth.provider.js +2 -2
- package/src/lib/core/providers/facebook-auth.provider.d.ts +1 -1
- package/src/lib/core/providers/facebook-auth.provider.d.ts.map +1 -1
- package/src/lib/core/providers/facebook-auth.provider.js +2 -2
- package/src/lib/core/providers/google-auth.provider.d.ts +9 -1
- package/src/lib/core/providers/google-auth.provider.d.ts.map +1 -1
- package/src/lib/core/providers/google-auth.provider.js +53 -10
- package/src/lib/core/services/auth-config.service.d.ts.map +1 -1
- package/src/lib/core/services/auth-config.service.js +3 -0
- package/src/lib/session/interfaces/session-repository.interface.d.ts.map +1 -1
- package/src/lib/user/services/user.service.d.ts.map +1 -1
- package/src/lib/user/services/user.service.js +25 -6
package/package.json
CHANGED
|
@@ -2426,7 +2426,8 @@ const googleAccessToken = googleResponse.getAuthResponse().access_token;
|
|
|
2426
2426
|
const { data } = await api.post('/auth/login', {
|
|
2427
2427
|
providerName: 'google',
|
|
2428
2428
|
credentials: {
|
|
2429
|
-
|
|
2429
|
+
token: googleAccessToken,
|
|
2430
|
+
type: 'access' // or 'id' for ID Tokens
|
|
2430
2431
|
},
|
|
2431
2432
|
createUserIfNotExists: true // Auto-create user
|
|
2432
2433
|
});
|
|
@@ -5301,7 +5302,7 @@ export class OnboardingService {
|
|
|
5301
5302
|
- Header mode (default): Returns new tokens in response body
|
|
5302
5303
|
- Cookie mode: Sets new tokens in HTTP-only cookies and returns success message`,operationId:"AuthController_refreshToken",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/RefreshTokenRequestDto"}}}},responses:{200:{description:"Header mode: Returns message + tokens in body",content:{"application/json":{schema:{$ref:"#/components/schemas/AuthWithTokensResponseDto"}}}}},summary:"Refresh Token",tags:["Auth"]}},"/auth/send-2fa-code":{post:{operationId:"AuthController_send2faCode",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Send 2FA Code",tags:["Auth"]}},"/auth/verify-2fa":{post:{description:`Verify two-factor authentication. Response format depends on accessTokenType configuration:
|
|
5303
5304
|
- Header mode (default): Returns tokens in response body
|
|
5304
|
-
- Cookie mode: Sets tokens in HTTP-only cookies and returns success message`,operationId:"AuthController_verify2fa",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/Verify2faRequestDto"}}}},responses:{200:{description:"Header mode: Returns message + tokens in body",content:{"application/json":{schema:{$ref:"#/components/schemas/Verify2faWithTokensResponseDto"}}}}},summary:"Verify 2FA",tags:["Auth"]}},"/auth/logout":{post:{operationId:"AuthController_logout",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Logout",tags:["Auth"]}},"/auth/logout-all":{post:{operationId:"AuthController_logoutAll",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Logout All",tags:["Auth"]}},"/auth/change-password":{post:{operationId:"AuthController_changePassword",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ChangePasswordRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/AuthWithTokensResponseDto"}}}}},summary:"Change Password",tags:["Auth"]}},"/auth/forgot-password":{post:{operationId:"AuthController_forgotPassword",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ForgotPasswordRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Forgot Password",tags:["Auth"]}},"/auth/verify-forgot-password-otp":{post:{operationId:"AuthController_verifyForgotPasswordOtp",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/VerifyForgotPasswordOtpRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/VerifyOtpResponseDto"}}}}},summary:"Verify Forgot Password OTP and get reset token",tags:["Auth"]}},"/auth/reset-password":{post:{operationId:"AuthController_resetPassword",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ResetPasswordRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Reset Password (Legacy - using OTP)",tags:["Auth"]}},"/auth/reset-password-with-token":{post:{operationId:"AuthController_resetPasswordWithToken",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ResetPasswordWithTokenRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Reset Password with Token",tags:["Auth"]}},"/auth/user":{get:{operationId:"AuthController_getUser",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/UserResponseDto"}}}}},summary:"Get Logged In User",tags:["Auth"]}},"/auth/send-email-verification":{post:{operationId:"AuthController_sendEmailVerification",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/SendEmailVerificationRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Send Email Verification",tags:["Auth"]}},"/auth/verify-email":{post:{operationId:"AuthController_verifyEmail",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/VerifyEmailRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Verify Email",tags:["Auth"]}},"/auth/client-config":{get:{description:"Returns backend configuration for frontend clients. Includes enabled auth methods, registration settings, MFA options, tenant configuration, and SSO providers. Can be customized via clientConfig.factory in AuthModuleOptions.",operationId:"AuthController_getClientConfig",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/ClientConfigResponseDto"}}}}},summary:"Get Client Configuration",tags:["Auth"]}},"/auth/callback/{provider}":{get:{description:"OAuth callback endpoint for SSO providers. Exchanges authorization code for access token and returns raw SSO user info. Returns HTML page that posts SSO data to parent window and auto-closes.",operationId:"AuthController_ssoCallback",parameters:[{name:"provider",required:!0,in:"path",schema:{type:"string"}}],responses:{200:{description:""}},summary:"SSO Callback",tags:["Auth"]}},"/auth/mfa/status":{get:{operationId:"MfaController_getStatus",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MfaStatusResponseDto"}}}}},summary:"Get MFA status for the current user",tags:["Mfa"]}},"/auth/mfa/toggle":{post:{operationId:"MfaController_toggleMfa",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ToggleMfaRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Enable or disable MFA for the current user",tags:["Mfa"]}},"/auth/mfa/devices":{get:{operationId:"MfaController_listDevices",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{type:"array",items:{$ref:"#/components/schemas/MfaDeviceDto"}}}}}},summary:"List registered MFA devices",tags:["Mfa"]}},"/auth/mfa/devices/{deviceId}":{delete:{operationId:"MfaController_removeDevice",parameters:[{name:"deviceId",required:!0,in:"path",schema:{type:"string"}}],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Remove a registered MFA device",tags:["Mfa"]}},"/auth/mfa/send-mfa-code":{post:{operationId:"MfaController_sendMfaCode",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/SendMfaCodeRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Send MFA Code",tags:["Mfa"]}},"/auth/mfa/setup-totp":{post:{operationId:"MfaController_setupTotp",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Setup TOTP Device",tags:["Mfa"]}},"/auth/mfa/verify-totp-setup":{post:{operationId:"MfaController_verifyTotpSetup",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/VerifyTotpSetupRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Verify TOTP Setup",tags:["Mfa"]}},"/auth/mfa/generate-recovery-code":{post:{operationId:"MfaController_generateRecoveryCodes",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Generate Recovery Codes",tags:["Mfa"]}},"/auth/mfa/reset-totp":{post:{operationId:"MfaController_resetTotp",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Reset TOTP Device",tags:["Mfa"]}}},Jet={title:"@ackplus/nest-auth API",description:"OpenAPI specification generated from the Nest Auth module",version:"1.1.15",contact:{}},Xet=[],Zet=[],Qet={securitySchemes:{bearer:{scheme:"bearer",bearerFormat:"JWT",type:"http"}},schemas:{SignupRequestDto:{type:"object",properties:{email:{type:"string",description:"User email address (required if phone not provided)",example:"user@example.com"},phone:{type:"string",description:"User phone number (required if email not provided)",example:"+1234567890"},password:{type:"string",description:"User password",example:"SecurePass123!",minLength:8},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}},required:["password"]},UserResponseDto:{type:"object",properties:{id:{type:"string",description:"User unique identifier",example:"123e4567-e89b-12d3-a456-426614174000"},email:{type:"string",description:"User email address",example:"user@example.com"},phone:{type:"string",description:"User phone number",example:"+1234567890"},isVerified:{type:"boolean",description:"Email verification status",example:!0},metadata:{type:"object",description:"Additional user metadata",example:{firstName:"John",lastName:"Doe"}}},required:["id","isVerified"]},AuthWithTokensResponseDto:{type:"object",properties:{accessToken:{type:"string",description:"JWT access token (short-lived)",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJpYXQiOjE2OTk5OTk5OTksImV4cCI6MTY5OTk5OTk5OX0.xyz"},refreshToken:{type:"string",description:"JWT refresh token (long-lived)",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJ0eXBlIjoicmVmcmVzaCIsImlhdCI6MTY5OTk5OTk5OX0.abc"},message:{type:"string",description:"Success message (added by controller based on configuration)",example:"Login successful"},isRequiresMfa:{type:"boolean",description:"Whether multi-factor authentication is required",example:!1},user:{description:"User information",allOf:[{$ref:"#/components/schemas/UserResponseDto"}]}},required:["accessToken","refreshToken","isRequiresMfa"]},EmailCredentialsDto:{type:"object",properties:{email:{type:"string",description:"User email address",example:"user@example.com"},password:{type:"string",description:"User password",example:"SecurePass123!",minLength:8}},required:["email","password"]},PhoneCredentialsDto:{type:"object",properties:{phone:{type:"string",description:"User phone number",example:"+1234567890"},password:{type:"string",description:"User password",example:"SecurePass123!",minLength:8}},required:["phone","password"]},SocialCredentialsDto:{type:"object",properties:{accessToken:{type:"string",description:"OAuth token or ID token from social provider",example:"ya29.a0AfH6SMBx1234567890abcdefghijklmnop"}},required:["accessToken"]},LoginRequestDto:{type:"object",properties:{providerName:{type:"string",description:"Authentication provider name",example:"email",enum:["email","phone","google","facebook","apple","github"],default:"email"},credentials:{description:"Login credentials - type varies by provider",examples:{emailLogin:{summary:"Email Login",value:{email:"user@example.com",password:"SecurePass123!"}},phoneLogin:{summary:"Phone Login",value:{phone:"+1234567890",password:"SecurePass123!"}},socialLogin:{summary:"Social Login (Google/Facebook/etc)",value:{token:"ya29.a0AfH6SMBx..."}}},oneOf:[{$ref:"#/components/schemas/EmailCredentialsDto"},{$ref:"#/components/schemas/PhoneCredentialsDto"},{$ref:"#/components/schemas/SocialCredentialsDto"}]},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"},createUserIfNotExists:{type:"boolean",description:"Auto-create user if not exists (for social auth)",default:!1}}},RefreshTokenRequestDto:{type:"object",properties:{refreshToken:{type:"string",description:"Refresh token to obtain new access token",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJ0eXBlIjoicmVmcmVzaCJ9.abc123"}},required:["refreshToken"]},MessageResponseDto:{type:"object",properties:{message:{type:"string",description:"Response message"}},required:["message"]},MFAMethodEnum:{type:"string",enum:["totp","sms","email"],description:"MFA method used"},Verify2faRequestDto:{type:"object",properties:{method:{description:"MFA method used",example:"totp",allOf:[{$ref:"#/components/schemas/MFAMethodEnum"}]},otp:{type:"string",description:"One-time password code",example:"123456",minLength:6,maxLength:8},rememberDevice:{type:"boolean",description:"Whether to trust this device for future logins",example:!0}},required:["method","otp"]},Verify2faWithTokensResponseDto:{type:"object",properties:{accessToken:{type:"string",description:"JWT access token (short-lived)",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJpYXQiOjE2OTk5OTk5OTksImV4cCI6MTY5OTk5OTk5OX0.xyz"},refreshToken:{type:"string",description:"JWT refresh token (long-lived)",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJ0eXBlIjoicmVmcmVzaCIsImlhdCI6MTY5OTk5OTk5OX0.abc"},message:{type:"string",description:"Verification success message (added by controller)",example:"2FA verification successful"}},required:["accessToken","refreshToken"]},ChangePasswordRequestDto:{type:"object",properties:{currentPassword:{type:"string",description:"Current password",example:"DemoOwner1!",minLength:8},newPassword:{type:"string",description:"New password",example:"DemoOwner1!New",minLength:8}},required:["currentPassword","newPassword"]},ForgotPasswordRequestDto:{type:"object",properties:{email:{type:"string",description:"User email address (required if phone not provided)",example:"user@example.com"},phone:{type:"string",description:"User phone number (required if email not provided)",example:"+1234567890"},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}}},VerifyForgotPasswordOtpRequestDto:{type:"object",properties:{email:{type:"string",description:"User email address (required if phone not provided)",example:"user@example.com"},phone:{type:"string",description:"User phone number (required if email not provided)",example:"+1234567890"},otp:{type:"string",description:"One-time password code received via email or SMS",example:"123456",minLength:6,maxLength:8},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}},required:["otp"]},VerifyOtpResponseDto:{type:"object",properties:{message:{type:"string",description:"Success message"},resetToken:{type:"string",description:"Password reset token - use this to reset password"}},required:["message"]},ResetPasswordRequestDto:{type:"object",properties:{email:{type:"string",description:"User email address (required if phone not provided)",example:"user@example.com"},phone:{type:"string",description:"User phone number (required if email not provided)",example:"+1234567890"},otp:{type:"string",description:"One-time password (OTP) received via email or SMS",example:"123456",minLength:6,maxLength:8},newPassword:{type:"string",description:"New password",example:"NewSecurePass123!",minLength:8},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}},required:["otp","newPassword"]},ResetPasswordWithTokenRequestDto:{type:"object",properties:{token:{type:"string",description:"Password reset token (JWT) received after OTP verification",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoicGFzc3dvcmQtcmVzZXQifQ.xyz"},newPassword:{type:"string",description:"New password",example:"NewSecurePass123!",minLength:8}},required:["token","newPassword"]},SendEmailVerificationRequestDto:{type:"object",properties:{tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}}},VerifyEmailRequestDto:{type:"object",properties:{otp:{type:"string",description:"One-time password code received via email",example:"123456",minLength:6,maxLength:8},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}},required:["otp"]},EmailAuthConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!0}},required:["enabled"]},PhoneAuthConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!1}},required:["enabled"]},RegistrationConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!0,description:"Whether user registration is enabled"},requireInvitation:{type:"boolean",example:!1,description:"Whether registration requires an invitation"},collectProfileFields:{type:"array",description:"Additional profile fields to collect during registration",items:{type:"object",properties:{id:{type:"string"},label:{type:"string"},required:{type:"boolean"},type:{type:"string",enum:["text","email","phone","select","checkbox","password"]},placeholder:{type:"string"},options:{type:"array",items:{type:"object",properties:{label:{type:"string"},value:{type:"string"}}}}}}}},required:["enabled"]},MfaConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!0},methods:{example:["email","totp"],type:"array",items:{type:"array"}},allowUserToggle:{type:"boolean",example:!0},allowMethodSelection:{type:"boolean",example:!0}},required:["enabled"]},TenantOptionDto:{type:"object",properties:{id:{type:"string"},name:{type:"string"},slug:{type:"string"},isActive:{type:"boolean"},metadata:{type:"object"}},required:["id","name","slug","isActive"]},TenantsConfigDto:{type:"object",properties:{mode:{type:"string",example:"single",enum:["single","multi"]},defaultTenantId:{type:"string",nullable:!0},options:{type:"array",items:{$ref:"#/components/schemas/TenantOptionDto"}}},required:["mode"]},SsoProviderConfigDto:{type:"object",properties:{id:{type:"string"},name:{type:"string"},logoUrl:{type:"string"},authorizationUrl:{type:"string"},clientId:{type:"string"},hint:{type:"string"}},required:["id","name"]},SsoConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!1},providers:{type:"array",items:{$ref:"#/components/schemas/SsoProviderConfigDto"}}},required:["enabled"]},UiConfigDto:{type:"object",properties:{brandName:{type:"string"},brandColor:{type:"string"},logoUrl:{type:"string"},backgroundImageUrl:{type:"string"}}},ClientConfigResponseDto:{type:"object",properties:{emailAuth:{$ref:"#/components/schemas/EmailAuthConfigDto"},phoneAuth:{$ref:"#/components/schemas/PhoneAuthConfigDto"},registration:{$ref:"#/components/schemas/RegistrationConfigDto"},mfa:{$ref:"#/components/schemas/MfaConfigDto"},tenants:{$ref:"#/components/schemas/TenantsConfigDto"},sso:{$ref:"#/components/schemas/SsoConfigDto"},ui:{$ref:"#/components/schemas/UiConfigDto"}},required:["emailAuth","phoneAuth","registration","mfa","tenants","sso"]},MfaDeviceDto:{type:"object",properties:{id:{type:"string",description:"Unique identifier of the MFA device",example:"4b3c9c9c-9a9d-4d1e-8d9f-123456789abc"},deviceName:{type:"string",description:"Friendly name of the registered device",example:"Work laptop"},method:{type:"string",description:"MFA method this device supports",enum:["totp","sms","email"],example:"totp"},lastUsedAt:{format:"date-time",type:"string",description:"Timestamp of when the device was last used",example:"2024-05-20T12:34:56.000Z"},verified:{type:"boolean",description:"Whether the device setup has been verified",example:!0},createdAt:{format:"date-time",type:"string",description:"Timestamp of when the device was registered",example:"2024-05-18T10:15:00.000Z"}},required:["id","deviceName","method","verified"]},MfaStatusResponseDto:{type:"object",properties:{isEnabled:{type:"boolean",description:"Whether MFA is currently enabled for the user",example:!0},enabledMethods:{type:"array",description:"MFA methods currently active for the user",example:["email","totp"],items:{type:"string",enum:["totp","sms","email"]}},availableMethods:{type:"array",description:"All MFA methods available to the user based on backend configuration",example:["email","totp"],items:{type:"string",enum:["totp","sms","email"]}},allowUserToggle:{type:"boolean",description:"Indicates if MFA toggling is allowed for the user",example:!0},allowMethodSelection:{type:"boolean",description:"Indicates if users can choose their preferred MFA method",example:!0},totpDevices:{description:"Registered TOTP devices for the user",type:"array",items:{$ref:"#/components/schemas/MfaDeviceDto"}},hasRecoveryCode:{type:"boolean",description:"Whether a recovery code has been generated for the user",example:!1}},required:["isEnabled","enabledMethods","availableMethods","allowUserToggle","allowMethodSelection","totpDevices","hasRecoveryCode"]},ToggleMfaRequestDto:{type:"object",properties:{enabled:{type:"boolean",description:"Whether MFA should be enabled for the current user",example:!0}},required:["enabled"]},SendMfaCodeRequestDto:{type:"object",properties:{method:{description:"MFA delivery method",example:"email",examples:{email:{value:"email",description:"Send OTP via email"},sms:{value:"sms",description:"Send OTP via SMS"},totp:{value:"totp",description:"Use authenticator app (TOTP)"}},allOf:[{$ref:"#/components/schemas/MFAMethodEnum"}]}},required:["method"]},VerifyTotpSetupRequestDto:{type:"object",properties:{otp:{type:"string",description:"The TOTP code from authenticator app",example:"123456",minLength:6,maxLength:6},secret:{type:"string",description:"Secret key from TOTP setup",example:"JBSWY3DPEHPK3PXP"}},required:["otp","secret"]}}},ett={openapi:Ket,paths:Yet,info:Jet,tags:Xet,servers:Zet,components:Qet},fg=({content:e})=>A.jsx(vJe,{remarkPlugins:[IZe],components:{code({node:t,inline:r,className:n,children:a,...i}){const s=/language-(\w+)/.exec(n||"");return!r&&s?A.jsx(Boe,{...i,style:zet,language:s[1],PreTag:"div",customStyle:{margin:0,borderRadius:"0.5rem",fontSize:"0.875rem"},children:String(a).replace(/\n$/,"")}):A.jsx("code",{...i,className:`${n} bg-gray-100 text-gray-800 rounded px-1 py-0.5 text-sm font-mono`,children:a})},table({children:t}){return A.jsx("div",{className:"overflow-x-auto my-4 border border-gray-200 rounded-lg",children:A.jsx("table",{className:"min-w-full divide-y divide-gray-200",children:t})})},thead({children:t}){return A.jsx("thead",{className:"bg-gray-50",children:t})},th({children:t}){return A.jsx("th",{scope:"col",className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:t})},td({children:t}){return A.jsx("td",{className:"px-6 py-4 whitespace-nowrap text-sm text-gray-500 border-t border-gray-200",children:t})},a({href:t,children:r}){return A.jsx("a",{href:t,className:"text-primary-600 hover:text-primary-800 hover:underline",target:"_blank",rel:"noopener noreferrer",children:r})},h2({children:t}){return A.jsx("h2",{className:"text-2xl font-bold text-gray-900 mt-8 mb-4 pb-2 border-b border-gray-200",children:t})},h3({children:t}){return A.jsx("h3",{className:"text-xl font-semibold text-gray-900 mt-6 mb-3",children:t})},p({children:t}){return A.jsx("p",{className:"text-gray-700 leading-relaxed mb-4",children:t})},ul({children:t}){return A.jsx("ul",{className:"list-disc list-inside space-y-1 mb-4 text-gray-700",children:t})},li({children:t}){return A.jsx("li",{className:"ml-4",children:t})},blockquote({children:t}){return A.jsx("blockquote",{className:"border-l-4 border-primary-500 pl-4 py-1 my-4 bg-primary-50 text-gray-700 italic rounded-r",children:t})}},children:e}),ttt=()=>{const[e,t]=te.useState(!1),[r,n]=te.useState(null),[a,i]=te.useState("swagger");te.useEffect(()=>{const l=ett||{};!l||!l.paths||Object.keys(l.paths||{}).length===0?t(!0):n(l)},[]);const s=()=>{if(!r)return;const l=JSON.stringify(r,null,2),u=new Blob([l],{type:"application/json"}),c=URL.createObjectURL(u),d=document.createElement("a");d.href=c,d.download="nest-auth-api.json",document.body.appendChild(d),d.click(),document.body.removeChild(d),URL.revokeObjectURL(c)},o=[{id:"swagger",label:"Interactive API",icon:vR},{id:"config",label:"Configuration",icon:iSe},{id:"examples",label:"Examples",icon:GV},{id:"events",label:"Events",icon:cSe},{id:"api-reference",label:"API Reference",icon:GEe},{id:"services",label:"Services",icon:GV}];return A.jsxs("div",{className:"space-y-6",children:[A.jsx(hm,{title:"API Documentation",description:"Comprehensive guide and interactive API documentation.",action:a==="swagger"&&A.jsxs("button",{onClick:s,className:"btn-secondary flex items-center gap-2",disabled:e,children:[A.jsx(XEe,{className:"w-4 h-4"}),"Download JSON"]})}),A.jsx("div",{className:"border-b border-gray-200",children:A.jsx("nav",{className:"-mb-px flex space-x-8","aria-label":"Tabs",children:o.map(l=>{const u=l.icon;return A.jsxs("button",{onClick:()=>i(l.id),className:`
|
|
5305
|
+
- Cookie mode: Sets tokens in HTTP-only cookies and returns success message`,operationId:"AuthController_verify2fa",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/Verify2faRequestDto"}}}},responses:{200:{description:"Header mode: Returns message + tokens in body",content:{"application/json":{schema:{$ref:"#/components/schemas/Verify2faWithTokensResponseDto"}}}}},summary:"Verify 2FA",tags:["Auth"]}},"/auth/logout":{post:{operationId:"AuthController_logout",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Logout",tags:["Auth"]}},"/auth/logout-all":{post:{operationId:"AuthController_logoutAll",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Logout All",tags:["Auth"]}},"/auth/change-password":{post:{operationId:"AuthController_changePassword",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ChangePasswordRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/AuthWithTokensResponseDto"}}}}},summary:"Change Password",tags:["Auth"]}},"/auth/forgot-password":{post:{operationId:"AuthController_forgotPassword",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ForgotPasswordRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Forgot Password",tags:["Auth"]}},"/auth/verify-forgot-password-otp":{post:{operationId:"AuthController_verifyForgotPasswordOtp",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/VerifyForgotPasswordOtpRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/VerifyOtpResponseDto"}}}}},summary:"Verify Forgot Password OTP and get reset token",tags:["Auth"]}},"/auth/reset-password":{post:{operationId:"AuthController_resetPassword",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ResetPasswordRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Reset Password (Legacy - using OTP)",tags:["Auth"]}},"/auth/reset-password-with-token":{post:{operationId:"AuthController_resetPasswordWithToken",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ResetPasswordWithTokenRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Reset Password with Token",tags:["Auth"]}},"/auth/user":{get:{operationId:"AuthController_getUser",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/UserResponseDto"}}}}},summary:"Get Logged In User",tags:["Auth"]}},"/auth/send-email-verification":{post:{operationId:"AuthController_sendEmailVerification",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/SendEmailVerificationRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Send Email Verification",tags:["Auth"]}},"/auth/verify-email":{post:{operationId:"AuthController_verifyEmail",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/VerifyEmailRequestDto"}}}},responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MessageResponseDto"}}}}},summary:"Verify Email",tags:["Auth"]}},"/auth/client-config":{get:{description:"Returns backend configuration for frontend clients. Includes enabled auth methods, registration settings, MFA options, tenant configuration, and SSO providers. Can be customized via clientConfig.factory in AuthModuleOptions.",operationId:"AuthController_getClientConfig",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/ClientConfigResponseDto"}}}}},summary:"Get Client Configuration",tags:["Auth"]}},"/auth/callback/{provider}":{get:{description:"OAuth callback endpoint for SSO providers. Exchanges authorization code for access token and returns raw SSO user info. Returns HTML page that posts SSO data to parent window and auto-closes.",operationId:"AuthController_ssoCallback",parameters:[{name:"provider",required:!0,in:"path",schema:{type:"string"}}],responses:{200:{description:""}},summary:"SSO Callback",tags:["Auth"]}},"/auth/mfa/status":{get:{operationId:"MfaController_getStatus",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{$ref:"#/components/schemas/MfaStatusResponseDto"}}}}},summary:"Get MFA status for the current user",tags:["Mfa"]}},"/auth/mfa/toggle":{post:{operationId:"MfaController_toggleMfa",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ToggleMfaRequestDto"}}}},responses:{200:{description:""}},summary:"Enable or disable MFA for the current user",tags:["Mfa"]}},"/auth/mfa/devices":{get:{operationId:"MfaController_listDevices",parameters:[],responses:{200:{description:"",content:{"application/json":{schema:{type:"array",items:{$ref:"#/components/schemas/MfaDeviceDto"}}}}}},summary:"List registered MFA devices",tags:["Mfa"]}},"/auth/mfa/devices/{deviceId}":{delete:{operationId:"MfaController_removeDevice",parameters:[{name:"deviceId",required:!0,in:"path",schema:{type:"string"}}],responses:{200:{description:""}},summary:"Remove a registered MFA device",tags:["Mfa"]}},"/auth/mfa/send-mfa-code":{post:{operationId:"MfaController_sendMfaCode",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/SendMfaCodeRequestDto"}}}},responses:{200:{description:""}},summary:"Send MFA Code",tags:["Mfa"]}},"/auth/mfa/setup-totp":{post:{operationId:"MfaController_setupTotp",parameters:[],responses:{200:{description:""}},summary:"Setup TOTP Device",tags:["Mfa"]}},"/auth/mfa/verify-totp-setup":{post:{operationId:"MfaController_verifyTotpSetup",parameters:[],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/VerifyTotpSetupRequestDto"}}}},responses:{200:{description:""}},summary:"Verify TOTP Setup",tags:["Mfa"]}},"/auth/mfa/generate-recovery-code":{post:{operationId:"MfaController_generateRecoveryCodes",parameters:[],responses:{200:{description:""}},summary:"Generate Recovery Codes",tags:["Mfa"]}},"/auth/mfa/reset-totp":{post:{operationId:"MfaController_resetTotp",parameters:[],responses:{200:{description:""}},summary:"Reset TOTP Device",tags:["Mfa"]}}},Jet={title:"@ackplus/nest-auth API",description:"OpenAPI specification generated from the Nest Auth module",version:"1.1.18",contact:{}},Xet=[],Zet=[],Qet={securitySchemes:{bearer:{scheme:"bearer",bearerFormat:"JWT",type:"http"}},schemas:{SignupRequestDto:{type:"object",properties:{email:{type:"string",description:"User email address (required if phone not provided)",example:"user@example.com"},phone:{type:"string",description:"User phone number (required if email not provided)",example:"+1234567890"},password:{type:"string",description:"User password",example:"SecurePass123!",minLength:8},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}},required:["password"]},UserResponseDto:{type:"object",properties:{id:{type:"string",description:"User unique identifier",example:"123e4567-e89b-12d3-a456-426614174000"},email:{type:"string",description:"User email address",example:"user@example.com"},phone:{type:"string",description:"User phone number",example:"+1234567890"},isVerified:{type:"boolean",description:"Email verification status",example:!0},metadata:{type:"object",description:"Additional user metadata",example:{firstName:"John",lastName:"Doe"}}},required:["id","isVerified"]},AuthWithTokensResponseDto:{type:"object",properties:{accessToken:{type:"string",description:"JWT access token (short-lived)",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJpYXQiOjE2OTk5OTk5OTksImV4cCI6MTY5OTk5OTk5OX0.xyz"},refreshToken:{type:"string",description:"JWT refresh token (long-lived)",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJ0eXBlIjoicmVmcmVzaCIsImlhdCI6MTY5OTk5OTk5OX0.abc"},message:{type:"string",description:"Success message (added by controller based on configuration)",example:"Login successful"},isRequiresMfa:{type:"boolean",description:"Whether multi-factor authentication is required",example:!1},user:{description:"User information",allOf:[{$ref:"#/components/schemas/UserResponseDto"}]}},required:["accessToken","refreshToken","isRequiresMfa"]},EmailCredentialsDto:{type:"object",properties:{email:{type:"string",description:"User email address",example:"user@example.com"},password:{type:"string",description:"User password",example:"SecurePass123!",minLength:8}},required:["email","password"]},PhoneCredentialsDto:{type:"object",properties:{phone:{type:"string",description:"User phone number",example:"+1234567890"},password:{type:"string",description:"User password",example:"SecurePass123!",minLength:8}},required:["phone","password"]},SocialCredentialsDto:{type:"object",properties:{accessToken:{type:"string",description:"OAuth token or ID token from social provider",example:"ya29.a0AfH6SMBx1234567890abcdefghijklmnop"}},required:["accessToken"]},LoginRequestDto:{type:"object",properties:{providerName:{type:"string",description:"Authentication provider name",example:"email",enum:["email","phone","google","facebook","apple","github"],default:"email"},credentials:{description:"Login credentials - type varies by provider",examples:{emailLogin:{summary:"Email Login",value:{email:"user@example.com",password:"SecurePass123!"}},phoneLogin:{summary:"Phone Login",value:{phone:"+1234567890",password:"SecurePass123!"}},socialLogin:{summary:"Social Login (Google/Facebook/etc)",value:{token:"ya29.a0AfH6SMBx..."}}},oneOf:[{$ref:"#/components/schemas/EmailCredentialsDto"},{$ref:"#/components/schemas/PhoneCredentialsDto"},{$ref:"#/components/schemas/SocialCredentialsDto"}]},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"},createUserIfNotExists:{type:"boolean",description:"Auto-create user if not exists (for social auth)",default:!1}}},RefreshTokenRequestDto:{type:"object",properties:{refreshToken:{type:"string",description:"Refresh token to obtain new access token",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJ0eXBlIjoicmVmcmVzaCJ9.abc123"}},required:["refreshToken"]},MessageResponseDto:{type:"object",properties:{message:{type:"string",description:"Response message"}},required:["message"]},MFAMethodEnum:{type:"string",enum:["totp","sms","email"],description:"MFA method used"},Verify2faRequestDto:{type:"object",properties:{method:{description:"MFA method used",example:"totp",allOf:[{$ref:"#/components/schemas/MFAMethodEnum"}]},otp:{type:"string",description:"One-time password code",example:"123456",minLength:6,maxLength:8},rememberDevice:{type:"boolean",description:"Whether to trust this device for future logins",example:!0}},required:["method","otp"]},Verify2faWithTokensResponseDto:{type:"object",properties:{accessToken:{type:"string",description:"JWT access token (short-lived)",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJpYXQiOjE2OTk5OTk5OTksImV4cCI6MTY5OTk5OTk5OX0.xyz"},refreshToken:{type:"string",description:"JWT refresh token (long-lived)",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjMiLCJ0eXBlIjoicmVmcmVzaCIsImlhdCI6MTY5OTk5OTk5OX0.abc"},message:{type:"string",description:"Verification success message (added by controller)",example:"2FA verification successful"}},required:["accessToken","refreshToken"]},ChangePasswordRequestDto:{type:"object",properties:{currentPassword:{type:"string",description:"Current password",example:"DemoOwner1!",minLength:8},newPassword:{type:"string",description:"New password",example:"DemoOwner1!New",minLength:8}},required:["currentPassword","newPassword"]},ForgotPasswordRequestDto:{type:"object",properties:{email:{type:"string",description:"User email address (required if phone not provided)",example:"user@example.com"},phone:{type:"string",description:"User phone number (required if email not provided)",example:"+1234567890"},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}}},VerifyForgotPasswordOtpRequestDto:{type:"object",properties:{email:{type:"string",description:"User email address (required if phone not provided)",example:"user@example.com"},phone:{type:"string",description:"User phone number (required if email not provided)",example:"+1234567890"},otp:{type:"string",description:"One-time password code received via email or SMS",example:"123456",minLength:6,maxLength:8},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}},required:["otp"]},VerifyOtpResponseDto:{type:"object",properties:{message:{type:"string",description:"Success message"},resetToken:{type:"string",description:"Password reset token - use this to reset password"}},required:["message"]},ResetPasswordRequestDto:{type:"object",properties:{email:{type:"string",description:"User email address (required if phone not provided)",example:"user@example.com"},phone:{type:"string",description:"User phone number (required if email not provided)",example:"+1234567890"},otp:{type:"string",description:"One-time password (OTP) received via email or SMS",example:"123456",minLength:6,maxLength:8},newPassword:{type:"string",description:"New password",example:"NewSecurePass123!",minLength:8},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}},required:["otp","newPassword"]},ResetPasswordWithTokenRequestDto:{type:"object",properties:{token:{type:"string",description:"Password reset token (JWT) received after OTP verification",example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoicGFzc3dvcmQtcmVzZXQifQ.xyz"},newPassword:{type:"string",description:"New password",example:"NewSecurePass123!",minLength:8}},required:["token","newPassword"]},SendEmailVerificationRequestDto:{type:"object",properties:{tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}}},VerifyEmailRequestDto:{type:"object",properties:{otp:{type:"string",description:"One-time password code received via email",example:"123456",minLength:6,maxLength:8},tenantId:{type:"string",description:"Tenant ID for multi-tenant applications",example:"123e4567-e89b-12d3-a456-426614174000"}},required:["otp"]},EmailAuthConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!0}},required:["enabled"]},PhoneAuthConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!1}},required:["enabled"]},RegistrationConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!0,description:"Whether user registration is enabled"},requireInvitation:{type:"boolean",example:!1,description:"Whether registration requires an invitation"},collectProfileFields:{type:"array",description:"Additional profile fields to collect during registration",items:{type:"object",properties:{id:{type:"string"},label:{type:"string"},required:{type:"boolean"},type:{type:"string",enum:["text","email","phone","select","checkbox","password"]},placeholder:{type:"string"},options:{type:"array",items:{type:"object",properties:{label:{type:"string"},value:{type:"string"}}}}}}}},required:["enabled"]},MfaConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!0},methods:{example:["email","totp"],type:"array",items:{type:"array"}},allowUserToggle:{type:"boolean",example:!0},allowMethodSelection:{type:"boolean",example:!0}},required:["enabled"]},TenantOptionDto:{type:"object",properties:{id:{type:"string"},name:{type:"string"},slug:{type:"string"},isActive:{type:"boolean"},metadata:{type:"object"}},required:["id","name","slug","isActive"]},TenantsConfigDto:{type:"object",properties:{mode:{type:"string",example:"single",enum:["single","multi"]},defaultTenantId:{type:"string",nullable:!0},options:{type:"array",items:{$ref:"#/components/schemas/TenantOptionDto"}}},required:["mode"]},SsoProviderConfigDto:{type:"object",properties:{id:{type:"string"},name:{type:"string"},logoUrl:{type:"string"},authorizationUrl:{type:"string"},clientId:{type:"string"},hint:{type:"string"}},required:["id","name"]},SsoConfigDto:{type:"object",properties:{enabled:{type:"boolean",example:!1},providers:{type:"array",items:{$ref:"#/components/schemas/SsoProviderConfigDto"}}},required:["enabled"]},UiConfigDto:{type:"object",properties:{brandName:{type:"string"},brandColor:{type:"string"},logoUrl:{type:"string"},backgroundImageUrl:{type:"string"}}},ClientConfigResponseDto:{type:"object",properties:{emailAuth:{$ref:"#/components/schemas/EmailAuthConfigDto"},phoneAuth:{$ref:"#/components/schemas/PhoneAuthConfigDto"},registration:{$ref:"#/components/schemas/RegistrationConfigDto"},mfa:{$ref:"#/components/schemas/MfaConfigDto"},tenants:{$ref:"#/components/schemas/TenantsConfigDto"},sso:{$ref:"#/components/schemas/SsoConfigDto"},ui:{$ref:"#/components/schemas/UiConfigDto"}},required:["emailAuth","phoneAuth","registration","mfa","tenants","sso"]},MfaDeviceDto:{type:"object",properties:{id:{type:"string",description:"Unique identifier of the MFA device",example:"4b3c9c9c-9a9d-4d1e-8d9f-123456789abc"},deviceName:{type:"string",description:"Friendly name of the registered device",example:"Work laptop"},method:{type:"string",description:"MFA method this device supports",enum:["totp","sms","email"],example:"totp"},lastUsedAt:{format:"date-time",type:"string",description:"Timestamp of when the device was last used",example:"2024-05-20T12:34:56.000Z"},verified:{type:"boolean",description:"Whether the device setup has been verified",example:!0},createdAt:{format:"date-time",type:"string",description:"Timestamp of when the device was registered",example:"2024-05-18T10:15:00.000Z"}},required:["id","deviceName","method","verified"]},MfaStatusResponseDto:{type:"object",properties:{isEnabled:{type:"boolean",description:"Whether MFA is currently enabled for the user",example:!0},verifiedMethods:{type:"array",description:"MFA methods the user has verified and can currently use (includes EMAIL/SMS if configured, and TOTP if user has verified device)",example:["email","totp"],items:{type:"string",enum:["totp","sms","email"]}},configuredMethods:{type:"array",description:"All MFA methods configured and available in the application (methods user can potentially set up)",example:["email","totp","sms"],items:{type:"string",enum:["totp","sms","email"]}},allowUserToggle:{type:"boolean",description:"Indicates if MFA toggling is allowed for the user",example:!0},allowMethodSelection:{type:"boolean",description:"Indicates if users can choose their preferred MFA method",example:!0},totpDevices:{description:"Registered TOTP devices for the user",type:"array",items:{$ref:"#/components/schemas/MfaDeviceDto"}},hasRecoveryCode:{type:"boolean",description:"Whether a recovery code has been generated for the user",example:!1}},required:["isEnabled","verifiedMethods","configuredMethods","allowUserToggle","allowMethodSelection","totpDevices","hasRecoveryCode"]},ToggleMfaRequestDto:{type:"object",properties:{enabled:{type:"boolean",description:"Whether MFA should be enabled for the current user",example:!0}},required:["enabled"]},SendMfaCodeRequestDto:{type:"object",properties:{method:{description:"MFA delivery method",example:"email",examples:{email:{value:"email",description:"Send OTP via email"},sms:{value:"sms",description:"Send OTP via SMS"},totp:{value:"totp",description:"Use authenticator app (TOTP)"}},allOf:[{$ref:"#/components/schemas/MFAMethodEnum"}]}},required:["method"]},VerifyTotpSetupRequestDto:{type:"object",properties:{otp:{type:"string",description:"The TOTP code from authenticator app",example:"123456",minLength:6,maxLength:6},secret:{type:"string",description:"Secret key from TOTP setup",example:"JBSWY3DPEHPK3PXP"}},required:["otp","secret"]}}},ett={openapi:Ket,paths:Yet,info:Jet,tags:Xet,servers:Zet,components:Qet},fg=({content:e})=>A.jsx(vJe,{remarkPlugins:[IZe],components:{code({node:t,inline:r,className:n,children:a,...i}){const s=/language-(\w+)/.exec(n||"");return!r&&s?A.jsx(Boe,{...i,style:zet,language:s[1],PreTag:"div",customStyle:{margin:0,borderRadius:"0.5rem",fontSize:"0.875rem"},children:String(a).replace(/\n$/,"")}):A.jsx("code",{...i,className:`${n} bg-gray-100 text-gray-800 rounded px-1 py-0.5 text-sm font-mono`,children:a})},table({children:t}){return A.jsx("div",{className:"overflow-x-auto my-4 border border-gray-200 rounded-lg",children:A.jsx("table",{className:"min-w-full divide-y divide-gray-200",children:t})})},thead({children:t}){return A.jsx("thead",{className:"bg-gray-50",children:t})},th({children:t}){return A.jsx("th",{scope:"col",className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:t})},td({children:t}){return A.jsx("td",{className:"px-6 py-4 whitespace-nowrap text-sm text-gray-500 border-t border-gray-200",children:t})},a({href:t,children:r}){return A.jsx("a",{href:t,className:"text-primary-600 hover:text-primary-800 hover:underline",target:"_blank",rel:"noopener noreferrer",children:r})},h2({children:t}){return A.jsx("h2",{className:"text-2xl font-bold text-gray-900 mt-8 mb-4 pb-2 border-b border-gray-200",children:t})},h3({children:t}){return A.jsx("h3",{className:"text-xl font-semibold text-gray-900 mt-6 mb-3",children:t})},p({children:t}){return A.jsx("p",{className:"text-gray-700 leading-relaxed mb-4",children:t})},ul({children:t}){return A.jsx("ul",{className:"list-disc list-inside space-y-1 mb-4 text-gray-700",children:t})},li({children:t}){return A.jsx("li",{className:"ml-4",children:t})},blockquote({children:t}){return A.jsx("blockquote",{className:"border-l-4 border-primary-500 pl-4 py-1 my-4 bg-primary-50 text-gray-700 italic rounded-r",children:t})}},children:e}),ttt=()=>{const[e,t]=te.useState(!1),[r,n]=te.useState(null),[a,i]=te.useState("swagger");te.useEffect(()=>{const l=ett||{};!l||!l.paths||Object.keys(l.paths||{}).length===0?t(!0):n(l)},[]);const s=()=>{if(!r)return;const l=JSON.stringify(r,null,2),u=new Blob([l],{type:"application/json"}),c=URL.createObjectURL(u),d=document.createElement("a");d.href=c,d.download="nest-auth-api.json",document.body.appendChild(d),d.click(),document.body.removeChild(d),URL.revokeObjectURL(c)},o=[{id:"swagger",label:"Interactive API",icon:vR},{id:"config",label:"Configuration",icon:iSe},{id:"examples",label:"Examples",icon:GV},{id:"events",label:"Events",icon:cSe},{id:"api-reference",label:"API Reference",icon:GEe},{id:"services",label:"Services",icon:GV}];return A.jsxs("div",{className:"space-y-6",children:[A.jsx(hm,{title:"API Documentation",description:"Comprehensive guide and interactive API documentation.",action:a==="swagger"&&A.jsxs("button",{onClick:s,className:"btn-secondary flex items-center gap-2",disabled:e,children:[A.jsx(XEe,{className:"w-4 h-4"}),"Download JSON"]})}),A.jsx("div",{className:"border-b border-gray-200",children:A.jsx("nav",{className:"-mb-px flex space-x-8","aria-label":"Tabs",children:o.map(l=>{const u=l.icon;return A.jsxs("button",{onClick:()=>i(l.id),className:`
|
|
5305
5306
|
whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm flex items-center gap-2 transition-colors
|
|
5306
5307
|
${a===l.id?"border-primary-500 text-primary-600":"border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"}
|
|
5307
5308
|
`,children:[A.jsx(u,{className:"w-4 h-4"}),l.label]},l.id)})})}),a==="swagger"&&(e?A.jsx("div",{className:"card",children:A.jsx("div",{className:"p-6 text-center",children:A.jsxs("div",{className:"p-4 bg-amber-50 border border-amber-200 rounded-lg flex items-start gap-3 mb-4",children:[A.jsx(Rl,{className:"w-5 h-5 text-amber-600 flex-shrink-0 mt-0.5"}),A.jsxs("div",{className:"text-left",children:[A.jsx("p",{className:"font-semibold text-amber-900 mb-1",children:"API Documentation Not Available"}),A.jsx("p",{className:"text-sm text-amber-800",children:"The OpenAPI specification file could not be loaded. Make sure the Swagger spec has been generated by running the build process."})]})]})})}):A.jsxs(A.Fragment,{children:[A.jsx("div",{className:"card bg-blue-50 border-blue-200",children:A.jsxs("div",{className:"p-4 flex items-start gap-3",children:[A.jsx(vR,{className:"w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5"}),A.jsxs("div",{className:"flex-1",children:[A.jsx("p",{className:"text-sm font-medium text-blue-900 mb-1",children:"Interactive API Documentation"}),A.jsx("p",{className:"text-sm text-blue-800",children:'This documentation is auto-generated from the OpenAPI specification. You can test endpoints directly from this page. Click "Download JSON" to get the raw OpenAPI specification file for importing into Postman or other API tools.'})]})]})}),r&&A.jsx(zGe,{spec:r})]})),a==="config"&&A.jsx("div",{className:"card p-8",children:A.jsx("div",{className:"prose prose-blue max-w-none",children:A.jsx(fg,{content:Vet})})}),a==="examples"&&A.jsx("div",{className:"card p-8",children:A.jsx("div",{className:"prose prose-blue max-w-none",children:A.jsx(fg,{content:qet})})}),a==="events"&&A.jsx("div",{className:"card p-8",children:A.jsx("div",{className:"prose prose-blue max-w-none",children:A.jsx(fg,{content:Het})})}),a==="api-reference"&&A.jsx("div",{className:"card p-8",children:A.jsx("div",{className:"prose prose-blue max-w-none",children:A.jsx(fg,{content:Get})})}),a==="services"&&A.jsx("div",{className:"card p-8",children:A.jsx("div",{className:"prose prose-blue max-w-none",children:A.jsx(fg,{content:Wet})})})]})},Pc=({children:e,authenticated:t})=>t===null?A.jsx("div",{className:"min-h-screen bg-gray-50 flex items-center justify-center",children:A.jsxs("div",{className:"text-center",children:[A.jsx("div",{className:"animate-spin rounded-full h-16 w-16 border-b-4 border-primary-600 mx-auto mb-4"}),A.jsx("p",{className:"text-gray-600 font-medium",children:"Verifying authentication..."})]})}):t?A.jsx(A.Fragment,{children:e}):A.jsx(Jp,{to:"/login",replace:!0}),rtt=()=>{const[e,t]=te.useState(null),[r,n]=te.useState(null),[a,i]=te.useState(!1),[s,o]=te.useState(null);te.useEffect(()=>{l()},[]);const l=async()=>{try{await It.get("/me"),t(!0);const d=await It.get("/config");n(d)}catch(d){console.error("Auth check failed:",d),t(!1);try{const p=await It.get("/config");n(p)}catch(p){console.error("Failed to load config:",p),n({allowAdminManagement:!1})}}finally{i(!0)}},u=async d=>{o(null);try{await It.post("/login",d),t(!0),await l()}catch(p){throw t(!1),o((p==null?void 0:p.message)||"Login failed"),p}},c=async()=>{try{await It.post("/logout",{})}catch(d){console.error("Logout failed:",d)}t(!1)};return!a||r===null?A.jsx("div",{className:"min-h-screen bg-gradient-to-br from-primary-50 via-blue-50 to-purple-50 flex items-center justify-center",children:A.jsxs("div",{className:"text-center",children:[A.jsx("div",{className:"inline-flex items-center justify-center w-16 h-16 bg-primary-600 rounded-full mb-4 shadow-lg",children:A.jsxs("svg",{className:"w-8 h-8 text-white animate-spin",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[A.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),A.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})}),A.jsx("p",{className:"text-gray-700 font-medium text-lg",children:"Loading Nest Auth Dashboard..."}),A.jsx("p",{className:"text-gray-500 text-sm mt-2",children:"Verifying authentication"})]})}):A.jsx(VEe,{children:A.jsx(DEe,{children:A.jsxs(OEe,{children:[A.jsx(_s,{path:"/login",element:e?A.jsx(Jp,{to:"/dashboard",replace:!0}):A.jsx(Uwe,{onLogin:u,error:s})}),A.jsx(_s,{path:"/dashboard",element:A.jsx(Pc,{authenticated:e,children:A.jsx(kc,{config:r,onLogout:c,children:A.jsx(dGe,{})})})}),A.jsx(_s,{path:"/users",element:A.jsx(Pc,{authenticated:e,children:A.jsx(kc,{config:r,onLogout:c,children:A.jsx(EGe,{})})})}),A.jsx(_s,{path:"/roles",element:A.jsx(Pc,{authenticated:e,children:A.jsx(kc,{config:r,onLogout:c,children:A.jsx(_Ge,{})})})}),A.jsx(_s,{path:"/tenants",element:A.jsx(Pc,{authenticated:e,children:A.jsx(kc,{config:r,onLogout:c,children:A.jsx(CGe,{})})})}),A.jsx(_s,{path:"/permissions",element:A.jsx(Pc,{authenticated:e,children:A.jsx(kc,{config:r,onLogout:c,children:A.jsx(MGe,{})})})}),A.jsx(_s,{path:"/api",element:A.jsx(Pc,{authenticated:e,children:A.jsx(kc,{config:r,onLogout:c,children:A.jsx(ttt,{})})})}),r.allowAdminManagement&&A.jsx(_s,{path:"/admins",element:A.jsx(Pc,{authenticated:e,children:A.jsx(kc,{config:r,onLogout:c,children:A.jsx(PGe,{})})})}),A.jsx(_s,{path:"/",element:e?A.jsx(Jp,{to:"/dashboard",replace:!0}):A.jsx(Jp,{to:"/login",replace:!0})}),A.jsx(_s,{path:"*",element:e?A.jsx(Jp,{to:"/dashboard",replace:!0}):A.jsx(Jp,{to:"/login",replace:!0})})]})})})},VW=document.getElementById("root");VW&&SI.createRoot(VW).render(A.jsx(de.StrictMode,{children:A.jsx(rtt,{})}));var wv={};/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */var ntt=wv.read=function(e,t,r,n,a){var i,s,o=a*8-n-1,l=(1<<o)-1,u=l>>1,c=-7,d=r?a-1:0,p=r?-1:1,f=e[t+d];for(d+=p,i=f&(1<<-c)-1,f>>=-c,c+=o;c>0;i=i*256+e[t+d],d+=p,c-=8);for(s=i&(1<<-c)-1,i>>=-c,c+=n;c>0;s=s*256+e[t+d],d+=p,c-=8);if(i===0)i=1-u;else{if(i===l)return s?NaN:(f?-1:1)*(1/0);s=s+Math.pow(2,n),i=i-u}return(f?-1:1)*s*Math.pow(2,i-n)},att=wv.write=function(e,t,r,n,a,i){var s,o,l,u=i*8-a-1,c=(1<<u)-1,d=c>>1,p=a===23?Math.pow(2,-24)-Math.pow(2,-77):0,f=n?0:i-1,h=n?1:-1,m=t<0||t===0&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(o=isNaN(t)?1:0,s=c):(s=Math.floor(Math.log(t)/Math.LN2),t*(l=Math.pow(2,-s))<1&&(s--,l*=2),s+d>=1?t+=p/l:t+=p*Math.pow(2,1-d),t*l>=2&&(s++,l/=2),s+d>=c?(o=0,s=c):s+d>=1?(o=(t*l-1)*Math.pow(2,a),s=s+d):(o=t*Math.pow(2,d-1)*Math.pow(2,a),s=0));a>=8;e[r+f]=o&255,f+=h,o/=256,a-=8);for(s=s<<a|o,u+=a;u>0;e[r+f]=s&255,f+=h,s/=256,u-=8);e[r+f-h]|=m*128};const itt=hA({__proto__:null,default:wv,read:ntt,write:att},[wv]);var hP={exports:{}},Uoe={},Ch={},stt=Ch.byteLength=dtt,ott=Ch.toByteArray=ftt,ltt=Ch.fromByteArray=gtt,_o=[],Hi=[],utt=typeof Uint8Array<"u"?Uint8Array:Array,AC="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(var Mp=0,ctt=AC.length;Mp<ctt;++Mp)_o[Mp]=AC[Mp],Hi[AC.charCodeAt(Mp)]=Mp;Hi[45]=62;Hi[95]=63;function zoe(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var r=e.indexOf("=");r===-1&&(r=t);var n=r===t?0:4-r%4;return[r,n]}function dtt(e){var t=zoe(e),r=t[0],n=t[1];return(r+n)*3/4-n}function ptt(e,t,r){return(t+r)*3/4-r}function ftt(e){var t,r=zoe(e),n=r[0],a=r[1],i=new utt(ptt(e,n,a)),s=0,o=a>0?n-4:n,l;for(l=0;l<o;l+=4)t=Hi[e.charCodeAt(l)]<<18|Hi[e.charCodeAt(l+1)]<<12|Hi[e.charCodeAt(l+2)]<<6|Hi[e.charCodeAt(l+3)],i[s++]=t>>16&255,i[s++]=t>>8&255,i[s++]=t&255;return a===2&&(t=Hi[e.charCodeAt(l)]<<2|Hi[e.charCodeAt(l+1)]>>4,i[s++]=t&255),a===1&&(t=Hi[e.charCodeAt(l)]<<10|Hi[e.charCodeAt(l+1)]<<4|Hi[e.charCodeAt(l+2)]>>2,i[s++]=t>>8&255,i[s++]=t&255),i}function htt(e){return _o[e>>18&63]+_o[e>>12&63]+_o[e>>6&63]+_o[e&63]}function mtt(e,t,r){for(var n,a=[],i=t;i<r;i+=3)n=(e[i]<<16&16711680)+(e[i+1]<<8&65280)+(e[i+2]&255),a.push(htt(n));return a.join("")}function gtt(e){for(var t,r=e.length,n=r%3,a=[],i=16383,s=0,o=r-n;s<o;s+=i)a.push(mtt(e,s,s+i>o?o:s+i));return n===1?(t=e[r-1],a.push(_o[t>>2]+_o[t<<4&63]+"==")):n===2&&(t=(e[r-2]<<8)+e[r-1],a.push(_o[t>>10]+_o[t>>4&63]+_o[t<<2&63]+"=")),a.join("")}const ytt=hA({__proto__:null,byteLength:stt,default:Ch,fromByteArray:ltt,toByteArray:ott},[Ch]);/*!
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-auth/src/lib/auth/auth.module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-auth/src/lib/auth/auth.module.ts"],"names":[],"mappings":"AAwBA,qBAoCa,UAAU;CACtB"}
|
|
@@ -11,6 +11,7 @@ const auth_guard_1 = require("./guards/auth.guard");
|
|
|
11
11
|
const refresh_token_interceptor_1 = require("./interceptors/refresh-token.interceptor");
|
|
12
12
|
const auth_controller_1 = require("./controllers/auth.controller");
|
|
13
13
|
const mfa_controller_1 = require("./controllers/mfa.controller");
|
|
14
|
+
const auth_session_event_listener_service_1 = require("./services/auth-session-event-listener.service");
|
|
14
15
|
const identity_entity_1 = require("../user/entities/identity.entity");
|
|
15
16
|
const typeorm_1 = require("@nestjs/typeorm");
|
|
16
17
|
const user_entity_1 = require("../user/entities/user.entity");
|
|
@@ -52,6 +53,7 @@ exports.AuthModule = AuthModule = tslib_1.__decorate([
|
|
|
52
53
|
client_config_service_1.ClientConfigService,
|
|
53
54
|
auth_guard_1.NestAuthAuthGuard,
|
|
54
55
|
refresh_token_interceptor_1.RefreshTokenInterceptor,
|
|
56
|
+
auth_session_event_listener_service_1.AuthSessionEventListener,
|
|
55
57
|
],
|
|
56
58
|
controllers: [auth_controller_1.AuthController, mfa_controller_1.MfaController],
|
|
57
59
|
exports: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.guard.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/guards/auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,WAAW,EAAE,gBAAgB,EAA6C,MAAM,gBAAgB,CAAC;AAEtH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAK1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAG5E,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,qBACa,iBAAkB,YAAW,WAAW;IAE7C,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,iBAAiB;gBAJjB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,qBAAqB,EACrC,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,EAAE,iBAAiB;IAG1C,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;YAyFhD,aAAa;
|
|
1
|
+
{"version":3,"file":"auth.guard.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/guards/auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,WAAW,EAAE,gBAAgB,EAA6C,MAAM,gBAAgB,CAAC;AAEtH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAK1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAG5E,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,qBACa,iBAAkB,YAAW,WAAW;IAE7C,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,iBAAiB;gBAJjB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,qBAAqB,EACrC,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,EAAE,iBAAiB;IAG1C,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;YAyFhD,aAAa;YAmGb,gBAAgB;YAqDhB,QAAQ;IA0BtB;;OAEG;YACW,kBAAkB;IAqChC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAc9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH;;OAEG;IACH;;OAEG;YACW,gBAAgB;IAoB9B;;OAEG;YACW,UAAU;IAsBxB;;OAEG;IACH;;OAEG;IACH;;OAEG;YACW,gBAAgB;IAuC9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAiB7B"}
|
|
@@ -114,7 +114,7 @@ let NestAuthAuthGuard = class NestAuthAuthGuard {
|
|
|
114
114
|
return false;
|
|
115
115
|
}
|
|
116
116
|
// After successful authentication, check authorization (roles, permissions)
|
|
117
|
-
// Only check authorization if user is authenticated
|
|
117
|
+
// Only check authorization if user is authenticated and we have user data
|
|
118
118
|
if (isAuthenticated && request.user) {
|
|
119
119
|
await this.checkAuthorization(context, request);
|
|
120
120
|
}
|
|
@@ -164,6 +164,20 @@ let NestAuthAuthGuard = class NestAuthAuthGuard {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
request.session = session;
|
|
167
|
+
// Check if user is active
|
|
168
|
+
if (session.user && session.user.isActive === false) {
|
|
169
|
+
if (isOptional) {
|
|
170
|
+
request.user = null;
|
|
171
|
+
request.authType = null;
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
throw new common_1.UnauthorizedException({
|
|
176
|
+
message: 'User is not active',
|
|
177
|
+
code: auth_constants_1.ERROR_CODES.ACCOUNT_INACTIVE
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
167
181
|
// Check MFA requirements
|
|
168
182
|
await this.checkMfa(context, payload, isOptional);
|
|
169
183
|
// Apply guards.afterAuth hook if configured
|
|
@@ -186,6 +200,10 @@ let NestAuthAuthGuard = class NestAuthAuthGuard {
|
|
|
186
200
|
return false;
|
|
187
201
|
}
|
|
188
202
|
else {
|
|
203
|
+
// If it's already an HttpException (like UnauthorizedException from our checks), rethrow it
|
|
204
|
+
if (error instanceof common_1.UnauthorizedException || error.status) {
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
189
207
|
throw new common_1.UnauthorizedException({
|
|
190
208
|
message: 'Invalid or expired token',
|
|
191
209
|
code: auth_constants_1.ERROR_CODES.INVALID_TOKEN
|
|
@@ -286,6 +304,11 @@ let NestAuthAuthGuard = class NestAuthAuthGuard {
|
|
|
286
304
|
code: auth_constants_1.ERROR_CODES.UNAUTHORIZED,
|
|
287
305
|
});
|
|
288
306
|
}
|
|
307
|
+
// If isFetchUser=false, we might not have roles in the user object (which is just payload)
|
|
308
|
+
// Unless roles are in payload.
|
|
309
|
+
// Assuming roles are NOT in payload by default unless configured.
|
|
310
|
+
// If we need roles check but have no roles/data, we must throw or fetch.
|
|
311
|
+
// For now, if defaults are used, user is just payload.
|
|
289
312
|
// Check roles if required
|
|
290
313
|
if (requiredRoles.length > 0) {
|
|
291
314
|
await this.checkRoles(user, requiredRoles);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { UserUpdatedEvent } from '../../user/events/user-updated.event';
|
|
2
|
+
import { UserDeletedEvent } from '../../user/events/user-deleted.event';
|
|
3
|
+
import { SessionManagerService } from '../../session/services/session-manager.service';
|
|
4
|
+
import { DebugLoggerService } from '../../core/services/debug-logger.service';
|
|
5
|
+
/**
|
|
6
|
+
* Listens to user events and manages session validity.
|
|
7
|
+
* For example, revokes sessions when a user is deactivated or deleted.
|
|
8
|
+
*/
|
|
9
|
+
export declare class AuthSessionEventListener {
|
|
10
|
+
private readonly sessionManager;
|
|
11
|
+
private readonly debugLogger;
|
|
12
|
+
constructor(sessionManager: SessionManagerService, debugLogger: DebugLoggerService);
|
|
13
|
+
handleUserUpdated(event: UserUpdatedEvent): Promise<void>;
|
|
14
|
+
handleUserDeleted(event: UserDeletedEvent): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=auth-session-event-listener.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-session-event-listener.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/services/auth-session-event-listener.service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAE9E;;;GAGG;AACH,qBACa,wBAAwB;IAE7B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW;gBADX,cAAc,EAAE,qBAAqB,EACrC,WAAW,EAAE,kBAAkB;IAI9C,iBAAiB,CAAC,KAAK,EAAE,gBAAgB;IAWzC,iBAAiB,CAAC,KAAK,EAAE,gBAAgB;CAKlD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthSessionEventListener = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
7
|
+
const auth_constants_1 = require("../../auth.constants");
|
|
8
|
+
const user_updated_event_1 = require("../../user/events/user-updated.event");
|
|
9
|
+
const user_deleted_event_1 = require("../../user/events/user-deleted.event");
|
|
10
|
+
const session_manager_service_1 = require("../../session/services/session-manager.service");
|
|
11
|
+
const debug_logger_service_1 = require("../../core/services/debug-logger.service");
|
|
12
|
+
/**
|
|
13
|
+
* Listens to user events and manages session validity.
|
|
14
|
+
* For example, revokes sessions when a user is deactivated or deleted.
|
|
15
|
+
*/
|
|
16
|
+
let AuthSessionEventListener = class AuthSessionEventListener {
|
|
17
|
+
constructor(sessionManager, debugLogger) {
|
|
18
|
+
this.sessionManager = sessionManager;
|
|
19
|
+
this.debugLogger = debugLogger;
|
|
20
|
+
}
|
|
21
|
+
async handleUserUpdated(event) {
|
|
22
|
+
const { user, updatedFields } = event.payload;
|
|
23
|
+
// If isActive status changed to false, revoke all sessions
|
|
24
|
+
if (updatedFields.includes('isActive') && user.isActive === false) {
|
|
25
|
+
this.debugLogger.info('User deactivated. Revoking all sessions.', 'AuthSessionEventListener', { userId: user.id });
|
|
26
|
+
await this.sessionManager.revokeAllUserSessions(user.id);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async handleUserDeleted(event) {
|
|
30
|
+
const { user } = event.payload;
|
|
31
|
+
this.debugLogger.info('User deleted. Revoking all sessions.', 'AuthSessionEventListener', { userId: user.id });
|
|
32
|
+
await this.sessionManager.revokeAllUserSessions(user.id);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
exports.AuthSessionEventListener = AuthSessionEventListener;
|
|
36
|
+
tslib_1.__decorate([
|
|
37
|
+
(0, event_emitter_1.OnEvent)(auth_constants_1.NestAuthEvents.USER_UPDATED),
|
|
38
|
+
tslib_1.__metadata("design:type", Function),
|
|
39
|
+
tslib_1.__metadata("design:paramtypes", [user_updated_event_1.UserUpdatedEvent]),
|
|
40
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
41
|
+
], AuthSessionEventListener.prototype, "handleUserUpdated", null);
|
|
42
|
+
tslib_1.__decorate([
|
|
43
|
+
(0, event_emitter_1.OnEvent)(auth_constants_1.NestAuthEvents.USER_DELETED),
|
|
44
|
+
tslib_1.__metadata("design:type", Function),
|
|
45
|
+
tslib_1.__metadata("design:paramtypes", [user_deleted_event_1.UserDeletedEvent]),
|
|
46
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
47
|
+
], AuthSessionEventListener.prototype, "handleUserDeleted", null);
|
|
48
|
+
exports.AuthSessionEventListener = AuthSessionEventListener = tslib_1.__decorate([
|
|
49
|
+
(0, common_1.Injectable)(),
|
|
50
|
+
tslib_1.__metadata("design:paramtypes", [session_manager_service_1.SessionManagerService,
|
|
51
|
+
debug_logger_service_1.DebugLoggerService])
|
|
52
|
+
], AuthSessionEventListener);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/services/auth.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAU7D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AAEvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EACH,aAAa,EACb,UAAU,EACb,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAEvF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAUrF,OAAO,EAAE,2BAA2B,EAAE,MAAM,oDAAoD,CAAC;AACjG,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAE9E,OAAO,EAAE,iCAAiC,EAAE,MAAM,wDAAwD,CAAC;AAC3G,OAAO,EAAE,gCAAgC,EAAE,MAAM,uDAAuD,CAAC;AACzG,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AACvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,+BAA+B,EAAE,MAAM,qDAAqD,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAI5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAI/D,qBACa,WAAW;IAIhB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAG/B,OAAO,CAAC,aAAa;IAErB,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAErC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAE3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAE3B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAE7B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,WAAW;gBArBX,cAAc,EAAE,UAAU,CAAC,YAAY,CAAC,EAGjD,aAAa,EAAE,UAAU,CAAC,WAAW,CAAC,EAE7B,oBAAoB,EAAE,2BAA2B,EAEjD,UAAU,EAAE,UAAU,EAEtB,cAAc,EAAE,qBAAqB,EAErC,UAAU,EAAE,UAAU,EAEtB,YAAY,EAAE,aAAa,EAE3B,aAAa,EAAE,aAAa,EAE5B,WAAW,EAAE,kBAAkB,EAE/B,iBAAiB,EAAE,iBAAiB,EAEpC,WAAW,EAAE,WAAW;IAM7C,IAAI,SAAS,IAAI,UAAU,CAE1B;IAED,8BAA8B,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,YAAY,CAAC;IAUzF,OAAO;IAgBP,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/services/auth.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -94,38 +94,44 @@ let AuthService = class AuthService {
|
|
|
94
94
|
code: auth_constants_1.ERROR_CODES.EMAIL_OR_PHONE_REQUIRED,
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
const providersToLink = [];
|
|
98
|
+
if (email && config.emailAuth?.enabled !== false) {
|
|
99
|
+
const provider = this.authProviderRegistry.getProvider(auth_constants_1.EMAIL_AUTH_PROVIDER);
|
|
100
|
+
if (provider) {
|
|
101
|
+
providersToLink.push({ provider, userId: email, type: 'email' });
|
|
102
|
+
}
|
|
102
103
|
}
|
|
103
|
-
|
|
104
|
-
provider = this.authProviderRegistry.getProvider(auth_constants_1.PHONE_AUTH_PROVIDER);
|
|
105
|
-
|
|
104
|
+
if (phone && config.phoneAuth?.enabled === true) {
|
|
105
|
+
const provider = this.authProviderRegistry.getProvider(auth_constants_1.PHONE_AUTH_PROVIDER);
|
|
106
|
+
if (provider) {
|
|
107
|
+
providersToLink.push({ provider, userId: phone, type: 'phone' });
|
|
108
|
+
}
|
|
106
109
|
}
|
|
107
|
-
if (
|
|
110
|
+
if (providersToLink.length === 0) {
|
|
108
111
|
this.debugLogger.error('Provider not found for signup', 'AuthService', { email: !!email, phone: !!phone });
|
|
109
112
|
throw new common_1.InternalServerErrorException({
|
|
110
113
|
message: 'Phone or email authentication is not enabled',
|
|
111
114
|
code: auth_constants_1.ERROR_CODES.PROVIDER_NOT_FOUND,
|
|
112
115
|
});
|
|
113
116
|
}
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
117
|
+
// Check for existing identities across all providers
|
|
118
|
+
for (const item of providersToLink) {
|
|
119
|
+
this.debugLogger.debug('Checking for existing identity', 'AuthService', { providerUserId: item.userId, type: item.type });
|
|
120
|
+
const identity = await item.provider.findIdentity(item.userId);
|
|
121
|
+
if (identity) {
|
|
122
|
+
this.debugLogger.warn('Identity already exists', 'AuthService', { email: !!email, phone: !!phone, tenantId });
|
|
123
|
+
if (item.type === 'email') {
|
|
124
|
+
throw new common_1.BadRequestException({
|
|
125
|
+
message: 'Email already exists in this tenant',
|
|
126
|
+
code: auth_constants_1.ERROR_CODES.EMAIL_ALREADY_EXISTS,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (item.type === 'phone') {
|
|
130
|
+
throw new common_1.BadRequestException({
|
|
131
|
+
message: 'Phone number already exists in this tenant',
|
|
132
|
+
code: auth_constants_1.ERROR_CODES.PHONE_ALREADY_EXISTS,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
137
|
this.debugLogger.debug('Creating new user via UserService', 'AuthService', { email: !!email, phone: !!phone, tenantId });
|
|
@@ -140,9 +146,12 @@ let AuthService = class AuthService {
|
|
|
140
146
|
}, input);
|
|
141
147
|
this.debugLogger.info('User created successfully', 'AuthService', { userId: user.id, tenantId });
|
|
142
148
|
user = await this.getUserWithRolesAndPermissions(user.id);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
149
|
+
// Link user to all enabled providers
|
|
150
|
+
for (const item of providersToLink) {
|
|
151
|
+
this.debugLogger.debug('Linking user to provider', 'AuthService', { userId: user.id, providerName: item.provider.providerName });
|
|
152
|
+
// Note: UserService might have already created the identity, but we ensure it's linked here
|
|
153
|
+
await item.provider.linkToUser(user.id, item.userId);
|
|
154
|
+
}
|
|
146
155
|
this.debugLogger.debug('Creating session for new user', 'AuthService', { userId: user.id });
|
|
147
156
|
const session = await this.sessionManager.createSessionFromUser(user);
|
|
148
157
|
const tokens = await this.generateTokensFromSession(session);
|
|
@@ -150,6 +159,7 @@ let AuthService = class AuthService {
|
|
|
150
159
|
this.debugLogger.debug('Signup tokens generated', 'AuthService', { userId: user.id, isRequiresMfa });
|
|
151
160
|
// Emit registration event
|
|
152
161
|
this.debugLogger.debug('Emitting user registration event', 'AuthService', { userId: user.id });
|
|
162
|
+
const provider = providersToLink[0]?.provider;
|
|
153
163
|
await this.eventEmitter.emitAsync(auth_constants_1.NestAuthEvents.REGISTERED, new user_registered_event_1.UserRegisteredEvent({
|
|
154
164
|
user,
|
|
155
165
|
tenantId: user.tenantId,
|
|
@@ -8,7 +8,7 @@ export declare class AppleAuthProvider extends BaseAuthProvider {
|
|
|
8
8
|
private appleAuth;
|
|
9
9
|
constructor(dataSource: DataSource, jwtService: JwtService);
|
|
10
10
|
validate(credentials: {
|
|
11
|
-
|
|
11
|
+
token: string;
|
|
12
12
|
}): Promise<{
|
|
13
13
|
userId: string;
|
|
14
14
|
email: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apple-auth.provider.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/providers/apple-auth.provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAIxD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,qBACa,iBAAkB,SAAQ,gBAAgB;IAM/C,QAAQ,CAAC,UAAU,EAAE,UAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAN/B,YAAY,SAAuB;IAEnC,OAAO,CAAC,SAAS,CAAY;gBAGhB,UAAU,EAAE,UAAU,EACd,UAAU,EAAE,UAAU;IA0BrC,QAAQ,CAAC,WAAW,EAAE;QAAE,
|
|
1
|
+
{"version":3,"file":"apple-auth.provider.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/providers/apple-auth.provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAIxD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,qBACa,iBAAkB,SAAQ,gBAAgB;IAM/C,QAAQ,CAAC,UAAU,EAAE,UAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAN/B,YAAY,SAAuB;IAEnC,OAAO,CAAC,SAAS,CAAY;gBAGhB,UAAU,EAAE,UAAU,EACd,UAAU,EAAE,UAAU;IA0BrC,QAAQ,CAAC,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;;;;;IAc7C,iBAAiB,IAAI,MAAM,EAAE;CAGhC"}
|
|
@@ -32,7 +32,7 @@ let AppleAuthProvider = class AppleAuthProvider extends base_auth_provider_1.Bas
|
|
|
32
32
|
}
|
|
33
33
|
async validate(credentials) {
|
|
34
34
|
try {
|
|
35
|
-
const response = await this.appleAuth.accessToken(credentials.
|
|
35
|
+
const response = await this.appleAuth.accessToken(credentials.token);
|
|
36
36
|
const user = this.jwtService.decodeToken(response.id_token);
|
|
37
37
|
return {
|
|
38
38
|
userId: user.id,
|
|
@@ -45,7 +45,7 @@ let AppleAuthProvider = class AppleAuthProvider extends base_auth_provider_1.Bas
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
getRequiredFields() {
|
|
48
|
-
return ['
|
|
48
|
+
return ['token'];
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
exports.AppleAuthProvider = AppleAuthProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"facebook-auth.provider.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/providers/facebook-auth.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAKrC,qBACa,oBAAqB,SAAQ,gBAAgB;IAIlD,QAAQ,CAAC,UAAU,EAAE,UAAU;IAHnC,YAAY,SAA0B;gBAGzB,UAAU,EAAE,UAAU;IAkB7B,QAAQ,CAAC,WAAW,EAAE;QAAE,
|
|
1
|
+
{"version":3,"file":"facebook-auth.provider.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/providers/facebook-auth.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAKrC,qBACa,oBAAqB,SAAQ,gBAAgB;IAIlD,QAAQ,CAAC,UAAU,EAAE,UAAU;IAHnC,YAAY,SAA0B;gBAGzB,UAAU,EAAE,UAAU;IAkB7B,QAAQ,CAAC,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;;;;;;;;IAoB7C,iBAAiB,IAAI,MAAM,EAAE;CAGhC"}
|
|
@@ -29,7 +29,7 @@ let FacebookAuthProvider = class FacebookAuthProvider extends base_auth_provider
|
|
|
29
29
|
try {
|
|
30
30
|
const response = await fb_1.default.api('me', {
|
|
31
31
|
fields: ['id', 'email', 'name', 'picture'],
|
|
32
|
-
access_token: credentials.
|
|
32
|
+
access_token: credentials.token,
|
|
33
33
|
});
|
|
34
34
|
return {
|
|
35
35
|
userId: response.id,
|
|
@@ -45,7 +45,7 @@ let FacebookAuthProvider = class FacebookAuthProvider extends base_auth_provider
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
getRequiredFields() {
|
|
48
|
-
return ['
|
|
48
|
+
return ['token'];
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
exports.FacebookAuthProvider = FacebookAuthProvider;
|
|
@@ -6,8 +6,16 @@ export declare class GoogleAuthProvider extends BaseAuthProvider {
|
|
|
6
6
|
private client;
|
|
7
7
|
private googleConfig;
|
|
8
8
|
constructor(dataSource: DataSource);
|
|
9
|
+
/**
|
|
10
|
+
* Validate Google credentials.
|
|
11
|
+
* Supports validation via 'idToken' or 'accessToken'.
|
|
12
|
+
*
|
|
13
|
+
* @param credentials - Object containing either 'idToken' or 'accessToken'
|
|
14
|
+
* @returns AuthProviderUser - Validated user user info
|
|
15
|
+
*/
|
|
9
16
|
validate(credentials: {
|
|
10
|
-
|
|
17
|
+
token: string;
|
|
18
|
+
type: 'id' | 'access';
|
|
11
19
|
}): Promise<{
|
|
12
20
|
userId: string;
|
|
13
21
|
email: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-auth.provider.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/providers/google-auth.provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrC,qBACa,kBAAmB,SAAQ,gBAAgB;IAMhD,QAAQ,CAAC,UAAU,EAAE,UAAU;IALnC,YAAY,SAAwB;IACpC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,YAAY,CAA8B;gBAGrC,UAAU,EAAE,UAAU;
|
|
1
|
+
{"version":3,"file":"google-auth.provider.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/providers/google-auth.provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrC,qBACa,kBAAmB,SAAQ,gBAAgB;IAMhD,QAAQ,CAAC,UAAU,EAAE,UAAU;IALnC,YAAY,SAAwB;IACpC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,YAAY,CAA8B;gBAGrC,UAAU,EAAE,UAAU;IAenC;;;;;;OAMG;IACG,QAAQ,CAAC,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CAAA;KAAE;;;;;;;;;IA+DpE,iBAAiB,IAAI,MAAM,EAAE;CAGhC"}
|
|
@@ -22,15 +22,57 @@ let GoogleAuthProvider = class GoogleAuthProvider extends base_auth_provider_1.B
|
|
|
22
22
|
this.client = new google_auth_library_1.OAuth2Client(this.googleConfig.clientId, this.googleConfig.clientSecret);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Validate Google credentials.
|
|
27
|
+
* Supports validation via 'idToken' or 'accessToken'.
|
|
28
|
+
*
|
|
29
|
+
* @param credentials - Object containing either 'idToken' or 'accessToken'
|
|
30
|
+
* @returns AuthProviderUser - Validated user user info
|
|
31
|
+
*/
|
|
25
32
|
async validate(credentials) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
const { token, type = 'id' } = credentials;
|
|
34
|
+
let payload;
|
|
35
|
+
if (type === 'id') {
|
|
36
|
+
// CASE 1: Validation via ID Token
|
|
37
|
+
// Recommended for backend verification as it's stateless and secure.
|
|
38
|
+
try {
|
|
39
|
+
const ticket = await this.client.verifyIdToken({
|
|
40
|
+
idToken: token,
|
|
41
|
+
audience: this.googleConfig.clientId,
|
|
42
|
+
});
|
|
43
|
+
payload = ticket.getPayload();
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error('Google ID Token validation failed:', error);
|
|
47
|
+
throw new common_1.UnauthorizedException('Invalid Google ID token');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (type === 'access') {
|
|
51
|
+
// CASE 2: Validation via Access Token
|
|
52
|
+
// Useful when the client only has an access token (implicit flow or mobile SDKs).
|
|
53
|
+
try {
|
|
54
|
+
// Step 1: Verify the token info to ensure it's valid and for the correct app
|
|
55
|
+
const tokenInfo = await this.client.getTokenInfo(token);
|
|
56
|
+
// Optional: Verify audience if needed, though getTokenInfo validates validity
|
|
57
|
+
// if (tokenInfo.aud !== this.googleConfig.clientId) { ... }
|
|
58
|
+
if (!tokenInfo.email_verified) {
|
|
59
|
+
throw new common_1.UnauthorizedException('Google email not verified');
|
|
60
|
+
}
|
|
61
|
+
// Step 2: Fetch user profile to get standard fields (sub, name, email, picture)
|
|
62
|
+
const response = await this.client.request({
|
|
63
|
+
url: 'https://www.googleapis.com/oauth2/v3/userinfo',
|
|
64
|
+
headers: {
|
|
65
|
+
Authorization: `Bearer ${token}`,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
payload = response.data;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error('Google Access Token validation failed:', error);
|
|
72
|
+
throw new common_1.UnauthorizedException('Invalid Google Access token');
|
|
73
|
+
}
|
|
32
74
|
if (!payload) {
|
|
33
|
-
throw new common_1.UnauthorizedException(
|
|
75
|
+
throw new common_1.UnauthorizedException(`Invalid Google ${type} token`);
|
|
34
76
|
}
|
|
35
77
|
return {
|
|
36
78
|
userId: payload.sub,
|
|
@@ -42,12 +84,13 @@ let GoogleAuthProvider = class GoogleAuthProvider extends base_auth_provider_1.B
|
|
|
42
84
|
},
|
|
43
85
|
};
|
|
44
86
|
}
|
|
45
|
-
|
|
46
|
-
|
|
87
|
+
else {
|
|
88
|
+
// CASE 3: No valid credentials provided
|
|
89
|
+
throw new common_1.UnauthorizedException('Missing required Google credentials (idToken or accessToken)');
|
|
47
90
|
}
|
|
48
91
|
}
|
|
49
92
|
getRequiredFields() {
|
|
50
|
-
return ['
|
|
93
|
+
return ['token'];
|
|
51
94
|
}
|
|
52
95
|
};
|
|
53
96
|
exports.GoogleAuthProvider = GoogleAuthProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-config.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/services/auth-config.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAIhF,qBACa,iBAAiB;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoB;IAC3C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAoB;IAE1C;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"auth-config.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/services/auth-config.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAIhF,qBACa,iBAAiB;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoB;IAC3C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAoB;IAE1C;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc,CAoD3B;;IASF,MAAM,CAAC,WAAW,IAAI,iBAAiB;IAOvC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAIhC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAqB/B,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAyBnD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,2BAA2B;IAiB1C,MAAM,CAAC,UAAU,IAAI,iBAAiB;IAOtC,MAAM,CAAC,iBAAiB,IAAI,iBAAiB;IAI7C,SAAS,IAAI,iBAAiB;IAI9B,SAAS,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;CAG9C"}
|
|
@@ -132,6 +132,9 @@ AuthConfigService.defaultOptions = {
|
|
|
132
132
|
emailAuth: {
|
|
133
133
|
enabled: true,
|
|
134
134
|
},
|
|
135
|
+
phoneAuth: {
|
|
136
|
+
enabled: false,
|
|
137
|
+
},
|
|
135
138
|
mfa: {
|
|
136
139
|
enabled: false,
|
|
137
140
|
methods: [mfa_options_interface_1.MFAMethodEnum.EMAIL, mfa_options_interface_1.MFAMethodEnum.TOTP],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-repository.interface.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/session/interfaces/session-repository.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAE/E;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAC/B;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE1D;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAE7D;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAEzD;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAE/D;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"session-repository.interface.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/session/interfaces/session-repository.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAE/E;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAC/B;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE1D;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAE7D;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAEzD;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAE/D;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACvF;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC;;OAEG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAErD;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/user/services/user.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAe,UAAU,EAAE,MAAM,SAAS,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAKtD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAE5E,qBACa,WAAW;IAGhB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAJX,cAAc,EAAE,UAAU,CAAC,YAAY,CAAC,EACxC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,aAAa,EAC3B,iBAAiB,EAAE,iBAAiB,EACpC,WAAW,EAAE,kBAAkB;IAG9C,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"user.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/user/services/user.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -67,10 +67,12 @@ let UserService = class UserService {
|
|
|
67
67
|
this.debugLogger.info('User created successfully', 'UserService', { userId: user.id });
|
|
68
68
|
// Create identities
|
|
69
69
|
const normalizedEmail = email?.toLowerCase().trim();
|
|
70
|
-
if (normalizedEmail)
|
|
70
|
+
if (normalizedEmail && config.emailAuth?.enabled !== false) {
|
|
71
71
|
await user.findOrCreateIdentity(auth_constants_1.EMAIL_AUTH_PROVIDER, normalizedEmail);
|
|
72
|
-
|
|
72
|
+
}
|
|
73
|
+
if (phone && config.phoneAuth?.enabled === true) {
|
|
73
74
|
await user.findOrCreateIdentity(auth_constants_1.PHONE_AUTH_PROVIDER, phone);
|
|
75
|
+
}
|
|
74
76
|
// Emit user created event
|
|
75
77
|
this.debugLogger.debug('Emitting user created event', 'UserService', { userId: user.id });
|
|
76
78
|
await this.eventEmitter.emitAsync(auth_constants_1.NestAuthEvents.USER_CREATED, new user_created_event_1.UserCreatedEvent({
|
|
@@ -209,11 +211,12 @@ let UserService = class UserService {
|
|
|
209
211
|
Object.assign(user, data);
|
|
210
212
|
const updatedUser = await this.userRepository.save(user);
|
|
211
213
|
this.debugLogger.info('User updated successfully', 'UserService', { userId: updatedUser.id });
|
|
212
|
-
|
|
214
|
+
const config = this.authConfigService.getConfig();
|
|
215
|
+
if (data.email && config.emailAuth?.enabled !== false) {
|
|
213
216
|
this.debugLogger.debug('Updating email identity', 'UserService', { userId: id });
|
|
214
217
|
await user.updateOrCreateIdentity(auth_constants_1.EMAIL_AUTH_PROVIDER, { providerId: data.email });
|
|
215
218
|
}
|
|
216
|
-
if (data.phone) {
|
|
219
|
+
if (data.phone && config.phoneAuth?.enabled === true) {
|
|
217
220
|
this.debugLogger.debug('Updating phone identity', 'UserService', { userId: id });
|
|
218
221
|
await user.updateOrCreateIdentity(auth_constants_1.PHONE_AUTH_PROVIDER, { providerId: data.phone });
|
|
219
222
|
}
|
|
@@ -304,7 +307,15 @@ let UserService = class UserService {
|
|
|
304
307
|
});
|
|
305
308
|
}
|
|
306
309
|
user.isActive = isActive;
|
|
307
|
-
|
|
310
|
+
const updatedUser = await this.userRepository.save(user);
|
|
311
|
+
// Emit user updated event
|
|
312
|
+
this.debugLogger.debug('Emitting user updated event (status change)', 'UserService', { userId: id, isActive });
|
|
313
|
+
await this.eventEmitter.emitAsync(auth_constants_1.NestAuthEvents.USER_UPDATED, new user_updated_event_1.UserUpdatedEvent({
|
|
314
|
+
user: updatedUser,
|
|
315
|
+
tenantId: updatedUser.tenantId,
|
|
316
|
+
updatedFields: ['isActive']
|
|
317
|
+
}));
|
|
318
|
+
return updatedUser;
|
|
308
319
|
}
|
|
309
320
|
async updateUserMetadata(id, metadata) {
|
|
310
321
|
const user = await this.getUserById(id);
|
|
@@ -318,7 +329,15 @@ let UserService = class UserService {
|
|
|
318
329
|
...user.metadata,
|
|
319
330
|
...metadata
|
|
320
331
|
};
|
|
321
|
-
|
|
332
|
+
const updatedUser = await this.userRepository.save(user);
|
|
333
|
+
// Emit user updated event
|
|
334
|
+
this.debugLogger.debug('Emitting user updated event (metadata)', 'UserService', { userId: id });
|
|
335
|
+
await this.eventEmitter.emitAsync(auth_constants_1.NestAuthEvents.USER_UPDATED, new user_updated_event_1.UserUpdatedEvent({
|
|
336
|
+
user: updatedUser,
|
|
337
|
+
tenantId: updatedUser.tenantId,
|
|
338
|
+
updatedFields: ['metadata']
|
|
339
|
+
}));
|
|
340
|
+
return updatedUser;
|
|
322
341
|
}
|
|
323
342
|
async countUsers(options) {
|
|
324
343
|
return this.userRepository.count(options);
|