import axios from 'axios';
import { logger } from './logger.js';
interface TokenResponse {
access_token: string;
token_type: string;
expires_in: number;
}
export class CiscoAuthClient {
private clientId: string;
private clientSecret: string;
private tokenEndpoint = 'https://id.cisco.com/oauth2/default/v1/token';
private accessToken: string | null = null;
private tokenExpiry: number = 0;
constructor(clientId: string, clientSecret: string) {
this.clientId = clientId;
this.clientSecret = clientSecret;
logger.debug('CiscoAuthClient initialized', {
clientId: clientId.substring(0, 8) + '***',
tokenEndpoint: this.tokenEndpoint
});
}
async getAccessToken(): Promise<string> {
// Return cached token if still valid (with 5 minute buffer)
if (this.accessToken && Date.now() < this.tokenExpiry - 300000) {
logger.debug('Using cached access token', {
expiresIn: Math.floor((this.tokenExpiry - Date.now()) / 1000) + 's'
});
return this.accessToken;
}
logger.info('Requesting new access token from Cisco OAuth');
// Request new token
const params = new URLSearchParams({
grant_type: 'client_credentials',
client_id: this.clientId,
client_secret: this.clientSecret,
});
try {
logger.apiRequest('POST', this.tokenEndpoint);
const response = await axios.post<TokenResponse>(
this.tokenEndpoint,
params.toString(),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
}
);
logger.apiResponse('POST', this.tokenEndpoint, response.status, {
token_type: response.data.token_type,
expires_in: response.data.expires_in
});
this.accessToken = response.data.access_token;
// Set expiry time (expires_in is in seconds)
this.tokenExpiry = Date.now() + response.data.expires_in * 1000;
logger.info('Access token obtained successfully', {
expiresIn: response.data.expires_in + 's',
tokenType: response.data.token_type
});
return this.accessToken;
} catch (error) {
logger.apiError('POST', this.tokenEndpoint, error);
if (axios.isAxiosError(error)) {
throw new Error(
`Failed to obtain access token: ${error.response?.data?.error_description || error.message}`
);
}
throw error;
}
}
clearToken(): void {
logger.info('Clearing cached access token');
this.accessToken = null;
this.tokenExpiry = 0;
}
}