saas-platform-auth-client
Version:
Authentication client for SaaS platform auth-service with password reset support
361 lines (355 loc) • 11.8 kB
JavaScript
"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
});