Skip to content

Instantly share code, notes, and snippets.

@sam-artuso
Created April 4, 2024 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sam-artuso/0d844911f3c8a9d9062226de241dccc4 to your computer and use it in GitHub Desktop.
Save sam-artuso/0d844911f3c8a9d9062226de241dccc4 to your computer and use it in GitHub Desktop.
import { type OnModuleInit } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { httpFetchJson } from '@recharge/http';
import tracer from 'dd-trace';
import { AkeneoConfigService } from '../config/akeneo-config.service';
import { type AkeneoAuthenticationResponse } from './entity/akeneo-token-entity';
const refreshTokenDefaultExpiry = 1209600;
@Injectable()
export class AkeneoAuthenticationService implements OnModuleInit {
private accessToken?: string;
private accessTokenExpiryIn = 3600000;
private refreshBuffer = 600;
private refreshToken?: string;
private refreshTokenExpiry?: number;
constructor(private configService: AkeneoConfigService) {}
async onModuleInit() {
await this.fetchToken();
}
public getAuthorizationValue() {
return `Bearer ${this.accessToken}`;
}
private setAuthenticationResponse(response: AkeneoAuthenticationResponse) {
this.accessToken = response.access_token;
this.accessTokenExpiryIn = response.expires_in - this.refreshBuffer * 1000;
setTimeout(() => void this.fetchToken(), this.accessTokenExpiryIn);
this.refreshToken = response.refresh_token;
this.refreshTokenExpiry =
new Date().getTime() + refreshTokenDefaultExpiry * 1000;
}
private hasRefreshTokenExpired() {
const expiry = this.refreshTokenExpiry;
return expiry && expiry > new Date().getTime();
}
private async fetchToken() {
const response = await this.fetchAkeneoAuthenticationResponse();
this.setAuthenticationResponse(response);
}
private getBasicAuthForFetchToken() {
return Buffer.from(
`${this.configService.getClientId()}:${this.configService.getSecret()}`,
).toString('base64');
}
private fetchAkeneoAuthenticationResponse(): Promise<AkeneoAuthenticationResponse> {
if (this.hasRefreshTokenExpired()) {
return this.fetchAkeneoAuthenticationWithCredentials();
}
return this.fetchAkeneoAuthenticationWithRefreshToken();
}
private fetchAkeneoAuthenticationWithCredentials(): Promise<AkeneoAuthenticationResponse> {
tracer.dogstatsd.increment(
'app.product_information_service.akeneo.credentials_usage',
);
return httpFetchJson<AkeneoAuthenticationResponse>(
`${this.configService.getEndpoint()}/api/oauth/v1/token`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${this.getBasicAuthForFetchToken()}`,
},
body: JSON.stringify({
grant_type: 'password',
username: this.configService.getUsername(),
password: this.configService.getPassword(),
}),
},
);
}
private fetchAkeneoAuthenticationWithRefreshToken(): Promise<AkeneoAuthenticationResponse> {
tracer.dogstatsd.increment(
'app.product_information_service.akeneo.refresh_token_usage',
);
return httpFetchJson<AkeneoAuthenticationResponse>(
`${this.configService.getEndpoint()}/api/oauth/v1/token`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${this.getBasicAuthForFetchToken()}`,
},
body: JSON.stringify({
grant_type: 'refresh_token',
refresh_token: this.refreshToken,
}),
},
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment