import axios, { AxiosInstance } from "axios";
import { AuthConfig, AuthState } from "./types.js";
export class AuthManager {
private authState: AuthState = { isAuthenticated: false };
private config: AuthConfig;
private httpClient: AxiosInstance;
constructor(config: AuthConfig, baseUrl: string, timeout: number = 30000) {
this.config = config;
this.httpClient = axios.create({
baseURL: baseUrl,
timeout,
});
}
async authenticate(): Promise<void> {
if (this.config.type === "token") {
await this.authenticateWithToken();
} else if (this.config.type === "login") {
await this.authenticateWithLogin();
}
}
private async authenticateWithToken(): Promise<void> {
if (this.config.type !== "token") return;
this.authState = {
token: this.config.token,
isAuthenticated: true,
};
}
private async authenticateWithLogin(): Promise<void> {
if (this.config.type !== "login") return;
try {
const response = await this.httpClient.post(this.config.loginEndpoint, {
username: this.config.username,
password: this.config.password,
});
const token = response.data[this.config.tokenField];
if (!token) {
throw new Error(
`Token field '${this.config.tokenField}' not found in login response`
);
}
this.authState = {
token,
isAuthenticated: true,
// Set expiration if provided in response
expiresAt: response.data.expires_at
? new Date(response.data.expires_at)
: undefined,
};
} catch (error) {
this.authState = { isAuthenticated: false };
throw new Error(
`Authentication failed: ${
error instanceof Error ? error.message : "Unknown error"
}`
);
}
}
async ensureAuthenticated(): Promise<void> {
if (!this.isAuthenticated()) {
await this.authenticate();
}
}
isAuthenticated(): boolean {
if (!this.authState.isAuthenticated) {
return false;
}
// Check if token is expired
if (this.authState.expiresAt && this.authState.expiresAt <= new Date()) {
this.authState.isAuthenticated = false;
return false;
}
return true;
}
getAuthHeaders(): Record<string, string> {
if (!this.authState.token) {
return {};
}
return {
Authorization: `Bearer ${this.authState.token}`,
};
}
getToken(): string | undefined {
return this.authState.token;
}
logout(): void {
this.authState = { isAuthenticated: false };
}
}