odp-sdk
Version:
Ocean Data Platform JavaScript SDK
147 lines (131 loc) • 3.85 kB
text/typescript
import {
AuthenticationResult,
BrowserAuthOptions,
ILoggerCallback,
InteractionRequiredAuthError,
LogLevel,
PublicClientApplication,
} from "@azure/msal-browser"
import log from "loglevel"
const loggerCallback: ILoggerCallback = (level: LogLevel, message: string, containsPii: boolean): void => {
if (containsPii) {
return
}
switch (level) {
case LogLevel.Error:
log.error(message)
return
case LogLevel.Info:
log.info(message)
return
case LogLevel.Verbose:
log.debug(message)
return
case LogLevel.Warning:
log.warn(message)
return
}
}
interface BaseResponseT {
ok: boolean
message: string
}
interface UnauthenticatedResponseT extends BaseResponseT {
authenticated: false
}
interface AuthenticatedResponseT extends BaseResponseT {
authenticated: true
token: AuthenticationResult
}
export type AuthResponseT = AuthenticatedResponseT | UnauthenticatedResponseT
/**
* Auth class
*/
export class Auth {
private _msalInstance: PublicClientApplication
public constructor(authConfig: BrowserAuthOptions) {
this._msalInstance = new PublicClientApplication({
auth: authConfig,
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
secureCookies: false,
},
system: {
loggerOptions: {
piiLoggingEnabled: false,
loggerCallback,
},
windowHashTimeout: 60000,
iframeHashTimeout: 6000,
loadFrameTimeout: 0,
asyncPopups: false,
},
})
}
public logout = () => {
return this._msalInstance.logoutRedirect()
}
public getToken = async (scope: string[]): Promise<string> => {
const account = this._msalInstance.getAllAccounts()[0]
const request = {
account,
scopes: scope,
}
return new Promise<string>((resolve, reject) => {
this._msalInstance.acquireTokenSilent(request).then(res => {
if (res.accessToken) {
resolve(res.accessToken)
} else {
reject(new Error("No token acquired..."))
}
})
})
}
/*
* When using redirect APIs, handleRedirectPromise must be invoked when returning from the redirect. This ensures
* that the token response from the server is properly handled and temporary cache entries are cleaned up.
*/
public handleRedirectAuth = async (): Promise<AuthenticationResult | undefined> => {
try {
const redirectResponse = await this._msalInstance.handleRedirectPromise()
if (redirectResponse !== null) {
log.debug("Auth: Got redirect token")
// Acquire token silent success
return redirectResponse
}
} catch (error) {
log.error(error)
return
}
// MSAL.js v2 exposes several account APIs, logic to determine which account to use
// is the responsibility of the developer
const account = this._msalInstance.getAllAccounts()[0]
const accessTokenRequest = {
account,
scopes: ["openid", "profile", "email"],
}
const loginWithRedirect = () => {
this._msalInstance.acquireTokenRedirect(accessTokenRequest)
}
log.debug("Auth: Acquiring access token", accessTokenRequest)
if (!account) {
loginWithRedirect()
}
try {
const accessTokenResponse = await this._msalInstance.acquireTokenSilent(accessTokenRequest)
// Acquire token silent success
log.debug("Auth: Got silent token")
return accessTokenResponse
} catch (error) {
// Acquire token silent failure, and send an interactive request
if (error instanceof InteractionRequiredAuthError) {
log.debug("using fallback")
loginWithRedirect()
return
}
log.error("Auth: Failed to get silent token")
log.error(error)
}
}
}