Estructura inicial del proyecto
This commit is contained in:
17
backend/node_modules/@azure/msal-browser/src/naa/AccountInfo.ts
generated
vendored
Normal file
17
backend/node_modules/@azure/msal-browser/src/naa/AccountInfo.ts
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
export type AccountInfo = {
|
||||
homeAccountId?: string;
|
||||
environment: string;
|
||||
tenantId?: string;
|
||||
username: string;
|
||||
localAccountId?: string;
|
||||
name?: string;
|
||||
idToken?: string; // idTokenClaims can be parsed from idToken in MSAL.js
|
||||
platformBrokerId?: string; // Used by WAM previous called nativeAccountId
|
||||
idTokenClaims?: object;
|
||||
loginHint?: string;
|
||||
};
|
||||
17
backend/node_modules/@azure/msal-browser/src/naa/AuthBridge.ts
generated
vendored
Normal file
17
backend/node_modules/@azure/msal-browser/src/naa/AuthBridge.ts
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
export type AuthBridgeResponse = string | { data: string };
|
||||
export interface AuthBridge {
|
||||
addEventListener: (
|
||||
eventName: string,
|
||||
callback: (response: AuthBridgeResponse) => void
|
||||
) => void;
|
||||
postMessage: (message: string) => void;
|
||||
removeEventListener: (
|
||||
eventName: string,
|
||||
callback: (response: AuthBridgeResponse) => void
|
||||
) => void;
|
||||
}
|
||||
12
backend/node_modules/@azure/msal-browser/src/naa/AuthResult.ts
generated
vendored
Normal file
12
backend/node_modules/@azure/msal-browser/src/naa/AuthResult.ts
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { AccountInfo } from "./AccountInfo.js";
|
||||
import { TokenResponse } from "./TokenResponse.js";
|
||||
|
||||
export type AuthResult = {
|
||||
token: TokenResponse;
|
||||
account: AccountInfo;
|
||||
};
|
||||
17
backend/node_modules/@azure/msal-browser/src/naa/BridgeAccountContext.ts
generated
vendored
Normal file
17
backend/node_modules/@azure/msal-browser/src/naa/BridgeAccountContext.ts
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AccountContext is used to pass account information when the bridge is initialized
|
||||
*
|
||||
* NAA (MetaOS) apps are created and destroyed for the same session multiple times.
|
||||
* `AccountContext` helps in booting up the cached account when the bridge
|
||||
* is recreated for a new NAA instance in the same auth session.
|
||||
*/
|
||||
export interface AccountContext {
|
||||
homeAccountId: string;
|
||||
environment: string;
|
||||
tenantId: string;
|
||||
}
|
||||
9
backend/node_modules/@azure/msal-browser/src/naa/BridgeCapabilities.ts
generated
vendored
Normal file
9
backend/node_modules/@azure/msal-browser/src/naa/BridgeCapabilities.ts
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
// Capabilities are intended to future proof the bridge against any feature support
|
||||
export interface BridgeCapabilities {
|
||||
queryAccount?: boolean;
|
||||
}
|
||||
18
backend/node_modules/@azure/msal-browser/src/naa/BridgeError.ts
generated
vendored
Normal file
18
backend/node_modules/@azure/msal-browser/src/naa/BridgeError.ts
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { BridgeStatusCode } from "./BridgeStatusCode.js";
|
||||
|
||||
export type BridgeError = {
|
||||
status: BridgeStatusCode;
|
||||
code?: string; // auth_flow_last_error such as invalid_grant
|
||||
subError?: string; // server_suberror_code such as consent_required
|
||||
description?: string;
|
||||
properties?: object; // additional telemetry info
|
||||
};
|
||||
|
||||
export function isBridgeError(error: unknown): error is BridgeError {
|
||||
return (error as BridgeError).status !== undefined;
|
||||
}
|
||||
233
backend/node_modules/@azure/msal-browser/src/naa/BridgeProxy.ts
generated
vendored
Normal file
233
backend/node_modules/@azure/msal-browser/src/naa/BridgeProxy.ts
generated
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { AuthBridge, AuthBridgeResponse } from "./AuthBridge.js";
|
||||
import { AuthResult } from "./AuthResult.js";
|
||||
import { BridgeCapabilities } from "./BridgeCapabilities.js";
|
||||
import { AccountContext } from "./BridgeAccountContext.js";
|
||||
import { BridgeError } from "./BridgeError.js";
|
||||
import { BridgeRequest } from "./BridgeRequest.js";
|
||||
import {
|
||||
BridgeRequestEnvelope,
|
||||
BridgeMethods,
|
||||
} from "./BridgeRequestEnvelope.js";
|
||||
import { BridgeResponseEnvelope } from "./BridgeResponseEnvelope.js";
|
||||
import { BridgeStatusCode } from "./BridgeStatusCode.js";
|
||||
import { IBridgeProxy } from "./IBridgeProxy.js";
|
||||
import { InitContext } from "./InitContext.js";
|
||||
import { TokenRequest } from "./TokenRequest.js";
|
||||
import * as BrowserCrypto from "../crypto/BrowserCrypto.js";
|
||||
import { BrowserConstants } from "../utils/BrowserConstants.js";
|
||||
import { version } from "../packageMetadata.js";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
nestedAppAuthBridge: AuthBridge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BridgeProxy
|
||||
* Provides a proxy for accessing a bridge to a host app and/or
|
||||
* platform broker
|
||||
*/
|
||||
export class BridgeProxy implements IBridgeProxy {
|
||||
static bridgeRequests: BridgeRequest[] = [];
|
||||
sdkName: string;
|
||||
sdkVersion: string;
|
||||
capabilities?: BridgeCapabilities;
|
||||
accountContext?: AccountContext;
|
||||
|
||||
/**
|
||||
* initializeNestedAppAuthBridge - Initializes the bridge to the host app
|
||||
* @returns a promise that resolves to an InitializeBridgeResponse or rejects with an Error
|
||||
* @remarks This method will be called by the create factory method
|
||||
* @remarks If the bridge is not available, this method will throw an error
|
||||
*/
|
||||
protected static async initializeNestedAppAuthBridge(): Promise<InitContext> {
|
||||
if (window === undefined) {
|
||||
throw new Error("window is undefined");
|
||||
}
|
||||
if (window.nestedAppAuthBridge === undefined) {
|
||||
throw new Error("window.nestedAppAuthBridge is undefined");
|
||||
}
|
||||
|
||||
try {
|
||||
window.nestedAppAuthBridge.addEventListener(
|
||||
"message",
|
||||
(response: AuthBridgeResponse) => {
|
||||
const responsePayload =
|
||||
typeof response === "string" ? response : response.data;
|
||||
const responseEnvelope: BridgeResponseEnvelope =
|
||||
JSON.parse(responsePayload);
|
||||
const request = BridgeProxy.bridgeRequests.find(
|
||||
(element) =>
|
||||
element.requestId === responseEnvelope.requestId
|
||||
);
|
||||
if (request !== undefined) {
|
||||
BridgeProxy.bridgeRequests.splice(
|
||||
BridgeProxy.bridgeRequests.indexOf(request),
|
||||
1
|
||||
);
|
||||
if (responseEnvelope.success) {
|
||||
request.resolve(responseEnvelope);
|
||||
} else {
|
||||
request.reject(responseEnvelope.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const bridgeResponse = await new Promise<BridgeResponseEnvelope>(
|
||||
(resolve, reject) => {
|
||||
const message = BridgeProxy.buildRequest("GetInitContext");
|
||||
|
||||
const request: BridgeRequest = {
|
||||
requestId: message.requestId,
|
||||
method: message.method,
|
||||
resolve: resolve,
|
||||
reject: reject,
|
||||
};
|
||||
BridgeProxy.bridgeRequests.push(request);
|
||||
window.nestedAppAuthBridge.postMessage(
|
||||
JSON.stringify(message)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return BridgeProxy.validateBridgeResultOrThrow(
|
||||
bridgeResponse.initContext
|
||||
);
|
||||
} catch (error) {
|
||||
window.console.log(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getTokenInteractive - Attempts to get a token interactively from the bridge
|
||||
* @param request A token request
|
||||
* @returns a promise that resolves to an auth result or rejects with a BridgeError
|
||||
*/
|
||||
public getTokenInteractive(request: TokenRequest): Promise<AuthResult> {
|
||||
return this.getToken("GetTokenPopup", request);
|
||||
}
|
||||
|
||||
/**
|
||||
* getTokenSilent Attempts to get a token silently from the bridge
|
||||
* @param request A token request
|
||||
* @returns a promise that resolves to an auth result or rejects with a BridgeError
|
||||
*/
|
||||
public getTokenSilent(request: TokenRequest): Promise<AuthResult> {
|
||||
return this.getToken("GetToken", request);
|
||||
}
|
||||
|
||||
private async getToken(
|
||||
requestType: BridgeMethods,
|
||||
request: TokenRequest
|
||||
): Promise<AuthResult> {
|
||||
const result = await this.sendRequest(requestType, {
|
||||
tokenParams: request,
|
||||
});
|
||||
return {
|
||||
token: BridgeProxy.validateBridgeResultOrThrow(result.token),
|
||||
account: BridgeProxy.validateBridgeResultOrThrow(result.account),
|
||||
};
|
||||
}
|
||||
|
||||
public getHostCapabilities(): BridgeCapabilities | null {
|
||||
return this.capabilities ?? null;
|
||||
}
|
||||
|
||||
public getAccountContext(): AccountContext | null {
|
||||
return this.accountContext ? this.accountContext : null;
|
||||
}
|
||||
|
||||
private static buildRequest(
|
||||
method: BridgeMethods,
|
||||
requestParams?: Partial<BridgeRequestEnvelope>
|
||||
): BridgeRequestEnvelope {
|
||||
return {
|
||||
messageType: "NestedAppAuthRequest",
|
||||
method: method,
|
||||
requestId: BrowserCrypto.createNewGuid(),
|
||||
sendTime: Date.now(),
|
||||
clientLibrary: BrowserConstants.MSAL_SKU,
|
||||
clientLibraryVersion: version,
|
||||
...requestParams,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A method used to send a request to the bridge
|
||||
* @param request A token request
|
||||
* @returns a promise that resolves to a response of provided type or rejects with a BridgeError
|
||||
*/
|
||||
private sendRequest(
|
||||
method: BridgeMethods,
|
||||
requestParams?: Partial<BridgeRequestEnvelope>
|
||||
): Promise<BridgeResponseEnvelope> {
|
||||
const message = BridgeProxy.buildRequest(method, requestParams);
|
||||
|
||||
const promise = new Promise<BridgeResponseEnvelope>(
|
||||
(resolve, reject) => {
|
||||
const request: BridgeRequest = {
|
||||
requestId: message.requestId,
|
||||
method: message.method,
|
||||
resolve: resolve,
|
||||
reject: reject,
|
||||
};
|
||||
BridgeProxy.bridgeRequests.push(request);
|
||||
window.nestedAppAuthBridge.postMessage(JSON.stringify(message));
|
||||
}
|
||||
);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
private static validateBridgeResultOrThrow<T>(input: T | undefined): T {
|
||||
if (input === undefined) {
|
||||
const bridgeError: BridgeError = {
|
||||
status: BridgeStatusCode.NestedAppAuthUnavailable,
|
||||
};
|
||||
throw bridgeError;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for BridgeProxy
|
||||
* @param sdkName The name of the SDK being used to make requests on behalf of the app
|
||||
* @param sdkVersion The version of the SDK being used to make requests on behalf of the app
|
||||
* @param capabilities The capabilities of the bridge / SDK / platform broker
|
||||
*/
|
||||
private constructor(
|
||||
sdkName: string,
|
||||
sdkVersion: string,
|
||||
accountContext?: AccountContext,
|
||||
capabilities?: BridgeCapabilities
|
||||
) {
|
||||
this.sdkName = sdkName;
|
||||
this.sdkVersion = sdkVersion;
|
||||
this.accountContext = accountContext;
|
||||
this.capabilities = capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method for creating an implementation of IBridgeProxy
|
||||
* @returns A promise that resolves to a BridgeProxy implementation
|
||||
*/
|
||||
public static async create(): Promise<IBridgeProxy> {
|
||||
const response = await BridgeProxy.initializeNestedAppAuthBridge();
|
||||
return new BridgeProxy(
|
||||
response.sdkName,
|
||||
response.sdkVersion,
|
||||
response.accountContext,
|
||||
response.capabilities
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default BridgeProxy;
|
||||
16
backend/node_modules/@azure/msal-browser/src/naa/BridgeRequest.ts
generated
vendored
Normal file
16
backend/node_modules/@azure/msal-browser/src/naa/BridgeRequest.ts
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { BridgeResponseEnvelope } from "./BridgeResponseEnvelope.js";
|
||||
|
||||
export type BridgeRequest = {
|
||||
requestId: string;
|
||||
method: string;
|
||||
resolve: (
|
||||
value: BridgeResponseEnvelope | PromiseLike<BridgeResponseEnvelope>
|
||||
) => void;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
reject: (reason?: any) => void;
|
||||
};
|
||||
29
backend/node_modules/@azure/msal-browser/src/naa/BridgeRequestEnvelope.ts
generated
vendored
Normal file
29
backend/node_modules/@azure/msal-browser/src/naa/BridgeRequestEnvelope.ts
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { TokenRequest } from "./TokenRequest.js";
|
||||
|
||||
export type BridgeMethods = "GetToken" | "GetInitContext" | "GetTokenPopup";
|
||||
|
||||
export type BridgeRequestEnvelope = {
|
||||
messageType: "NestedAppAuthRequest";
|
||||
method: BridgeMethods;
|
||||
sendTime?: number; // Assume this is epoch
|
||||
clientLibrary?: string;
|
||||
clientLibraryVersion?: string;
|
||||
requestId: string;
|
||||
tokenParams?: TokenRequest;
|
||||
};
|
||||
|
||||
export function isBridgeRequestEnvelope(
|
||||
obj: unknown
|
||||
): obj is BridgeRequestEnvelope {
|
||||
return (
|
||||
(obj as BridgeRequestEnvelope).messageType !== undefined &&
|
||||
(obj as BridgeRequestEnvelope).messageType === "NestedAppAuthRequest" &&
|
||||
(obj as BridgeRequestEnvelope).method !== undefined &&
|
||||
(obj as BridgeRequestEnvelope).requestId !== undefined
|
||||
);
|
||||
}
|
||||
19
backend/node_modules/@azure/msal-browser/src/naa/BridgeResponseEnvelope.ts
generated
vendored
Normal file
19
backend/node_modules/@azure/msal-browser/src/naa/BridgeResponseEnvelope.ts
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { BridgeError } from "./BridgeError.js";
|
||||
import { TokenResponse } from "./TokenResponse.js";
|
||||
import { AccountInfo } from "./AccountInfo.js";
|
||||
import { InitContext } from "./InitContext.js";
|
||||
|
||||
export type BridgeResponseEnvelope = {
|
||||
messageType: "NestedAppAuthResponse";
|
||||
requestId: string;
|
||||
success: boolean; // false if body is error
|
||||
token?: TokenResponse;
|
||||
error?: BridgeError;
|
||||
account?: AccountInfo;
|
||||
initContext?: InitContext;
|
||||
};
|
||||
17
backend/node_modules/@azure/msal-browser/src/naa/BridgeStatusCode.ts
generated
vendored
Normal file
17
backend/node_modules/@azure/msal-browser/src/naa/BridgeStatusCode.ts
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
export const BridgeStatusCode = {
|
||||
UserInteractionRequired: "USER_INTERACTION_REQUIRED",
|
||||
UserCancel: "USER_CANCEL",
|
||||
NoNetwork: "NO_NETWORK",
|
||||
TransientError: "TRANSIENT_ERROR",
|
||||
PersistentError: "PERSISTENT_ERROR",
|
||||
Disabled: "DISABLED",
|
||||
AccountUnavailable: "ACCOUNT_UNAVAILABLE",
|
||||
NestedAppAuthUnavailable: "NESTED_APP_AUTH_UNAVAILABLE", // NAA is unavailable in the current context, can retry with standard browser based auth
|
||||
} as const;
|
||||
export type BridgeStatusCode =
|
||||
(typeof BridgeStatusCode)[keyof typeof BridgeStatusCode];
|
||||
16
backend/node_modules/@azure/msal-browser/src/naa/IBridgeProxy.ts
generated
vendored
Normal file
16
backend/node_modules/@azure/msal-browser/src/naa/IBridgeProxy.ts
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { AuthResult } from "./AuthResult.js";
|
||||
import { AccountContext } from "./BridgeAccountContext.js";
|
||||
import { BridgeCapabilities } from "./BridgeCapabilities.js";
|
||||
import { TokenRequest } from "./TokenRequest.js";
|
||||
|
||||
export interface IBridgeProxy {
|
||||
getTokenInteractive(request: TokenRequest): Promise<AuthResult>;
|
||||
getTokenSilent(request: TokenRequest): Promise<AuthResult>;
|
||||
getHostCapabilities(): BridgeCapabilities | null;
|
||||
getAccountContext(): AccountContext | null;
|
||||
}
|
||||
14
backend/node_modules/@azure/msal-browser/src/naa/InitContext.ts
generated
vendored
Normal file
14
backend/node_modules/@azure/msal-browser/src/naa/InitContext.ts
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { BridgeCapabilities } from "./BridgeCapabilities.js";
|
||||
import { AccountContext } from "./BridgeAccountContext.js";
|
||||
|
||||
export interface InitContext {
|
||||
capabilities?: BridgeCapabilities;
|
||||
sdkName: string;
|
||||
sdkVersion: string;
|
||||
accountContext?: AccountContext;
|
||||
}
|
||||
25
backend/node_modules/@azure/msal-browser/src/naa/TokenRequest.ts
generated
vendored
Normal file
25
backend/node_modules/@azure/msal-browser/src/naa/TokenRequest.ts
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
export type TokenRequest = {
|
||||
platformBrokerId?: string; // Account identifier used by OneAuth
|
||||
clientId: string;
|
||||
authority?: string;
|
||||
resource?: string;
|
||||
scope: string;
|
||||
correlationId: string;
|
||||
claims?: string;
|
||||
state?: string;
|
||||
reqCnf?: string; // Having OneAuth own the keypair is better for hardware token binding support
|
||||
keyId?: string; // Having OneAuth own the keypair is better for hardware token binding support
|
||||
authenticationScheme?: string;
|
||||
shrClaims?: string;
|
||||
shrNonce?: string;
|
||||
resourceRequestMethod?: string;
|
||||
resourceRequestUri?: string;
|
||||
extendedExpiryToken?: boolean;
|
||||
extraParameters?: Map<string, string>;
|
||||
forceRefresh?: boolean;
|
||||
};
|
||||
57
backend/node_modules/@azure/msal-browser/src/naa/TokenResponse.ts
generated
vendored
Normal file
57
backend/node_modules/@azure/msal-browser/src/naa/TokenResponse.ts
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
export type TokenResponse = {
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
id_token: string;
|
||||
properties: TokenResponseProperties | null;
|
||||
scope?: string;
|
||||
shr?: string; // token binding enabled at native layer it is the access token, not the signing keys
|
||||
extendedLifetimeToken?: boolean;
|
||||
authority?: string;
|
||||
};
|
||||
|
||||
export type TokenResponseProperties = {
|
||||
MATS?: string;
|
||||
};
|
||||
|
||||
/*
|
||||
* Sample response below
|
||||
* {
|
||||
* "body":{
|
||||
* "access_token":"<token>",
|
||||
* "account":{"environment":"login.microsoftonline.com",
|
||||
* "homeAccountId":"2995ae49-d9dd-409d-8d62-ba969ce58a81.51178b70-16cc-41b5-bef1-ae1808139065",
|
||||
* "idTokenClaims":{
|
||||
* "aud":"a076930c-cfc9-4ebd-9607-7963bccbf666",
|
||||
* "exp":"1680557128",
|
||||
* "graph_url":"https://graph.microsoft.com",
|
||||
* "iat":"1680553228",
|
||||
* "iss":"https://login.microsoftonline.com/51178b70-16cc-41b5-bef1-ae1808139065/v2.0",
|
||||
* "name":"Adele Vance",
|
||||
* "nbf":"1680553228",
|
||||
* "oid":"2995ae49-d9dd-409d-8d62-ba969ce58a81",
|
||||
* "preferred_username":"AdeleV@vc6w6.onmicrosoft.com",
|
||||
* "rh":"0.AX0AcIsXUcwWtUG-8a4YCBOQZQyTdqDJz71Olgd5Y7zL9maaAHs.",
|
||||
* "sovereignty2":"Global",
|
||||
* "sub":"wtxUI1WD2C--Bl8vN1p-P-VgadGud8QSqXD4Vp5i9sc",
|
||||
* "tid":"51178b70-16cc-41b5-bef1-ae1808139065",
|
||||
* "uti":"39pEKQyYDU6SXjD_phaCAA",
|
||||
* "ver":"2.0"},
|
||||
* "localAccountId":"2995ae49-d9dd-409d-8d62-ba969ce58a81",
|
||||
* "name":"Adele Vance",
|
||||
* "tenantId":"51178b70-16cc-41b5-bef1-ae1808139065",
|
||||
* "username":"AdeleV@vc6w6.onmicrosoft.com"
|
||||
* },
|
||||
* "client_info":"",
|
||||
* "expires_in":4290,
|
||||
* "id_token":"",
|
||||
* "properties":null,
|
||||
* "scope":"User.Read",
|
||||
* "state":""},
|
||||
* "requestId":"8863d6e8-a539-43e3-84b6-ca1bf64943f3",
|
||||
* "success":true}
|
||||
*/
|
||||
351
backend/node_modules/@azure/msal-browser/src/naa/mapping/NestedAppAuthAdapter.ts
generated
vendored
Normal file
351
backend/node_modules/@azure/msal-browser/src/naa/mapping/NestedAppAuthAdapter.ts
generated
vendored
Normal file
@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { TokenRequest } from "../TokenRequest.js";
|
||||
import { AccountInfo as NaaAccountInfo } from "../AccountInfo.js";
|
||||
import { RedirectRequest } from "../../request/RedirectRequest.js";
|
||||
import { PopupRequest } from "../../request/PopupRequest.js";
|
||||
import {
|
||||
AccountInfo as MsalAccountInfo,
|
||||
AuthError,
|
||||
ClientAuthError,
|
||||
ClientConfigurationError,
|
||||
InteractionRequiredAuthError,
|
||||
ServerError,
|
||||
ICrypto,
|
||||
Logger,
|
||||
AuthToken,
|
||||
TokenClaims,
|
||||
ClientAuthErrorCodes,
|
||||
RequestParameterBuilder,
|
||||
StringUtils,
|
||||
createClientAuthError,
|
||||
AccountInfo,
|
||||
IdTokenEntity,
|
||||
AccessTokenEntity,
|
||||
TenantProfile,
|
||||
buildTenantProfile,
|
||||
getTenantIdFromIdTokenClaims,
|
||||
TimeUtils,
|
||||
Constants,
|
||||
} from "@azure/msal-common/browser";
|
||||
import { isBridgeError } from "../BridgeError.js";
|
||||
import { BridgeStatusCode } from "../BridgeStatusCode.js";
|
||||
import { AuthenticationResult } from "../../response/AuthenticationResult.js";
|
||||
import {} from "../../error/BrowserAuthErrorCodes.js";
|
||||
import { AuthResult } from "../AuthResult.js";
|
||||
import { SsoSilentRequest } from "../../request/SsoSilentRequest.js";
|
||||
import { SilentRequest } from "../../request/SilentRequest.js";
|
||||
|
||||
export class NestedAppAuthAdapter {
|
||||
protected crypto: ICrypto;
|
||||
protected logger: Logger;
|
||||
protected clientId: string;
|
||||
protected clientCapabilities: string[];
|
||||
|
||||
constructor(
|
||||
clientId: string,
|
||||
clientCapabilities: string[],
|
||||
crypto: ICrypto,
|
||||
logger: Logger
|
||||
) {
|
||||
this.clientId = clientId;
|
||||
this.clientCapabilities = clientCapabilities;
|
||||
this.crypto = crypto;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public toNaaTokenRequest(
|
||||
request:
|
||||
| PopupRequest
|
||||
| RedirectRequest
|
||||
| SilentRequest
|
||||
| SsoSilentRequest
|
||||
): TokenRequest {
|
||||
let extraParams: Map<string, string>;
|
||||
if (request.extraQueryParameters === undefined) {
|
||||
extraParams = new Map<string, string>();
|
||||
} else {
|
||||
extraParams = new Map<string, string>(
|
||||
Object.entries(request.extraQueryParameters)
|
||||
);
|
||||
}
|
||||
|
||||
const correlationId =
|
||||
request.correlationId || this.crypto.createNewGuid();
|
||||
const claims = RequestParameterBuilder.addClientCapabilitiesToClaims(
|
||||
request.claims,
|
||||
this.clientCapabilities
|
||||
);
|
||||
const scopes = request.scopes || Constants.OIDC_DEFAULT_SCOPES;
|
||||
const tokenRequest: TokenRequest = {
|
||||
platformBrokerId: request.account?.homeAccountId,
|
||||
clientId: this.clientId,
|
||||
authority: request.authority,
|
||||
resource: request.resource,
|
||||
scope: scopes.join(" "),
|
||||
correlationId,
|
||||
claims: !StringUtils.isEmptyObj(claims) ? claims : undefined,
|
||||
state: request.state,
|
||||
authenticationScheme:
|
||||
request.authenticationScheme ||
|
||||
Constants.AuthenticationScheme.BEARER,
|
||||
extraParameters: extraParams,
|
||||
};
|
||||
|
||||
return tokenRequest;
|
||||
}
|
||||
|
||||
public fromNaaTokenResponse(
|
||||
request: TokenRequest,
|
||||
response: AuthResult,
|
||||
reqTimestamp: number
|
||||
): AuthenticationResult {
|
||||
if (!response.token.id_token || !response.token.access_token) {
|
||||
throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken);
|
||||
}
|
||||
|
||||
// Request timestamp and AuthResult expires_in are in seconds, converting to Date for AuthenticationResult
|
||||
const expiresOn = TimeUtils.toDateFromSeconds(
|
||||
reqTimestamp + (response.token.expires_in || 0)
|
||||
);
|
||||
const idTokenClaims = AuthToken.extractTokenClaims(
|
||||
response.token.id_token,
|
||||
this.crypto.base64Decode
|
||||
);
|
||||
const account = this.fromNaaAccountInfo(
|
||||
response.account,
|
||||
response.token.id_token,
|
||||
idTokenClaims
|
||||
);
|
||||
const scopes = response.token.scope || request.scope;
|
||||
|
||||
const authenticationResult: AuthenticationResult = {
|
||||
authority: response.token.authority || account.environment,
|
||||
uniqueId: account.localAccountId,
|
||||
tenantId: account.tenantId,
|
||||
scopes: scopes.split(" "),
|
||||
account,
|
||||
idToken: response.token.id_token,
|
||||
idTokenClaims,
|
||||
accessToken: response.token.access_token,
|
||||
fromCache: false,
|
||||
expiresOn: expiresOn,
|
||||
tokenType:
|
||||
request.authenticationScheme ||
|
||||
Constants.AuthenticationScheme.BEARER,
|
||||
correlationId: request.correlationId,
|
||||
extExpiresOn: expiresOn,
|
||||
state: request.state,
|
||||
};
|
||||
|
||||
return authenticationResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* export type AccountInfo = {
|
||||
* homeAccountId: string;
|
||||
* environment: string;
|
||||
* tenantId: string;
|
||||
* username: string;
|
||||
* localAccountId: string;
|
||||
* name?: string;
|
||||
* idToken?: string;
|
||||
* idTokenClaims?: TokenClaims & {
|
||||
* [key: string]:
|
||||
* | string
|
||||
* | number
|
||||
* | string[]
|
||||
* | object
|
||||
* | undefined
|
||||
* | unknown;
|
||||
* };
|
||||
* nativeAccountId?: string;
|
||||
* authorityType?: string;
|
||||
* };
|
||||
*/
|
||||
public fromNaaAccountInfo(
|
||||
fromAccount: NaaAccountInfo,
|
||||
idToken?: string,
|
||||
idTokenClaims?: TokenClaims
|
||||
): MsalAccountInfo {
|
||||
const effectiveIdTokenClaims =
|
||||
idTokenClaims || (fromAccount.idTokenClaims as TokenClaims);
|
||||
|
||||
const localAccountId =
|
||||
fromAccount.localAccountId ||
|
||||
effectiveIdTokenClaims?.oid ||
|
||||
effectiveIdTokenClaims?.sub ||
|
||||
"";
|
||||
|
||||
/*
|
||||
* In B2C scenarios tid may not be present, use getTenantIdFromIdTokenClaims
|
||||
* which handles tid, tfp (modern B2C), and acr (legacy B2C) claims
|
||||
*/
|
||||
const tenantId =
|
||||
fromAccount.tenantId ||
|
||||
getTenantIdFromIdTokenClaims(effectiveIdTokenClaims) ||
|
||||
"";
|
||||
|
||||
const homeAccountId =
|
||||
fromAccount.homeAccountId || `${localAccountId}.${tenantId}`;
|
||||
|
||||
// Validate environment - required field
|
||||
const environment = fromAccount.environment;
|
||||
if (!environment) {
|
||||
throw createClientAuthError(
|
||||
ClientAuthErrorCodes.invalidCacheEnvironment
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* In B2C scenarios the emails claim is used instead of preferred_username and it is an array.
|
||||
* In most cases it will contain a single email. This field should not be relied upon if a custom
|
||||
* policy is configured to return more than 1 email.
|
||||
*/
|
||||
const preferredUsername =
|
||||
effectiveIdTokenClaims?.preferred_username ||
|
||||
effectiveIdTokenClaims?.upn;
|
||||
|
||||
const email = effectiveIdTokenClaims?.emails?.[0] || null;
|
||||
|
||||
const username =
|
||||
fromAccount.username || preferredUsername || email || "";
|
||||
|
||||
const name = fromAccount.name || effectiveIdTokenClaims?.name || "";
|
||||
|
||||
const loginHint =
|
||||
fromAccount.loginHint || effectiveIdTokenClaims?.login_hint;
|
||||
|
||||
const tenantProfiles = new Map<string, TenantProfile>();
|
||||
|
||||
const tenantProfile = buildTenantProfile(
|
||||
homeAccountId,
|
||||
localAccountId,
|
||||
tenantId,
|
||||
effectiveIdTokenClaims
|
||||
);
|
||||
tenantProfiles.set(tenantId, tenantProfile);
|
||||
|
||||
const account: MsalAccountInfo = {
|
||||
homeAccountId,
|
||||
environment,
|
||||
tenantId,
|
||||
username,
|
||||
localAccountId,
|
||||
name,
|
||||
loginHint,
|
||||
idToken: idToken,
|
||||
idTokenClaims: effectiveIdTokenClaims,
|
||||
tenantProfiles,
|
||||
};
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param error BridgeError
|
||||
* @returns AuthError, ClientAuthError, ClientConfigurationError, ServerError, InteractionRequiredError
|
||||
*/
|
||||
public fromBridgeError(
|
||||
error: unknown
|
||||
):
|
||||
| AuthError
|
||||
| ClientAuthError
|
||||
| ClientConfigurationError
|
||||
| ServerError
|
||||
| InteractionRequiredAuthError {
|
||||
if (isBridgeError(error)) {
|
||||
switch (error.status) {
|
||||
case BridgeStatusCode.UserCancel:
|
||||
return new ClientAuthError(
|
||||
ClientAuthErrorCodes.userCanceled
|
||||
);
|
||||
case BridgeStatusCode.NoNetwork:
|
||||
return new ClientAuthError(
|
||||
ClientAuthErrorCodes.noNetworkConnectivity
|
||||
);
|
||||
case BridgeStatusCode.AccountUnavailable:
|
||||
return new ClientAuthError(
|
||||
ClientAuthErrorCodes.noAccountFound
|
||||
);
|
||||
case BridgeStatusCode.Disabled:
|
||||
return new ClientAuthError(
|
||||
ClientAuthErrorCodes.nestedAppAuthBridgeDisabled
|
||||
);
|
||||
case BridgeStatusCode.NestedAppAuthUnavailable:
|
||||
return new ClientAuthError(
|
||||
error.code ||
|
||||
ClientAuthErrorCodes.nestedAppAuthBridgeDisabled,
|
||||
error.description
|
||||
);
|
||||
case BridgeStatusCode.TransientError:
|
||||
case BridgeStatusCode.PersistentError:
|
||||
return new ServerError(error.code, error.description);
|
||||
case BridgeStatusCode.UserInteractionRequired:
|
||||
return new InteractionRequiredAuthError(
|
||||
error.code,
|
||||
error.description
|
||||
);
|
||||
default:
|
||||
return new AuthError(error.code, error.description);
|
||||
}
|
||||
} else {
|
||||
return new AuthError("unknown_error", "An unknown error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an AuthenticationResult from the given cache items
|
||||
*
|
||||
* @param account
|
||||
* @param idToken
|
||||
* @param accessToken
|
||||
* @param reqTimestamp
|
||||
* @returns
|
||||
*/
|
||||
public toAuthenticationResultFromCache(
|
||||
account: AccountInfo,
|
||||
idToken: IdTokenEntity,
|
||||
accessToken: AccessTokenEntity,
|
||||
request: SilentRequest,
|
||||
correlationId: string
|
||||
): AuthenticationResult {
|
||||
if (!idToken || !accessToken) {
|
||||
throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken);
|
||||
}
|
||||
|
||||
const idTokenClaims = AuthToken.extractTokenClaims(
|
||||
idToken.secret,
|
||||
this.crypto.base64Decode
|
||||
);
|
||||
|
||||
const scopes = accessToken.target || request.scopes.join(" ");
|
||||
|
||||
const authenticationResult: AuthenticationResult = {
|
||||
authority: accessToken.environment || account.environment,
|
||||
uniqueId: account.localAccountId,
|
||||
tenantId: account.tenantId,
|
||||
scopes: scopes.split(" "),
|
||||
account,
|
||||
idToken: idToken.secret,
|
||||
idTokenClaims: idTokenClaims || {},
|
||||
accessToken: accessToken.secret,
|
||||
fromCache: true,
|
||||
expiresOn: TimeUtils.toDateFromSeconds(accessToken.expiresOn),
|
||||
extExpiresOn: TimeUtils.toDateFromSeconds(
|
||||
accessToken.extendedExpiresOn
|
||||
),
|
||||
tokenType:
|
||||
request.authenticationScheme ||
|
||||
Constants.AuthenticationScheme.BEARER,
|
||||
correlationId,
|
||||
state: request.state,
|
||||
};
|
||||
|
||||
return authenticationResult;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user