/* eslint-disable no-return-await */
import {
Configuration,
LogLevel,
PublicClientApplication,
AccountInfo,
AuthenticationResult,
SilentFlowRequest,
} from '@azure/msal-node';
import { MsalInfo } from '../constants';
import { Axios } from 'axios';
import * as AxiosPack from './axios';
export default class MsalProvider {
scopes: string[] = [
'user.read',
'profile',
'teamsactivity.read',
'reports.read.all',
'user.read.all',
'group.read.all',
'onlinemeetingartifact.read.all',
];
private account: AccountInfo | undefined = undefined;
private readonly axios;
private readonly msalPublicClient: PublicClientApplication;
constructor(
private redirectUri: string = MsalInfo.REDIRECT_URI,
private readonly config: Configuration = {
auth: {
clientId: process.env.MSAL_CLIENT_ID as string,
authority:
process.env.MSAL_AUTHORITY_URL ?? MsalInfo.COMMON_AUTHORITY_URL,
clientSecret: process.env.MSAL_CLIENT_SECRET ?? undefined,
},
cache: undefined,
system: {
loggerOptions: {
loggerCallback: (lvl, msg, containsPi) => {
// TODO
},
piiLoggingEnabled: false,
logLevel: LogLevel.Warning,
},
},
}
) {
this.msalPublicClient = new PublicClientApplication(this.config);
this.axios = AxiosPack.msal();
}
public setScopes(data: string[]) {
this.scopes = data;
return this;
}
public setRedirectUri(uri: string) {
this.redirectUri = uri;
}
public async logout() {
if (this.account) {
await this.msalPublicClient.getTokenCache().removeAccount(this.account);
this.account = undefined;
}
}
public async getAuthUrl(
redirectUri: string = this.redirectUri,
scopes: string[] = this.scopes
) {
return await this.msalPublicClient.getAuthCodeUrl({
scopes,
redirectUri,
prompt: MsalInfo.promptType.SELECT_ACCOUNT.toString(),
});
}
public async getTokenByCode(
authCode: string,
redirectUri: string = this.redirectUri,
scopes: string[] = this.scopes
) {
const result = await this.msalPublicClient.acquireTokenByCode({
scopes,
redirectUri,
code: authCode ?? '',
});
this.setAccountFromResponse(result);
return result;
}
public async getAccessToken(
returnString: boolean = false,
scopes: string[] = this.scopes
) {
const account = this.account || (await this.getAccount());
if (account) {
const authResponse = await this.getTokenSilent({
account,
scopes,
forceRefresh: false,
});
if (authResponse && authResponse !== null) {
if (returnString) return authResponse.accessToken;
return authResponse;
}
}
}
public async getTokenSilent(
tokenRequest: SilentFlowRequest
😞 Promise<AuthenticationResult | null | undefined> {
try {
return await this.msalPublicClient.acquireTokenSilent(tokenRequest);
} catch (error) {
return null;
}
}
public async setAccountFromResponse(response: AuthenticationResult) {
if (response) {
this.account = response?.account || undefined;
} else {
this.account = await this.getAccount();
}
return this.account;
}
public async getAccount() {
const cache = this.msalPublicClient.getTokenCache();
const currentAccounts = await cache?.getAllAccounts();
if (currentAccounts && currentAccounts?.length! >= 1) {
return currentAccounts[0];
}
return undefined;
}
async getEndpoint<T extends unknown>(
token: string,
resource: string
😞 Promise<T> {
try {
const response = await this.axios(token).get<T>(resource);
return response.data;
} catch (error) {
const err: { data: { error: unknown } } = error as {
data: { error: unknown };
};
console.error(err.data);
throw error;
}
}
}