UNPKG

saas-platform-auth-client

Version:

Authentication client for SaaS platform auth-service with password reset support

361 lines (355 loc) 11.8 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { AdminLoginRequestSchema: () => AdminLoginRequestSchema, AuthClient: () => AuthClient, ForgotPasswordRequestSchema: () => ForgotPasswordRequestSchema, LoginRequestSchema: () => LoginRequestSchema, RefreshTokenRequestSchema: () => RefreshTokenRequestSchema, ResetPasswordRequestSchema: () => ResetPasswordRequestSchema, VERSION: () => VERSION, ValidateTokenRequestSchema: () => ValidateTokenRequestSchema }); module.exports = __toCommonJS(src_exports); // src/auth-client.ts var import_saas_platform_core_client = require("saas-platform-core-client"); // src/types.ts var import_zod = require("zod"); var LoginRequestSchema = import_zod.z.object({ email: import_zod.z.string().email("Email inv\xE1lido"), password: import_zod.z.string().min(6, "Senha deve ter pelo menos 6 caracteres"), saasId: import_zod.z.string().min(1, "SaasId \xE9 obrigat\xF3rio") }); var RefreshTokenRequestSchema = import_zod.z.object({ refreshToken: import_zod.z.string().min(1, "RefreshToken \xE9 obrigat\xF3rio"), saasId: import_zod.z.string().min(1, "SaasId \xE9 obrigat\xF3rio") }); var ValidateTokenRequestSchema = import_zod.z.object({ token: import_zod.z.string().min(1, "Token \xE9 obrigat\xF3rio"), saasId: import_zod.z.string().min(1, "SaasId \xE9 obrigat\xF3rio") }); var AdminLoginRequestSchema = import_zod.z.object({ userId: import_zod.z.string().uuid("UserId deve ser um GUID v\xE1lido"), saasId: import_zod.z.string().min(1, "SaasId \xE9 obrigat\xF3rio") }); var ForgotPasswordRequestSchema = import_zod.z.object({ email: import_zod.z.string().email("Email inv\xE1lido"), saasId: import_zod.z.string().min(1, "SaasId \xE9 obrigat\xF3rio") }); var ResetPasswordRequestSchema = import_zod.z.object({ email: import_zod.z.string().email("Email inv\xE1lido"), resetCode: import_zod.z.string().length(6, "C\xF3digo deve ter exatamente 6 d\xEDgitos").regex(/^\d{6}$/, "C\xF3digo deve conter apenas n\xFAmeros"), newPassword: import_zod.z.string().min(6, "Nova senha deve ter pelo menos 6 caracteres").max(128, "Nova senha deve ter no m\xE1ximo 128 caracteres"), saasId: import_zod.z.string().min(1, "SaasId \xE9 obrigat\xF3rio") }); // src/auth-client.ts var AuthClient = class { constructor(config) { this.callbacks = {}; this.axiosInstance = null; this.authManager = new import_saas_platform_core_client.AuthManager(config.authServiceUrl, config.saasId); this.httpClient = new import_saas_platform_core_client.HttpClient(config); this.httpClient.setBaseURL(config.authServiceUrl); this.httpClient.setAuthManager(this.authManager); } /** * Login with email and password * Public endpoint - requires saasId in request body */ async login(request) { const validatedRequest = LoginRequestSchema.parse(request); const response = await this.httpClient.post("/auth/login", validatedRequest); if (response.success && response.data) { let expiresIn = 3600; if (response.data.expiresAt) { const expiresAt = new Date(response.data.expiresAt); const now = /* @__PURE__ */ new Date(); expiresIn = Math.floor((expiresAt.getTime() - now.getTime()) / 1e3); } this.authManager.setTokens({ accessToken: response.data.accessToken, refreshToken: response.data.refreshToken, expiresIn, tokenType: "Bearer" }); } return response; } /** * Refresh access token using refresh token * Public endpoint - requires saasId in request body */ async refreshToken(request) { const validatedRequest = RefreshTokenRequestSchema.parse(request); const response = await this.httpClient.post("/auth/refresh", validatedRequest); if (response.success && response.data) { let expiresIn = 3600; if (response.data.expiresAt) { const expiresAt = new Date(response.data.expiresAt); const now = /* @__PURE__ */ new Date(); expiresIn = Math.floor((expiresAt.getTime() - now.getTime()) / 1e3); } this.authManager.setTokens({ accessToken: response.data.accessToken, refreshToken: response.data.refreshToken, expiresIn, tokenType: "Bearer" }); } return response; } /** * Validate current token * Protected endpoint - uses Authorization header, saasId extracted from token */ async validateToken() { const token = this.authManager.getAccessToken(); if (!token) { return { success: false, error: { code: "NO_TOKEN", message: "No access token available" }, timestamp: (/* @__PURE__ */ new Date()).toISOString() }; } return await this.httpClient.get("/auth/verify"); } /** * Admin impersonation login * Protected endpoint - requires admin token in Authorization header */ async adminLogin(request) { const validatedRequest = AdminLoginRequestSchema.parse(request); const response = await this.httpClient.post("/auth/impersonate", validatedRequest); if (response.success && response.data) { let expiresIn = 3600; if (response.data.expiresAt) { const expiresAt = new Date(response.data.expiresAt); const now = /* @__PURE__ */ new Date(); expiresIn = Math.floor((expiresAt.getTime() - now.getTime()) / 1e3); } this.authManager.setTokens({ accessToken: response.data.accessToken, refreshToken: response.data.refreshToken, expiresIn, tokenType: "Bearer" }); } return response; } /** * Request password reset * Public endpoint - requires saasId in request body */ async forgotPassword(request) { const validatedRequest = ForgotPasswordRequestSchema.parse(request); return await this.httpClient.post("/auth/forgot-password", validatedRequest); } /** * Reset password with verification code * Public endpoint - requires saasId in request body */ async resetPassword(request) { const validatedRequest = ResetPasswordRequestSchema.parse(request); return await this.httpClient.post("/auth/reset-password", validatedRequest); } /** * Get service health status * Public endpoint */ async getHealth() { return await this.httpClient.get("/health"); } /** * Logout - clear stored tokens */ logout() { this.authManager.clearTokens(); } /** * Check if user is authenticated - considera tanto token válido quanto refresh token */ isAuthenticated() { const result = this.authManager.hasAnyAuthenticationMaterial(); return result; } /** * Get current user info from token - interface mais rica * Se o token estiver expirado, tenta renovar automaticamente */ async getCurrentUser() { const hasValidToken = this.authManager.hasValidToken(); if (hasValidToken) { const payload = this.authManager.decodeToken(); if (payload) { const userInfo = { id: payload.sub, email: payload.email, name: payload.name || payload.email, role: payload.role || "USER", saasId: payload.saasId }; return userInfo; } } const hasAuthMaterial = this.authManager.hasAnyAuthenticationMaterial(); if (hasAuthMaterial) { try { const newToken = await this.authManager.ensureValidToken(); if (newToken) { const payload = this.authManager.decodeToken(); if (payload) { const userInfo = { id: payload.sub, email: payload.email, name: payload.name || payload.email, role: payload.role || "USER", saasId: payload.saasId }; return userInfo; } } } catch (error) { return null; } } return null; } /** * Get current access token */ getAccessToken() { return this.authManager.getAccessToken(); } /** * Get refresh token */ getRefreshToken() { return this.authManager.getRefreshToken(); } /** * Check if token is expired */ isTokenExpired() { return this.authManager.isTokenExpired(); } /** * Get SaasId from current token */ getSaasId() { return this.authManager.getSaasIdFromToken(); } /** * Get user ID from current token */ getUserId() { return this.authManager.getUserIdFromToken(); } /** * Set callbacks para eventos de autenticação */ setCallbacks(callbacks) { this.callbacks = { ...callbacks }; } /** * Setup HTTP interceptor automático para Axios * Intercepta requests, faz refresh transparente, retry automático */ setupAxiosInterceptor(axiosInstance) { this.axiosInstance = axiosInstance; axiosInstance.interceptors.request.use( (config) => { const token = this.getAccessToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error) ); axiosInstance.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; if (error.response?.status === 401 && !originalRequest._retry) { originalRequest._retry = true; const refreshToken = this.authManager.getRefreshToken(); if (!refreshToken) { this.handleSessionExpired(); return Promise.reject(error); } try { const newToken = await this.authManager.ensureValidToken(); if (newToken) { originalRequest.headers.Authorization = `Bearer ${newToken}`; return axiosInstance(originalRequest); } else { this.handleSessionExpired(); return Promise.reject(error); } } catch (refreshError) { this.handleSessionExpired(); return Promise.reject(error); } } return Promise.reject(error); } ); } /** * Handle session expired - chama callback apropriado */ handleSessionExpired() { this.clearTokens(); if (this.callbacks.onSessionExpired) { this.callbacks.onSessionExpired(); } else if (this.callbacks.onLoginRequired) { this.callbacks.onLoginRequired(); } } /** * Ensure we have a valid access token, refreshing if necessary */ async ensureValidToken() { return await this.authManager.ensureValidToken(); } /** * Clear tokens - agora também remove da memória do AuthManager */ clearTokens() { this.authManager.clearTokens(); } }; // src/index.ts var VERSION = "1.3.0"; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AdminLoginRequestSchema, AuthClient, ForgotPasswordRequestSchema, LoginRequestSchema, RefreshTokenRequestSchema, ResetPasswordRequestSchema, VERSION, ValidateTokenRequestSchema });