{"version":3,"file":"msal-node.cjs.production.min.js","sources":["../src/utils/Constants.ts","../src/utils/NetworkUtils.ts","../src/network/HttpClient.ts","../src/config/Configuration.ts","../src/crypto/GuidGenerator.ts","../src/utils/EncodingUtils.ts","../src/crypto/HashUtils.ts","../src/crypto/PkceGenerator.ts","../src/crypto/CryptoProvider.ts","../src/cache/serializer/Deserializer.ts","../src/cache/serializer/Serializer.ts","../src/cache/NodeStorage.ts","../src/cache/TokenCache.ts","../src/error/NodeAuthError.ts","../src/client/ClientApplication.ts","../src/packageMetadata.ts","../src/network/LoopbackClient.ts","../src/client/ClientAssertion.ts","../src/client/ConfidentialClientApplication.ts","../src/cache/distributed/DistributedCachePlugin.ts","../src/client/PublicClientApplication.ts"],"sourcesContent":["/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * http methods\r\n */\r\nexport enum HttpMethod {\r\n GET = \"get\",\r\n POST = \"post\",\r\n}\r\n\r\nexport enum HttpStatus {\r\n SUCCESS_RANGE_START = 200,\r\n SUCCESS_RANGE_END = 299,\r\n REDIRECT = 302,\r\n CLIENT_ERROR_RANGE_START = 400,\r\n CLIENT_ERROR_RANGE_END = 499,\r\n SERVER_ERROR_RANGE_START = 500,\r\n SERVER_ERROR_RANGE_END = 599\r\n}\r\n\r\nexport enum ProxyStatus {\r\n SUCCESS_RANGE_START = 200,\r\n SUCCESS_RANGE_END = 299,\r\n SERVER_ERROR = 500\r\n}\r\n\r\n/**\r\n * Constants used for region discovery\r\n */\r\nexport const REGION_ENVIRONMENT_VARIABLE = \"REGION_NAME\";\r\n\r\n/**\r\n * Constant used for PKCE\r\n */\r\nexport const RANDOM_OCTET_SIZE = 32;\r\n\r\n/**\r\n * Constants used in PKCE\r\n */\r\nexport const Hash = {\r\n SHA256: \"sha256\",\r\n};\r\n\r\n/**\r\n * Constants for encoding schemes\r\n */\r\nexport const CharSet = {\r\n CV_CHARSET:\r\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~\",\r\n};\r\n\r\n/**\r\n * Cache Constants\r\n */\r\nexport const CACHE = {\r\n FILE_CACHE: \"fileCache\",\r\n EXTENSION_LIB: \"extenstion_library\",\r\n};\r\n\r\n/**\r\n * Constants\r\n */\r\nexport const Constants = {\r\n MSAL_SKU: \"msal.js.node\",\r\n JWT_BEARER_ASSERTION_TYPE: \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\",\r\n AUTHORIZATION_PENDING: \"authorization_pending\",\r\n HTTP_PROTOCOL: \"http://\",\r\n LOCALHOST: \"localhost\"\r\n};\r\n\r\n/**\r\n * API Codes for Telemetry purposes.\r\n * Before adding a new code you must claim it in the MSAL Telemetry tracker as these number spaces are shared across all MSALs\r\n * 0-99 Silent Flow\r\n * 600-699 Device Code Flow\r\n * 800-899 Auth Code Flow\r\n */\r\nexport enum ApiId {\r\n acquireTokenSilent = 62,\r\n acquireTokenByUsernamePassword = 371,\r\n acquireTokenByDeviceCode = 671,\r\n acquireTokenByClientCredential = 771,\r\n acquireTokenByCode = 871,\r\n acquireTokenByRefreshToken = 872\r\n}\r\n\r\n/**\r\n * JWT constants\r\n */\r\nexport const JwtConstants = {\r\n ALGORITHM: \"alg\",\r\n RSA_256: \"RS256\",\r\n X5T: \"x5t\", \r\n X5C: \"x5c\",\r\n AUDIENCE: \"aud\",\r\n EXPIRATION_TIME: \"exp\",\r\n ISSUER: \"iss\",\r\n SUBJECT: \"sub\",\r\n NOT_BEFORE: \"nbf\",\r\n JWT_ID: \"jti\",\r\n};\r\n\r\nexport const LOOPBACK_SERVER_CONSTANTS = {\r\n INTERVAL_MS: 100,\r\n TIMEOUT_MS: 5000\r\n};\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { NetworkResponse, UrlToHttpRequestOptions } from \"@azure/msal-common\";\r\n\r\nexport class NetworkUtils {\r\n static getNetworkResponse(headers: Record, body: T, statusCode: number): NetworkResponse {\r\n return {\r\n headers: headers,\r\n body: body,\r\n status: statusCode,\r\n };\r\n }\r\n\r\n /*\r\n * Utility function that converts a URL object into an ordinary options object as expected by the\r\n * http.request and https.request APIs.\r\n * https://github.com/nodejs/node/blob/main/lib/internal/url.js#L1090\r\n */\r\n static urlToHttpOptions(url: URL): UrlToHttpRequestOptions {\r\n const options: UrlToHttpRequestOptions = {\r\n protocol: url.protocol,\r\n hostname: url.hostname && url.hostname.startsWith(\"[\") ?\r\n url.hostname.slice(1, -1) :\r\n url.hostname,\r\n hash: url.hash,\r\n search: url.search,\r\n pathname: url.pathname,\r\n path: `${url.pathname || \"\"}${url.search || \"\"}`,\r\n href: url.href,\r\n };\r\n if (url.port !== \"\") {\r\n options.port = Number(url.port);\r\n }\r\n if (url.username || url.password) {\r\n options.auth = `${decodeURIComponent(url.username)}:${decodeURIComponent(url.password)}`;\r\n }\r\n return options;\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { INetworkModule, NetworkRequestOptions, NetworkResponse } from \"@azure/msal-common\";\r\nimport { HttpMethod, Constants, HttpStatus, ProxyStatus } from \"../utils/Constants\";\r\nimport { NetworkUtils } from \"../utils/NetworkUtils\";\r\nimport http from \"http\";\r\nimport https from \"https\";\r\n\r\n/**\r\n * This class implements the API for network requests.\r\n */\r\nexport class HttpClient implements INetworkModule {\r\n private proxyUrl: string;\r\n private customAgentOptions: http.AgentOptions | https.AgentOptions;\r\n\r\n constructor(\r\n proxyUrl?: string,\r\n customAgentOptions?: http.AgentOptions | https.AgentOptions,\r\n ) {\r\n this.proxyUrl = proxyUrl || \"\";\r\n this.customAgentOptions = customAgentOptions || {};\r\n }\r\n\r\n /**\r\n * Http Get request\r\n * @param url\r\n * @param options\r\n */\r\n async sendGetRequestAsync(\r\n url: string,\r\n options?: NetworkRequestOptions,\r\n ): Promise> {\r\n if (this.proxyUrl) {\r\n return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.GET, options, this.customAgentOptions as http.AgentOptions);\r\n } else {\r\n return networkRequestViaHttps(url, HttpMethod.GET, options, this.customAgentOptions as https.AgentOptions);\r\n }\r\n }\r\n\r\n /**\r\n * Http Post request\r\n * @param url\r\n * @param options\r\n */\r\n async sendPostRequestAsync(\r\n url: string,\r\n options?: NetworkRequestOptions,\r\n cancellationToken?: number,\r\n ): Promise> {\r\n if (this.proxyUrl) {\r\n return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.POST, options, this.customAgentOptions as http.AgentOptions, cancellationToken);\r\n } else {\r\n return networkRequestViaHttps(url, HttpMethod.POST, options, this.customAgentOptions as https.AgentOptions, cancellationToken);\r\n }\r\n }\r\n}\r\n\r\nconst networkRequestViaProxy = (\r\n destinationUrlString: string,\r\n proxyUrlString: string,\r\n httpMethod: string,\r\n options?: NetworkRequestOptions,\r\n agentOptions?: http.AgentOptions,\r\n timeout?: number,\r\n): Promise> => {\r\n const destinationUrl = new URL(destinationUrlString);\r\n const proxyUrl = new URL(proxyUrlString);\r\n\r\n // \"method: connect\" must be used to establish a connection to the proxy\r\n const headers = options?.headers || {} as Record;\r\n const tunnelRequestOptions: https.RequestOptions = {\r\n host: proxyUrl.hostname,\r\n port: proxyUrl.port,\r\n method: \"CONNECT\",\r\n path: destinationUrl.hostname,\r\n headers: headers,\r\n };\r\n\r\n if (timeout) {\r\n tunnelRequestOptions.timeout = timeout;\r\n }\r\n\r\n if (agentOptions && Object.keys(agentOptions).length) {\r\n tunnelRequestOptions.agent = new http.Agent(agentOptions);\r\n }\r\n\r\n // compose a request string for the socket\r\n let postRequestStringContent: string = \"\";\r\n if (httpMethod === HttpMethod.POST) {\r\n const body = options?.body || \"\";\r\n postRequestStringContent =\r\n \"Content-Type: application/x-www-form-urlencoded\\r\\n\" +\r\n `Content-Length: ${body.length}\\r\\n` +\r\n `\\r\\n${body}`;\r\n }\r\n const outgoingRequestString = `${httpMethod.toUpperCase()} ${destinationUrl.href} HTTP/1.1\\r\\n` +\r\n `Host: ${destinationUrl.host}\\r\\n` +\r\n \"Connection: close\\r\\n\" +\r\n postRequestStringContent +\r\n \"\\r\\n\";\r\n\r\n return new Promise>(((resolve, reject) => {\r\n const request = http.request(tunnelRequestOptions);\r\n\r\n if (tunnelRequestOptions.timeout) {\r\n request.on(\"timeout\", () => {\r\n request.destroy();\r\n reject(new Error(\"Request time out\"));\r\n });\r\n }\r\n\r\n request.end();\r\n\r\n // establish connection to the proxy\r\n request.on(\"connect\", (response, socket) => {\r\n const proxyStatusCode = response?.statusCode || ProxyStatus.SERVER_ERROR;\r\n if ((proxyStatusCode < ProxyStatus.SUCCESS_RANGE_START) || (proxyStatusCode > ProxyStatus.SUCCESS_RANGE_END)) {\r\n request.destroy();\r\n socket.destroy();\r\n reject(new Error(`Error connecting to proxy. Http status code: ${response.statusCode}. Http status message: ${response?.statusMessage || \"Unknown\"}`));\r\n }\r\n if (tunnelRequestOptions.timeout) {\r\n socket.setTimeout(tunnelRequestOptions.timeout);\r\n socket.on(\"timeout\", () => {\r\n request.destroy();\r\n socket.destroy();\r\n reject(new Error(\"Request time out\"));\r\n });\r\n }\r\n\r\n // make a request over an HTTP tunnel\r\n socket.write(outgoingRequestString);\r\n\r\n const data: Buffer[] = [];\r\n socket.on(\"data\", (chunk) => {\r\n data.push(chunk);\r\n });\r\n\r\n socket.on(\"end\", () => {\r\n // combine all received buffer streams into one buffer, and then into a string\r\n const dataString = Buffer.concat([...data]).toString();\r\n\r\n // separate each line into it's own entry in an arry\r\n const dataStringArray = dataString.split(\"\\r\\n\");\r\n // the first entry will contain the statusCode and statusMessage\r\n const httpStatusCode = parseInt(dataStringArray[0].split(\" \")[1]);\r\n // remove \"HTTP/1.1\" and the status code to get the status message\r\n const statusMessage = dataStringArray[0].split(\" \").slice(2).join(\" \");\r\n // the last entry will contain the body\r\n const body = dataStringArray[dataStringArray.length - 1];\r\n\r\n // everything in between the first and last entries are the headers\r\n const headersArray = dataStringArray.slice(1, dataStringArray.length - 2);\r\n\r\n // build an object out of all the headers\r\n const entries = new Map();\r\n headersArray.forEach((header) => {\r\n /**\r\n * the header might look like \"Content-Length: 1531\", but that is just a string\r\n * it needs to be converted to a key/value pair\r\n * split the string at the first instance of \":\"\r\n * there may be more than one \":\" if the value of the header is supposed to be a JSON object\r\n */\r\n const headerKeyValue = header.split(new RegExp(/:\\s(.*)/s));\r\n const headerKey = headerKeyValue[0];\r\n let headerValue = headerKeyValue[1];\r\n\r\n // check if the value of the header is supposed to be a JSON object\r\n try {\r\n const object = JSON.parse(headerValue);\r\n\r\n // if it is, then convert it from a string to a JSON object\r\n if (object && (typeof object === \"object\")) {\r\n headerValue = object;\r\n }\r\n } catch (e) {\r\n // otherwise, leave it as a string\r\n }\r\n\r\n entries.set(headerKey, headerValue);\r\n });\r\n const headers = Object.fromEntries(entries);\r\n\r\n const parsedHeaders = headers as Record;\r\n const networkResponse = NetworkUtils.getNetworkResponse(\r\n parsedHeaders,\r\n parseBody(httpStatusCode, statusMessage, parsedHeaders, body) as T,\r\n httpStatusCode\r\n );\r\n\r\n if (((httpStatusCode < HttpStatus.SUCCESS_RANGE_START) || (httpStatusCode > HttpStatus.SUCCESS_RANGE_END)) &&\r\n // do not destroy the request for the device code flow\r\n networkResponse.body[\"error\"] !== Constants.AUTHORIZATION_PENDING) {\r\n request.destroy();\r\n }\r\n resolve(networkResponse);\r\n });\r\n\r\n socket.on(\"error\", (chunk) => {\r\n request.destroy();\r\n socket.destroy();\r\n reject(new Error(chunk.toString()));\r\n });\r\n });\r\n\r\n request.on(\"error\", (chunk) => {\r\n request.destroy();\r\n reject(new Error(chunk.toString()));\r\n });\r\n }));\r\n};\r\n\r\nconst networkRequestViaHttps = (\r\n urlString: string,\r\n httpMethod: string,\r\n options?: NetworkRequestOptions,\r\n agentOptions?: https.AgentOptions,\r\n timeout?: number,\r\n): Promise> => {\r\n const isPostRequest = httpMethod === HttpMethod.POST;\r\n const body: string = options?.body || \"\";\r\n\r\n const url = new URL(urlString);\r\n const headers = options?.headers || {} as Record;\r\n const customOptions: https.RequestOptions = {\r\n method: httpMethod,\r\n headers: headers,\r\n ...NetworkUtils.urlToHttpOptions(url),\r\n };\r\n\r\n if (timeout) {\r\n customOptions.timeout = timeout;\r\n }\r\n\r\n if (agentOptions && Object.keys(agentOptions).length) {\r\n customOptions.agent = new https.Agent(agentOptions);\r\n }\r\n\r\n if (isPostRequest) {\r\n // needed for post request to work\r\n customOptions.headers = {\r\n ...customOptions.headers,\r\n \"Content-Length\": body.length,\r\n };\r\n }\r\n\r\n return new Promise>((resolve, reject) => {\r\n const request = https.request(customOptions);\r\n\r\n if (timeout) {\r\n request.on(\"timeout\", () => {\r\n request.destroy();\r\n reject(new Error(\"Request time out\"));\r\n });\r\n }\r\n\r\n if (isPostRequest) {\r\n request.write(body);\r\n }\r\n\r\n request.end();\r\n\r\n request.on(\"response\", (response) => {\r\n const headers = response.headers;\r\n const statusCode = response.statusCode as number;\r\n const statusMessage = response.statusMessage;\r\n\r\n const data: Buffer[] = [];\r\n response.on(\"data\", (chunk) => {\r\n data.push(chunk);\r\n });\r\n\r\n response.on(\"end\", () => {\r\n // combine all received buffer streams into one buffer, and then into a string\r\n const body = Buffer.concat([...data]).toString();\r\n\r\n const parsedHeaders = headers as Record;\r\n const networkResponse = NetworkUtils.getNetworkResponse(\r\n parsedHeaders,\r\n parseBody(statusCode, statusMessage, parsedHeaders, body) as T,\r\n statusCode\r\n );\r\n\r\n if (((statusCode < HttpStatus.SUCCESS_RANGE_START) || (statusCode > HttpStatus.SUCCESS_RANGE_END)) &&\r\n // do not destroy the request for the device code flow\r\n networkResponse.body[\"error\"] !== Constants.AUTHORIZATION_PENDING) {\r\n request.destroy();\r\n }\r\n resolve(networkResponse);\r\n });\r\n });\r\n\r\n request.on(\"error\", (chunk) => {\r\n request.destroy();\r\n reject(new Error(chunk.toString()));\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Check if extra parsing is needed on the repsonse from the server\r\n * @param statusCode {number} the status code of the response from the server\r\n * @param statusMessage {string | undefined} the status message of the response from the server\r\n * @param headers {Record} the headers of the response from the server\r\n * @param body {string} the body from the response of the server\r\n * @returns {Object} JSON parsed body or error object\r\n */\r\nconst parseBody = (statusCode: number, statusMessage: string | undefined, headers: Record, body: string) => {\r\n /*\r\n * Informational responses (100 – 199)\r\n * Successful responses (200 – 299)\r\n * Redirection messages (300 – 399)\r\n * Client error responses (400 – 499)\r\n * Server error responses (500 – 599)\r\n */\r\n \r\n let parsedBody;\r\n try {\r\n parsedBody = JSON.parse(body);\r\n } catch (error) {\r\n let errorType;\r\n let errorDescriptionHelper;\r\n if ((statusCode >= HttpStatus.CLIENT_ERROR_RANGE_START) && (statusCode <= HttpStatus.CLIENT_ERROR_RANGE_END)) {\r\n errorType = \"client_error\";\r\n errorDescriptionHelper = \"A client\";\r\n } else if ((statusCode >= HttpStatus.SERVER_ERROR_RANGE_START) && (statusCode <= HttpStatus.SERVER_ERROR_RANGE_END)) {\r\n errorType = \"server_error\";\r\n errorDescriptionHelper = \"A server\";\r\n } else {\r\n errorType = \"unknown_error\";\r\n errorDescriptionHelper = \"An unknown\";\r\n }\r\n\r\n parsedBody = {\r\n error: errorType,\r\n error_description: `${errorDescriptionHelper} error occured.\\nHttp status code: ${statusCode}\\nHttp status message: ${statusMessage || \"Unknown\"}\\nHeaders: ${JSON.stringify(headers)}`\r\n };\r\n }\r\n\r\n return parsedBody;\r\n};\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n LoggerOptions,\r\n INetworkModule,\r\n LogLevel,\r\n ProtocolMode,\r\n ICachePlugin,\r\n Constants,\r\n AzureCloudInstance,\r\n AzureCloudOptions,\r\n ApplicationTelemetry,\r\n INativeBrokerPlugin\r\n} from \"@azure/msal-common\";\r\nimport { HttpClient } from \"../network/HttpClient\";\r\nimport { AgentOptions as httpAgentOptions } from \"http\";\r\nimport { AgentOptions as httpsAgentOptions } from \"https\";\r\n\r\n/**\r\n * - clientId - Client id of the application.\r\n * - authority - Url of the authority. If no value is set, defaults to https://login.microsoftonline.com/common.\r\n * - knownAuthorities - Needed for Azure B2C and ADFS. All authorities that will be used in the client application. Only the host of the authority should be passed in.\r\n * - clientSecret - Secret string that the application uses when requesting a token. Only used in confidential client applications. Can be created in the Azure app registration portal.\r\n * - clientAssertion - Assertion string that the application uses when requesting a token. Only used in confidential client applications. Assertion should be of type urn:ietf:params:oauth:client-assertion-type:jwt-bearer.\r\n * - clientCertificate - Certificate that the application uses when requesting a token. Only used in confidential client applications. Requires hex encoded X.509 SHA-1 thumbprint of the certificiate, and the PEM encoded private key (string should contain -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY----- )\r\n * - protocolMode - Enum that represents the protocol that msal follows. Used for configuring proper endpoints.\r\n * - skipAuthorityMetadataCache - A flag to choose whether to use or not use the local metadata cache during authority initialization. Defaults to false.\r\n * @public\r\n */\r\nexport type NodeAuthOptions = {\r\n clientId: string;\r\n authority?: string;\r\n clientSecret?: string;\r\n clientAssertion?: string;\r\n clientCertificate?: {\r\n thumbprint: string,\r\n privateKey: string,\r\n x5c?: string\r\n };\r\n knownAuthorities?: Array;\r\n cloudDiscoveryMetadata?: string;\r\n authorityMetadata?: string;\r\n clientCapabilities?: Array;\r\n protocolMode?: ProtocolMode;\r\n azureCloudOptions?: AzureCloudOptions;\r\n skipAuthorityMetadataCache?: boolean;\r\n};\r\n\r\n/**\r\n * Use this to configure the below cache configuration options:\r\n *\r\n * - cachePlugin - Plugin for reading and writing token cache to disk.\r\n * - claimsBasedCachingEnabled - Flag to enable/disable claims based caching. Set to true by default.\r\n * @public\r\n */\r\nexport type CacheOptions = {\r\n cachePlugin?: ICachePlugin;\r\n claimsBasedCachingEnabled?: boolean;\r\n};\r\n\r\n/**\r\n * Use this to configure the below broker options:\r\n * - nativeBrokerPlugin - Native broker implementation (should be imported from msal-node-extensions)\r\n * \r\n * Note: These options are only available for PublicClientApplications using the Authorization Code Flow\r\n * @public\r\n */\r\nexport type BrokerOptions = {\r\n nativeBrokerPlugin?: INativeBrokerPlugin;\r\n};\r\n\r\n/**\r\n * Type for configuring logger and http client options\r\n *\r\n * - logger - Used to initialize the Logger object; TODO: Expand on logger details or link to the documentation on logger\r\n * - networkClient - Http client used for all http get and post calls. Defaults to using MSAL's default http client.\r\n * @public\r\n */\r\nexport type NodeSystemOptions = {\r\n loggerOptions?: LoggerOptions;\r\n networkClient?: INetworkModule;\r\n proxyUrl?: string;\r\n customAgentOptions?: httpAgentOptions | httpsAgentOptions;\r\n};\r\n\r\nexport type NodeTelemetryOptions = {\r\n application?: ApplicationTelemetry;\r\n};\r\n\r\n/**\r\n * Use the configuration object to configure MSAL and initialize the client application object\r\n *\r\n * - auth: this is where you configure auth elements like clientID, authority used for authenticating against the Microsoft Identity Platform\r\n * - broker: this is where you configure broker options\r\n * - cache: this is where you configure cache location\r\n * - system: this is where you can configure the network client, logger\r\n * - telemetry: this is where you can configure telemetry options\r\n * @public\r\n */\r\nexport type Configuration = {\r\n auth: NodeAuthOptions;\r\n broker?: BrokerOptions;\r\n cache?: CacheOptions;\r\n system?: NodeSystemOptions;\r\n telemetry?: NodeTelemetryOptions;\r\n};\r\n\r\nconst DEFAULT_AUTH_OPTIONS: Required = {\r\n clientId: Constants.EMPTY_STRING,\r\n authority: Constants.DEFAULT_AUTHORITY,\r\n clientSecret: Constants.EMPTY_STRING,\r\n clientAssertion: Constants.EMPTY_STRING,\r\n clientCertificate: {\r\n thumbprint: Constants.EMPTY_STRING,\r\n privateKey: Constants.EMPTY_STRING,\r\n x5c: Constants.EMPTY_STRING\r\n },\r\n knownAuthorities: [],\r\n cloudDiscoveryMetadata: Constants.EMPTY_STRING,\r\n authorityMetadata: Constants.EMPTY_STRING,\r\n clientCapabilities: [],\r\n protocolMode: ProtocolMode.AAD,\r\n azureCloudOptions: {\r\n azureCloudInstance: AzureCloudInstance.None,\r\n tenant: Constants.EMPTY_STRING\r\n },\r\n skipAuthorityMetadataCache: false,\r\n};\r\n\r\nconst DEFAULT_CACHE_OPTIONS: CacheOptions = {\r\n claimsBasedCachingEnabled: true\r\n};\r\n\r\nconst DEFAULT_LOGGER_OPTIONS: LoggerOptions = {\r\n loggerCallback: (): void => {\r\n // allow users to not set logger call back \r\n },\r\n piiLoggingEnabled: false,\r\n logLevel: LogLevel.Info,\r\n};\r\n\r\nconst DEFAULT_SYSTEM_OPTIONS: Required = {\r\n loggerOptions: DEFAULT_LOGGER_OPTIONS,\r\n networkClient: new HttpClient(),\r\n proxyUrl: Constants.EMPTY_STRING,\r\n customAgentOptions: {} as httpAgentOptions | httpsAgentOptions,\r\n};\r\n\r\nconst DEFAULT_TELEMETRY_OPTIONS: Required = {\r\n application: {\r\n appName: Constants.EMPTY_STRING,\r\n appVersion: Constants.EMPTY_STRING\r\n }\r\n};\r\n\r\nexport type NodeConfiguration = {\r\n auth: Required;\r\n broker: BrokerOptions;\r\n cache: CacheOptions;\r\n system: Required;\r\n telemetry: Required;\r\n};\r\n\r\n/**\r\n * Sets the default options when not explicitly configured from app developer\r\n *\r\n * @param auth - Authentication options\r\n * @param cache - Cache options\r\n * @param system - System options\r\n * @param telemetry - Telemetry options\r\n *\r\n * @returns Configuration\r\n * @public\r\n */\r\nexport function buildAppConfiguration({\r\n auth,\r\n broker,\r\n cache,\r\n system,\r\n telemetry\r\n}: Configuration): NodeConfiguration {\r\n const systemOptions: Required = {\r\n ...DEFAULT_SYSTEM_OPTIONS,\r\n networkClient: new HttpClient(system?.proxyUrl, (system?.customAgentOptions as httpAgentOptions | httpsAgentOptions)),\r\n loggerOptions: system?.loggerOptions || DEFAULT_LOGGER_OPTIONS,\r\n };\r\n\r\n return {\r\n auth: { ...DEFAULT_AUTH_OPTIONS, ...auth },\r\n broker: { ...broker},\r\n cache: { ...DEFAULT_CACHE_OPTIONS, ...cache },\r\n system: { ...systemOptions, ...system },\r\n telemetry: { ...DEFAULT_TELEMETRY_OPTIONS, ...telemetry }\r\n };\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { IGuidGenerator } from \"@azure/msal-common\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\n\r\nexport class GuidGenerator implements IGuidGenerator {\r\n /**\r\n *\r\n * RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or pseudo-random numbers.\r\n * uuidv4 generates guids from cryprtographically-string random\r\n */\r\n generateGuid(): string {\r\n return uuidv4();\r\n }\r\n\r\n /**\r\n * verifies if a string is GUID\r\n * @param guid\r\n */\r\n isGuid(guid: string): boolean {\r\n const regexGuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\r\n return regexGuid.test(guid);\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Constants } from \"@azure/msal-common\";\r\n\r\nexport class EncodingUtils {\r\n /**\r\n * 'utf8': Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8.\r\n * 'base64': Base64 encoding.\r\n *\r\n * @param str text\r\n */\r\n static base64Encode(str: string, encoding?: BufferEncoding): string {\r\n return Buffer.from(str, encoding).toString(\"base64\");\r\n }\r\n\r\n /**\r\n * encode a URL\r\n * @param str\r\n */\r\n static base64EncodeUrl(str: string, encoding?: BufferEncoding): string {\r\n return EncodingUtils.base64Encode(str, encoding)\r\n .replace(/=/g, Constants.EMPTY_STRING)\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\");\r\n }\r\n\r\n /**\r\n * 'utf8': Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8.\r\n * 'base64': Base64 encoding.\r\n *\r\n * @param base64Str Base64 encoded text\r\n */\r\n static base64Decode(base64Str: string): string {\r\n return Buffer.from(base64Str, \"base64\").toString(\"utf8\");\r\n }\r\n\r\n /**\r\n * @param base64Str Base64 encoded Url\r\n */\r\n static base64DecodeUrl(base64Str: string): string {\r\n let str = base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\");\r\n while (str.length % 4) {\r\n str += \"=\";\r\n }\r\n return EncodingUtils.base64Decode(str);\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Hash } from \"../utils/Constants\";\r\nimport crypto from \"crypto\";\r\n\r\nexport class HashUtils {\r\n /**\r\n * generate 'SHA256' hash\r\n * @param buffer\r\n */\r\n sha256(buffer: string): Buffer {\r\n return crypto\r\n .createHash(Hash.SHA256)\r\n .update(buffer)\r\n .digest();\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Constants, PkceCodes } from \"@azure/msal-common\";\r\nimport { CharSet, RANDOM_OCTET_SIZE } from \"../utils/Constants\";\r\nimport { EncodingUtils } from \"../utils/EncodingUtils\";\r\nimport { HashUtils } from \"./HashUtils\";\r\nimport crypto from \"crypto\";\r\n\r\n/**\r\n * https://tools.ietf.org/html/rfc7636#page-8\r\n */\r\nexport class PkceGenerator {\r\n private hashUtils: HashUtils;\r\n\r\n constructor() {\r\n this.hashUtils = new HashUtils();\r\n }\r\n /**\r\n * generates the codeVerfier and the challenge from the codeVerfier\r\n * reference: https://tools.ietf.org/html/rfc7636#section-4.1 and https://tools.ietf.org/html/rfc7636#section-4.2\r\n */\r\n async generatePkceCodes(): Promise {\r\n const verifier = this.generateCodeVerifier();\r\n const challenge = this.generateCodeChallengeFromVerifier(verifier);\r\n return { verifier, challenge };\r\n }\r\n\r\n /**\r\n * generates the codeVerfier; reference: https://tools.ietf.org/html/rfc7636#section-4.1\r\n */\r\n private generateCodeVerifier(): string {\r\n const charArr = [];\r\n const maxNumber = 256 - (256 % CharSet.CV_CHARSET.length);\r\n while (charArr.length <= RANDOM_OCTET_SIZE) {\r\n const byte = crypto.randomBytes(1)[0];\r\n if (byte >= maxNumber) {\r\n /* \r\n * Ignore this number to maintain randomness.\r\n * Including it would result in an unequal distribution of characters after doing the modulo\r\n */\r\n continue;\r\n }\r\n const index = byte % CharSet.CV_CHARSET.length;\r\n charArr.push(CharSet.CV_CHARSET[index]);\r\n }\r\n const verifier: string = charArr.join(Constants.EMPTY_STRING);\r\n return EncodingUtils.base64EncodeUrl(verifier);\r\n }\r\n\r\n /**\r\n * generate the challenge from the codeVerfier; reference: https://tools.ietf.org/html/rfc7636#section-4.2\r\n * @param codeVerifier\r\n */\r\n private generateCodeChallengeFromVerifier(codeVerifier: string): string {\r\n return EncodingUtils.base64EncodeUrl(\r\n this.hashUtils.sha256(codeVerifier).toString(\"base64\"), \r\n \"base64\" \r\n );\r\n }\r\n\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ICrypto, PkceCodes } from \"@azure/msal-common\";\r\nimport { GuidGenerator } from \"./GuidGenerator\";\r\nimport { EncodingUtils } from \"../utils/EncodingUtils\";\r\nimport { PkceGenerator } from \"./PkceGenerator\";\r\nimport { HashUtils } from \"./HashUtils\";\r\n\r\n/**\r\n * This class implements MSAL node's crypto interface, which allows it to perform base64 encoding and decoding, generating cryptographically random GUIDs and\r\n * implementing Proof Key for Code Exchange specs for the OAuth Authorization Code Flow using PKCE (rfc here: https://tools.ietf.org/html/rfc7636).\r\n * @public\r\n */\r\nexport class CryptoProvider implements ICrypto {\r\n private pkceGenerator: PkceGenerator;\r\n private guidGenerator: GuidGenerator;\r\n private hashUtils: HashUtils;\r\n\r\n constructor() {\r\n // Browser crypto needs to be validated first before any other classes can be set.\r\n this.pkceGenerator = new PkceGenerator();\r\n this.guidGenerator = new GuidGenerator();\r\n this.hashUtils = new HashUtils();\r\n }\r\n\r\n /**\r\n * Creates a new random GUID - used to populate state and nonce.\r\n * @returns string (GUID)\r\n */\r\n createNewGuid(): string {\r\n return this.guidGenerator.generateGuid();\r\n }\r\n\r\n /**\r\n * Encodes input string to base64.\r\n * @param input - string to be encoded\r\n */\r\n base64Encode(input: string): string {\r\n return EncodingUtils.base64Encode(input);\r\n }\r\n\r\n /**\r\n * Decodes input string from base64.\r\n * @param input - string to be decoded\r\n */\r\n base64Decode(input: string): string {\r\n return EncodingUtils.base64Decode(input);\r\n }\r\n\r\n /**\r\n * Generates PKCE codes used in Authorization Code Flow.\r\n */\r\n generatePkceCodes(): Promise {\r\n return this.pkceGenerator.generatePkceCodes();\r\n }\r\n\r\n /**\r\n * Generates a keypair, stores it and returns a thumbprint - not yet implemented for node\r\n */\r\n getPublicKeyThumbprint(): Promise {\r\n throw new Error(\"Method not implemented.\");\r\n }\r\n\r\n /**\r\n * Removes cryptographic keypair from key store matching the keyId passed in\r\n * @param kid \r\n */\r\n removeTokenBindingKey(): Promise {\r\n throw new Error(\"Method not implemented.\");\r\n }\r\n\r\n /**\r\n * Removes all cryptographic keys from Keystore\r\n */\r\n clearKeystore(): Promise {\r\n throw new Error(\"Method not implemented.\");\r\n }\r\n\r\n /**\r\n * Signs the given object as a jwt payload with private key retrieved by given kid - currently not implemented for node\r\n */\r\n signJwt(): Promise {\r\n throw new Error(\"Method not implemented.\");\r\n }\r\n\r\n /**\r\n * Returns the SHA-256 hash of an input string\r\n */\r\n async hashString(plainText: string): Promise {\r\n return EncodingUtils.base64EncodeUrl(\r\n this.hashUtils.sha256(plainText).toString(\"base64\"), \r\n \"base64\" \r\n );\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { StringUtils, AccountCache, IdTokenCache, AccessTokenCache, RefreshTokenCache, AppMetadataCache, AccountEntity, IdTokenEntity, AccessTokenEntity, RefreshTokenEntity, AppMetadataEntity, CacheManager } from \"@azure/msal-common\";\r\nimport { JsonCache, InMemoryCache, SerializedAccountEntity, SerializedIdTokenEntity, SerializedAccessTokenEntity, SerializedRefreshTokenEntity, SerializedAppMetadataEntity } from \"./SerializerTypes\";\r\n\r\n/**\r\n * This class deserializes cache entities read from the file into in memory object types defined internally\r\n */\r\nexport class Deserializer {\r\n /**\r\n * Parse the JSON blob in memory and deserialize the content\r\n * @param cachedJson\r\n */\r\n static deserializeJSONBlob(jsonFile: string): JsonCache {\r\n const deserializedCache = StringUtils.isEmpty(jsonFile)\r\n ? {}\r\n : JSON.parse(jsonFile);\r\n return deserializedCache;\r\n }\r\n\r\n /**\r\n * Deserializes accounts to AccountEntity objects\r\n * @param accounts\r\n */\r\n static deserializeAccounts(accounts: Record): AccountCache {\r\n const accountObjects: AccountCache = {};\r\n if (accounts) {\r\n Object.keys(accounts).map(function (key) {\r\n const serializedAcc = accounts[key];\r\n const mappedAcc = {\r\n homeAccountId: serializedAcc.home_account_id,\r\n environment: serializedAcc.environment,\r\n realm: serializedAcc.realm,\r\n localAccountId: serializedAcc.local_account_id,\r\n username: serializedAcc.username,\r\n authorityType: serializedAcc.authority_type,\r\n name: serializedAcc.name,\r\n clientInfo: serializedAcc.client_info,\r\n lastModificationTime: serializedAcc.last_modification_time,\r\n lastModificationApp: serializedAcc.last_modification_app,\r\n };\r\n const account: AccountEntity = new AccountEntity();\r\n CacheManager.toObject(account, mappedAcc);\r\n accountObjects[key] = account;\r\n });\r\n }\r\n\r\n return accountObjects;\r\n }\r\n\r\n /**\r\n * Deserializes id tokens to IdTokenEntity objects\r\n * @param idTokens\r\n */\r\n static deserializeIdTokens(idTokens: Record): IdTokenCache {\r\n const idObjects: IdTokenCache = {};\r\n if (idTokens) {\r\n Object.keys(idTokens).map(function (key) {\r\n const serializedIdT = idTokens[key];\r\n const mappedIdT = {\r\n homeAccountId: serializedIdT.home_account_id,\r\n environment: serializedIdT.environment,\r\n credentialType: serializedIdT.credential_type,\r\n clientId: serializedIdT.client_id,\r\n secret: serializedIdT.secret,\r\n realm: serializedIdT.realm,\r\n };\r\n const idToken: IdTokenEntity = new IdTokenEntity();\r\n CacheManager.toObject(idToken, mappedIdT);\r\n idObjects[key] = idToken;\r\n });\r\n }\r\n return idObjects;\r\n }\r\n\r\n /**\r\n * Deserializes access tokens to AccessTokenEntity objects\r\n * @param accessTokens\r\n */\r\n static deserializeAccessTokens(accessTokens: Record): AccessTokenCache {\r\n const atObjects: AccessTokenCache = {};\r\n if (accessTokens) {\r\n Object.keys(accessTokens).map(function (key) {\r\n const serializedAT = accessTokens[key];\r\n const mappedAT = {\r\n homeAccountId: serializedAT.home_account_id,\r\n environment: serializedAT.environment,\r\n credentialType: serializedAT.credential_type,\r\n clientId: serializedAT.client_id,\r\n secret: serializedAT.secret,\r\n realm: serializedAT.realm,\r\n target: serializedAT.target,\r\n cachedAt: serializedAT.cached_at,\r\n expiresOn: serializedAT.expires_on,\r\n extendedExpiresOn: serializedAT.extended_expires_on,\r\n refreshOn: serializedAT.refresh_on,\r\n keyId: serializedAT.key_id,\r\n tokenType: serializedAT.token_type,\r\n requestedClaims: serializedAT.requestedClaims,\r\n requestedClaimsHash: serializedAT.requestedClaimsHash,\r\n userAssertionHash: serializedAT.userAssertionHash,\r\n };\r\n const accessToken: AccessTokenEntity = new AccessTokenEntity();\r\n CacheManager.toObject(accessToken, mappedAT);\r\n atObjects[key] = accessToken;\r\n });\r\n }\r\n\r\n return atObjects;\r\n }\r\n\r\n /**\r\n * Deserializes refresh tokens to RefreshTokenEntity objects\r\n * @param refreshTokens\r\n */\r\n static deserializeRefreshTokens(refreshTokens: Record): RefreshTokenCache {\r\n const rtObjects: RefreshTokenCache = {};\r\n if (refreshTokens) {\r\n Object.keys(refreshTokens).map(function (key) {\r\n const serializedRT = refreshTokens[key];\r\n const mappedRT = {\r\n homeAccountId: serializedRT.home_account_id,\r\n environment: serializedRT.environment,\r\n credentialType: serializedRT.credential_type,\r\n clientId: serializedRT.client_id,\r\n secret: serializedRT.secret,\r\n familyId: serializedRT.family_id,\r\n target: serializedRT.target,\r\n realm: serializedRT.realm,\r\n };\r\n const refreshToken: RefreshTokenEntity = new RefreshTokenEntity();\r\n CacheManager.toObject(refreshToken, mappedRT);\r\n rtObjects[key] = refreshToken;\r\n });\r\n }\r\n\r\n return rtObjects;\r\n }\r\n\r\n /**\r\n * Deserializes appMetadata to AppMetaData objects\r\n * @param appMetadata\r\n */\r\n static deserializeAppMetadata(appMetadata: Record): AppMetadataCache {\r\n const appMetadataObjects: AppMetadataCache = {};\r\n if (appMetadata) {\r\n Object.keys(appMetadata).map(function (key) {\r\n const serializedAmdt = appMetadata[key];\r\n const mappedAmd = {\r\n clientId: serializedAmdt.client_id,\r\n environment: serializedAmdt.environment,\r\n familyId: serializedAmdt.family_id,\r\n };\r\n const amd: AppMetadataEntity = new AppMetadataEntity();\r\n CacheManager.toObject(amd, mappedAmd);\r\n appMetadataObjects[key] = amd;\r\n });\r\n }\r\n\r\n return appMetadataObjects;\r\n }\r\n\r\n /**\r\n * Deserialize an inMemory Cache\r\n * @param jsonCache\r\n */\r\n static deserializeAllCache(jsonCache: JsonCache): InMemoryCache {\r\n return {\r\n accounts: jsonCache.Account\r\n ? this.deserializeAccounts(jsonCache.Account)\r\n : {},\r\n idTokens: jsonCache.IdToken\r\n ? this.deserializeIdTokens(jsonCache.IdToken)\r\n : {},\r\n accessTokens: jsonCache.AccessToken\r\n ? this.deserializeAccessTokens(jsonCache.AccessToken)\r\n : {},\r\n refreshTokens: jsonCache.RefreshToken\r\n ? this.deserializeRefreshTokens(jsonCache.RefreshToken)\r\n : {},\r\n appMetadata: jsonCache.AppMetadata\r\n ? this.deserializeAppMetadata(jsonCache.AppMetadata)\r\n : {},\r\n };\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AccountCache, IdTokenCache, AccessTokenCache, RefreshTokenCache, AppMetadataCache } from \"@azure/msal-common\";\r\nimport { InMemoryCache, JsonCache, SerializedAccountEntity, SerializedIdTokenEntity, SerializedAccessTokenEntity, SerializedRefreshTokenEntity, SerializedAppMetadataEntity } from \"./SerializerTypes\";\r\n\r\nexport class Serializer {\r\n /**\r\n * serialize the JSON blob\r\n * @param data\r\n */\r\n static serializeJSONBlob(data: JsonCache): string {\r\n return JSON.stringify(data);\r\n }\r\n\r\n /**\r\n * Serialize Accounts\r\n * @param accCache\r\n */\r\n static serializeAccounts(accCache: AccountCache): Record {\r\n const accounts: Record = {};\r\n Object.keys(accCache).map(function (key) {\r\n const accountEntity = accCache[key];\r\n accounts[key] = {\r\n home_account_id: accountEntity.homeAccountId,\r\n environment: accountEntity.environment,\r\n realm: accountEntity.realm,\r\n local_account_id: accountEntity.localAccountId,\r\n username: accountEntity.username,\r\n authority_type: accountEntity.authorityType,\r\n name: accountEntity.name,\r\n client_info: accountEntity.clientInfo,\r\n last_modification_time: accountEntity.lastModificationTime,\r\n last_modification_app: accountEntity.lastModificationApp,\r\n };\r\n });\r\n\r\n return accounts;\r\n }\r\n\r\n /**\r\n * Serialize IdTokens\r\n * @param idTCache\r\n */\r\n static serializeIdTokens(idTCache: IdTokenCache): Record {\r\n const idTokens: Record = {};\r\n Object.keys(idTCache).map(function (key) {\r\n const idTEntity = idTCache[key];\r\n idTokens[key] = {\r\n home_account_id: idTEntity.homeAccountId,\r\n environment: idTEntity.environment,\r\n credential_type: idTEntity.credentialType,\r\n client_id: idTEntity.clientId,\r\n secret: idTEntity.secret,\r\n realm: idTEntity.realm,\r\n };\r\n });\r\n\r\n return idTokens;\r\n }\r\n\r\n /**\r\n * Serializes AccessTokens\r\n * @param atCache\r\n */\r\n static serializeAccessTokens(atCache: AccessTokenCache): Record {\r\n const accessTokens: Record = {};\r\n Object.keys(atCache).map(function (key) {\r\n const atEntity = atCache[key];\r\n accessTokens[key] = {\r\n home_account_id: atEntity.homeAccountId,\r\n environment: atEntity.environment,\r\n credential_type: atEntity.credentialType,\r\n client_id: atEntity.clientId,\r\n secret: atEntity.secret,\r\n realm: atEntity.realm,\r\n target: atEntity.target,\r\n cached_at: atEntity.cachedAt,\r\n expires_on: atEntity.expiresOn,\r\n extended_expires_on: atEntity.extendedExpiresOn,\r\n refresh_on: atEntity.refreshOn,\r\n key_id: atEntity.keyId,\r\n token_type: atEntity.tokenType,\r\n requestedClaims: atEntity.requestedClaims,\r\n requestedClaimsHash: atEntity.requestedClaimsHash,\r\n userAssertionHash: atEntity.userAssertionHash\r\n };\r\n });\r\n\r\n return accessTokens;\r\n }\r\n\r\n /**\r\n * Serialize refreshTokens\r\n * @param rtCache\r\n */\r\n static serializeRefreshTokens(rtCache: RefreshTokenCache): Record {\r\n const refreshTokens: Record = {};\r\n Object.keys(rtCache).map(function (key) {\r\n const rtEntity = rtCache[key];\r\n refreshTokens[key] = {\r\n home_account_id: rtEntity.homeAccountId,\r\n environment: rtEntity.environment,\r\n credential_type: rtEntity.credentialType,\r\n client_id: rtEntity.clientId,\r\n secret: rtEntity.secret,\r\n family_id: rtEntity.familyId,\r\n target: rtEntity.target,\r\n realm: rtEntity.realm\r\n };\r\n });\r\n\r\n return refreshTokens;\r\n }\r\n\r\n /**\r\n * Serialize amdtCache\r\n * @param amdtCache\r\n */\r\n static serializeAppMetadata(amdtCache: AppMetadataCache): Record {\r\n const appMetadata: Record = {};\r\n Object.keys(amdtCache).map(function (key) {\r\n const amdtEntity = amdtCache[key];\r\n appMetadata[key] = {\r\n client_id: amdtEntity.clientId,\r\n environment: amdtEntity.environment,\r\n family_id: amdtEntity.familyId,\r\n };\r\n });\r\n\r\n return appMetadata;\r\n }\r\n\r\n /**\r\n * Serialize the cache\r\n * @param jsonContent\r\n */\r\n static serializeAllCache(inMemCache: InMemoryCache): JsonCache {\r\n return {\r\n Account: this.serializeAccounts(inMemCache.accounts),\r\n IdToken: this.serializeIdTokens(inMemCache.idTokens),\r\n AccessToken: this.serializeAccessTokens(inMemCache.accessTokens),\r\n RefreshToken: this.serializeRefreshTokens(inMemCache.refreshTokens),\r\n AppMetadata: this.serializeAppMetadata(inMemCache.appMetadata),\r\n };\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { TokenKeys ,\r\n AccountEntity,\r\n IdTokenEntity,\r\n AccessTokenEntity,\r\n RefreshTokenEntity,\r\n AppMetadataEntity,\r\n ServerTelemetryEntity,\r\n ThrottlingEntity,\r\n CacheManager,\r\n Logger,\r\n ValidCacheType,\r\n ICrypto,\r\n AuthorityMetadataEntity,\r\n ValidCredentialType\r\n} from \"@azure/msal-common\";\r\n\r\nimport { Deserializer } from \"./serializer/Deserializer\";\r\nimport { Serializer } from \"./serializer/Serializer\";\r\nimport { InMemoryCache, JsonCache, CacheKVStore } from \"./serializer/SerializerTypes\";\r\n\r\n/**\r\n * This class implements Storage for node, reading cache from user specified storage location or an extension library\r\n * @public\r\n */\r\nexport class NodeStorage extends CacheManager {\r\n // Cache configuration, either set by user or default values.\r\n private logger: Logger;\r\n private cache: CacheKVStore = {};\r\n private changeEmitters: Array = [];\r\n\r\n constructor(logger: Logger, clientId: string, cryptoImpl: ICrypto) {\r\n super(clientId, cryptoImpl, logger);\r\n this.logger = logger;\r\n }\r\n\r\n /**\r\n * Queue up callbacks\r\n * @param func - a callback function for cache change indication\r\n */\r\n registerChangeEmitter(func: () => void): void {\r\n this.changeEmitters.push(func);\r\n }\r\n\r\n /**\r\n * Invoke the callback when cache changes\r\n */\r\n emitChange(): void {\r\n this.changeEmitters.forEach(func => func.call(null));\r\n }\r\n\r\n /**\r\n * Converts cacheKVStore to InMemoryCache\r\n * @param cache - key value store\r\n */\r\n cacheToInMemoryCache(cache: CacheKVStore): InMemoryCache {\r\n const inMemoryCache: InMemoryCache = {\r\n accounts: {},\r\n idTokens: {},\r\n accessTokens: {},\r\n refreshTokens: {},\r\n appMetadata: {},\r\n };\r\n\r\n for (const key in cache) {\r\n if (cache[key as string] instanceof AccountEntity) {\r\n inMemoryCache.accounts[key] = cache[key] as AccountEntity;\r\n } else if (cache[key] instanceof IdTokenEntity) {\r\n inMemoryCache.idTokens[key] = cache[key] as IdTokenEntity;\r\n } else if (cache[key] instanceof AccessTokenEntity) {\r\n inMemoryCache.accessTokens[key] = cache[key] as AccessTokenEntity;\r\n } else if (cache[key] instanceof RefreshTokenEntity) {\r\n inMemoryCache.refreshTokens[key] = cache[key] as RefreshTokenEntity;\r\n } else if (cache[key] instanceof AppMetadataEntity) {\r\n inMemoryCache.appMetadata[key] = cache[key] as AppMetadataEntity;\r\n } else {\r\n continue;\r\n }\r\n }\r\n\r\n return inMemoryCache;\r\n }\r\n\r\n /**\r\n * converts inMemoryCache to CacheKVStore\r\n * @param inMemoryCache - kvstore map for inmemory\r\n */\r\n inMemoryCacheToCache(inMemoryCache: InMemoryCache): CacheKVStore {\r\n\r\n // convert in memory cache to a flat Key-Value map\r\n let cache = this.getCache();\r\n\r\n cache = {\r\n ...cache,\r\n ...inMemoryCache.accounts,\r\n ...inMemoryCache.idTokens,\r\n ...inMemoryCache.accessTokens,\r\n ...inMemoryCache.refreshTokens,\r\n ...inMemoryCache.appMetadata\r\n };\r\n\r\n // convert in memory cache to a flat Key-Value map\r\n return cache;\r\n }\r\n\r\n /**\r\n * gets the current in memory cache for the client\r\n */\r\n getInMemoryCache(): InMemoryCache {\r\n this.logger.trace(\"Getting in-memory cache\");\r\n\r\n // convert the cache key value store to inMemoryCache\r\n const inMemoryCache = this.cacheToInMemoryCache(this.getCache());\r\n return inMemoryCache;\r\n }\r\n\r\n /**\r\n * sets the current in memory cache for the client\r\n * @param inMemoryCache - key value map in memory\r\n */\r\n setInMemoryCache(inMemoryCache: InMemoryCache): void{\r\n this.logger.trace(\"Setting in-memory cache\");\r\n\r\n // convert and append the inMemoryCache to cacheKVStore\r\n const cache = this.inMemoryCacheToCache(inMemoryCache);\r\n this.setCache(cache);\r\n\r\n this.emitChange();\r\n }\r\n\r\n /**\r\n * get the current cache key-value store\r\n */\r\n getCache(): CacheKVStore {\r\n this.logger.trace(\"Getting cache key-value store\");\r\n return this.cache;\r\n }\r\n\r\n /**\r\n * sets the current cache (key value store)\r\n * @param cacheMap - key value map\r\n */\r\n setCache(cache: CacheKVStore): void {\r\n this.logger.trace(\"Setting cache key value store\");\r\n this.cache = cache;\r\n\r\n // mark change in cache\r\n this.emitChange();\r\n }\r\n\r\n /**\r\n * Gets cache item with given key.\r\n * @param key - lookup key for the cache entry\r\n */\r\n getItem(key: string): ValidCacheType {\r\n this.logger.tracePii(`Item key: ${key}`);\r\n\r\n // read cache\r\n const cache = this.getCache();\r\n return cache[key];\r\n }\r\n\r\n /**\r\n * Gets cache item with given key-value\r\n * @param key - lookup key for the cache entry\r\n * @param value - value of the cache entry\r\n */\r\n setItem(key: string, value: ValidCacheType): void {\r\n this.logger.tracePii(`Item key: ${key}`);\r\n\r\n // read cache\r\n const cache = this.getCache();\r\n cache[key] = value;\r\n\r\n // write to cache\r\n this.setCache(cache);\r\n }\r\n\r\n getAccountKeys(): string[] {\r\n const inMemoryCache = this.getInMemoryCache();\r\n const accountKeys = Object.keys(inMemoryCache.accounts);\r\n\r\n return accountKeys;\r\n }\r\n\r\n getTokenKeys(): TokenKeys {\r\n const inMemoryCache = this.getInMemoryCache();\r\n const tokenKeys = {\r\n idToken: Object.keys(inMemoryCache.idTokens),\r\n accessToken: Object.keys(inMemoryCache.accessTokens),\r\n refreshToken: Object.keys(inMemoryCache.refreshTokens)\r\n };\r\n\r\n return tokenKeys;\r\n }\r\n\r\n /**\r\n * fetch the account entity\r\n * @param accountKey - lookup key to fetch cache type AccountEntity\r\n */\r\n getAccount(accountKey: string): AccountEntity | null {\r\n const account = this.getItem(accountKey) as AccountEntity;\r\n if (AccountEntity.isAccountEntity(account)) {\r\n return account;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * set account entity\r\n * @param account - cache value to be set of type AccountEntity\r\n */\r\n setAccount(account: AccountEntity): void {\r\n const accountKey = account.generateAccountKey();\r\n this.setItem(accountKey, account);\r\n }\r\n\r\n /**\r\n * fetch the idToken credential\r\n * @param idTokenKey - lookup key to fetch cache type IdTokenEntity\r\n */\r\n getIdTokenCredential(idTokenKey: string): IdTokenEntity | null {\r\n const idToken = this.getItem(idTokenKey) as IdTokenEntity;\r\n if (IdTokenEntity.isIdTokenEntity(idToken)) {\r\n return idToken;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * set idToken credential\r\n * @param idToken - cache value to be set of type IdTokenEntity\r\n */\r\n setIdTokenCredential(idToken: IdTokenEntity): void {\r\n const idTokenKey = idToken.generateCredentialKey();\r\n this.setItem(idTokenKey, idToken);\r\n }\r\n\r\n /**\r\n * fetch the accessToken credential\r\n * @param accessTokenKey - lookup key to fetch cache type AccessTokenEntity\r\n */\r\n getAccessTokenCredential(accessTokenKey: string): AccessTokenEntity | null {\r\n const accessToken = this.getItem(accessTokenKey) as AccessTokenEntity;\r\n if (AccessTokenEntity.isAccessTokenEntity(accessToken)) {\r\n return accessToken;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * set accessToken credential\r\n * @param accessToken - cache value to be set of type AccessTokenEntity\r\n */\r\n setAccessTokenCredential(accessToken: AccessTokenEntity): void {\r\n const accessTokenKey = accessToken.generateCredentialKey();\r\n this.setItem(accessTokenKey, accessToken);\r\n }\r\n\r\n /**\r\n * fetch the refreshToken credential\r\n * @param refreshTokenKey - lookup key to fetch cache type RefreshTokenEntity\r\n */\r\n getRefreshTokenCredential(refreshTokenKey: string): RefreshTokenEntity | null {\r\n const refreshToken = this.getItem(refreshTokenKey) as RefreshTokenEntity;\r\n if (RefreshTokenEntity.isRefreshTokenEntity(refreshToken)) {\r\n return refreshToken as RefreshTokenEntity;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * set refreshToken credential\r\n * @param refreshToken - cache value to be set of type RefreshTokenEntity\r\n */\r\n setRefreshTokenCredential(refreshToken: RefreshTokenEntity): void {\r\n const refreshTokenKey = refreshToken.generateCredentialKey();\r\n this.setItem(refreshTokenKey, refreshToken);\r\n }\r\n\r\n /**\r\n * fetch appMetadata entity from the platform cache\r\n * @param appMetadataKey - lookup key to fetch cache type AppMetadataEntity\r\n */\r\n getAppMetadata(appMetadataKey: string): AppMetadataEntity | null {\r\n const appMetadata: AppMetadataEntity = this.getItem(appMetadataKey) as AppMetadataEntity;\r\n if (AppMetadataEntity.isAppMetadataEntity(appMetadataKey, appMetadata)) {\r\n return appMetadata;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * set appMetadata entity to the platform cache\r\n * @param appMetadata - cache value to be set of type AppMetadataEntity\r\n */\r\n setAppMetadata(appMetadata: AppMetadataEntity): void {\r\n const appMetadataKey = appMetadata.generateAppMetadataKey();\r\n this.setItem(appMetadataKey, appMetadata);\r\n }\r\n\r\n /**\r\n * fetch server telemetry entity from the platform cache\r\n * @param serverTelemetrykey - lookup key to fetch cache type ServerTelemetryEntity\r\n */\r\n getServerTelemetry(serverTelemetrykey: string): ServerTelemetryEntity | null {\r\n const serverTelemetryEntity: ServerTelemetryEntity = this.getItem(serverTelemetrykey) as ServerTelemetryEntity;\r\n if (serverTelemetryEntity && ServerTelemetryEntity.isServerTelemetryEntity(serverTelemetrykey, serverTelemetryEntity)) {\r\n return serverTelemetryEntity;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * set server telemetry entity to the platform cache\r\n * @param serverTelemetryKey - lookup key to fetch cache type ServerTelemetryEntity\r\n * @param serverTelemetry - cache value to be set of type ServerTelemetryEntity\r\n */\r\n setServerTelemetry(serverTelemetryKey: string, serverTelemetry: ServerTelemetryEntity): void {\r\n this.setItem(serverTelemetryKey, serverTelemetry);\r\n }\r\n\r\n /**\r\n * fetch authority metadata entity from the platform cache\r\n * @param key - lookup key to fetch cache type AuthorityMetadataEntity\r\n */\r\n getAuthorityMetadata(key: string): AuthorityMetadataEntity | null {\r\n const authorityMetadataEntity: AuthorityMetadataEntity = this.getItem(key) as AuthorityMetadataEntity;\r\n if (authorityMetadataEntity && AuthorityMetadataEntity.isAuthorityMetadataEntity(key, authorityMetadataEntity)) {\r\n return authorityMetadataEntity;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Get all authority metadata keys\r\n */\r\n getAuthorityMetadataKeys(): Array {\r\n return this.getKeys().filter((key) => {\r\n return this.isAuthorityMetadata(key);\r\n });\r\n }\r\n\r\n /**\r\n * set authority metadata entity to the platform cache\r\n * @param key - lookup key to fetch cache type AuthorityMetadataEntity\r\n * @param metadata - cache value to be set of type AuthorityMetadataEntity\r\n */\r\n setAuthorityMetadata(key: string, metadata: AuthorityMetadataEntity): void {\r\n this.setItem(key, metadata);\r\n }\r\n\r\n /**\r\n * fetch throttling entity from the platform cache\r\n * @param throttlingCacheKey - lookup key to fetch cache type ThrottlingEntity\r\n */\r\n getThrottlingCache(throttlingCacheKey: string): ThrottlingEntity | null {\r\n const throttlingCache: ThrottlingEntity = this.getItem(throttlingCacheKey) as ThrottlingEntity;\r\n if (throttlingCache && ThrottlingEntity.isThrottlingEntity(throttlingCacheKey, throttlingCache)) {\r\n return throttlingCache;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * set throttling entity to the platform cache\r\n * @param throttlingCacheKey - lookup key to fetch cache type ThrottlingEntity\r\n * @param throttlingCache - cache value to be set of type ThrottlingEntity\r\n */\r\n setThrottlingCache(throttlingCacheKey: string, throttlingCache: ThrottlingEntity): void {\r\n this.setItem(throttlingCacheKey, throttlingCache);\r\n }\r\n\r\n /**\r\n * Removes the cache item from memory with the given key.\r\n * @param key - lookup key to remove a cache entity\r\n * @param inMemory - key value map of the cache\r\n */\r\n removeItem(key: string): boolean {\r\n this.logger.tracePii(`Item key: ${key}`);\r\n\r\n // read inMemoryCache\r\n let result: boolean = false;\r\n const cache = this.getCache();\r\n\r\n if (!!cache[key]) {\r\n delete cache[key];\r\n result = true;\r\n }\r\n\r\n // write to the cache after removal\r\n if (result) {\r\n this.setCache(cache);\r\n this.emitChange();\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Checks whether key is in cache.\r\n * @param key - look up key for a cache entity\r\n */\r\n containsKey(key: string): boolean {\r\n return this.getKeys().includes(key);\r\n }\r\n\r\n /**\r\n * Gets all keys in window.\r\n */\r\n getKeys(): string[] {\r\n this.logger.trace(\"Retrieving all cache keys\");\r\n\r\n // read cache\r\n const cache = this.getCache();\r\n return [ ...Object.keys(cache)];\r\n }\r\n\r\n /**\r\n * Clears all cache entries created by MSAL (except tokens).\r\n */\r\n async clear(): Promise {\r\n this.logger.trace(\"Clearing cache entries created by MSAL\");\r\n\r\n // read inMemoryCache\r\n const cacheKeys = this.getKeys();\r\n\r\n // delete each element\r\n cacheKeys.forEach(key => {\r\n this.removeItem(key);\r\n });\r\n this.emitChange();\r\n }\r\n\r\n /**\r\n * Initialize in memory cache from an exisiting cache vault\r\n * @param cache - blob formatted cache (JSON)\r\n */\r\n static generateInMemoryCache(cache: string): InMemoryCache {\r\n return Deserializer.deserializeAllCache(\r\n Deserializer.deserializeJSONBlob(cache)\r\n );\r\n }\r\n\r\n /**\r\n * retrieves the final JSON\r\n * @param inMemoryCache - itemised cache read from the JSON\r\n */\r\n static generateJsonCache(inMemoryCache: InMemoryCache): JsonCache {\r\n return Serializer.serializeAllCache(inMemoryCache);\r\n }\r\n\r\n /**\r\n * Updates a credential's cache key if the current cache key is outdated\r\n */\r\n updateCredentialCacheKey(currentCacheKey: string, credential: ValidCredentialType): string {\r\n const updatedCacheKey = credential.generateCredentialKey();\r\n\r\n if (currentCacheKey !== updatedCacheKey) {\r\n const cacheItem = this.getItem(currentCacheKey);\r\n if (cacheItem) {\r\n this.removeItem(currentCacheKey);\r\n this.setItem(updatedCacheKey, cacheItem);\r\n this.logger.verbose(`Updated an outdated ${credential.credentialType} cache key`);\r\n return updatedCacheKey;\r\n } else {\r\n this.logger.error(`Attempted to update an outdated ${credential.credentialType} cache key but no item matching the outdated key was found in storage`);\r\n }\r\n }\r\n\r\n return currentCacheKey;\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { NodeStorage } from \"./NodeStorage\";\r\nimport { StringUtils, AccountEntity, AccountInfo, Logger, ISerializableTokenCache, ICachePlugin, TokenCacheContext } from \"@azure/msal-common\";\r\nimport { InMemoryCache, JsonCache, SerializedAccountEntity, SerializedAccessTokenEntity, SerializedRefreshTokenEntity, SerializedIdTokenEntity, SerializedAppMetadataEntity, CacheKVStore } from \"./serializer/SerializerTypes\";\r\nimport { Deserializer } from \"./serializer/Deserializer\";\r\nimport { Serializer } from \"./serializer/Serializer\";\r\nimport { ITokenCache } from \"./ITokenCache\";\r\n\r\nconst defaultSerializedCache: JsonCache = {\r\n Account: {},\r\n IdToken: {},\r\n AccessToken: {},\r\n RefreshToken: {},\r\n AppMetadata: {},\r\n};\r\n\r\n/**\r\n * In-memory token cache manager\r\n * @public\r\n */\r\nexport class TokenCache implements ISerializableTokenCache, ITokenCache {\r\n\r\n private storage: NodeStorage;\r\n private cacheHasChanged: boolean;\r\n private cacheSnapshot: string;\r\n private readonly persistence: ICachePlugin;\r\n private logger: Logger;\r\n\r\n constructor(storage: NodeStorage, logger: Logger, cachePlugin?: ICachePlugin) {\r\n this.cacheHasChanged = false;\r\n this.storage = storage;\r\n this.storage.registerChangeEmitter(this.handleChangeEvent.bind(this));\r\n if (cachePlugin) {\r\n this.persistence = cachePlugin;\r\n }\r\n this.logger = logger;\r\n }\r\n\r\n /**\r\n * Set to true if cache state has changed since last time serialize or writeToPersistence was called\r\n */\r\n hasChanged(): boolean {\r\n return this.cacheHasChanged;\r\n }\r\n\r\n /**\r\n * Serializes in memory cache to JSON\r\n */\r\n serialize(): string {\r\n this.logger.trace(\"Serializing in-memory cache\");\r\n let finalState = Serializer.serializeAllCache(\r\n this.storage.getInMemoryCache() as InMemoryCache\r\n );\r\n\r\n // if cacheSnapshot not null or empty, merge\r\n if (!StringUtils.isEmpty(this.cacheSnapshot)) {\r\n this.logger.trace(\"Reading cache snapshot from disk\");\r\n finalState = this.mergeState(\r\n JSON.parse(this.cacheSnapshot),\r\n finalState\r\n );\r\n } else {\r\n this.logger.trace(\"No cache snapshot to merge\");\r\n }\r\n this.cacheHasChanged = false;\r\n\r\n return JSON.stringify(finalState);\r\n }\r\n\r\n /**\r\n * Deserializes JSON to in-memory cache. JSON should be in MSAL cache schema format\r\n * @param cache - blob formatted cache\r\n */\r\n deserialize(cache: string): void {\r\n this.logger.trace(\"Deserializing JSON to in-memory cache\");\r\n this.cacheSnapshot = cache;\r\n\r\n if (!StringUtils.isEmpty(this.cacheSnapshot)) {\r\n this.logger.trace(\"Reading cache snapshot from disk\");\r\n const deserializedCache = Deserializer.deserializeAllCache(\r\n this.overlayDefaults(JSON.parse(this.cacheSnapshot))\r\n );\r\n this.storage.setInMemoryCache(deserializedCache);\r\n } else {\r\n this.logger.trace(\"No cache snapshot to deserialize\");\r\n }\r\n }\r\n\r\n /**\r\n * Fetches the cache key-value map\r\n */\r\n getKVStore(): CacheKVStore {\r\n return this.storage.getCache();\r\n }\r\n\r\n /**\r\n * API that retrieves all accounts currently in cache to the user\r\n */\r\n async getAllAccounts(): Promise {\r\n\r\n this.logger.trace(\"getAllAccounts called\");\r\n let cacheContext;\r\n try {\r\n if (this.persistence) {\r\n cacheContext = new TokenCacheContext(this, false);\r\n await this.persistence.beforeCacheAccess(cacheContext);\r\n }\r\n return this.storage.getAllAccounts();\r\n } finally {\r\n if (this.persistence && cacheContext) {\r\n await this.persistence.afterCacheAccess(cacheContext);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching homeAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param homeAccountId - unique identifier for an account (uid.utid)\r\n */\r\n async getAccountByHomeId(homeAccountId: string): Promise {\r\n const allAccounts = await this.getAllAccounts();\r\n if (!StringUtils.isEmpty(homeAccountId) && allAccounts && allAccounts.length) {\r\n return allAccounts.filter(accountObj => accountObj.homeAccountId === homeAccountId)[0] || null;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching localAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param localAccountId - unique identifier of an account (sub/obj when homeAccountId cannot be populated)\r\n */\r\n async getAccountByLocalId(localAccountId: string): Promise {\r\n const allAccounts = await this.getAllAccounts();\r\n if (!StringUtils.isEmpty(localAccountId) && allAccounts && allAccounts.length) {\r\n return allAccounts.filter(accountObj => accountObj.localAccountId === localAccountId)[0] || null;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * API to remove a specific account and the relevant data from cache\r\n * @param account - AccountInfo passed by the user\r\n */\r\n async removeAccount(account: AccountInfo): Promise {\r\n this.logger.trace(\"removeAccount called\");\r\n let cacheContext;\r\n try {\r\n if (this.persistence) {\r\n cacheContext = new TokenCacheContext(this, true);\r\n await this.persistence.beforeCacheAccess(cacheContext);\r\n }\r\n await this.storage.removeAccount(AccountEntity.generateAccountCacheKey(account));\r\n } finally {\r\n if (this.persistence && cacheContext) {\r\n await this.persistence.afterCacheAccess(cacheContext);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Called when the cache has changed state.\r\n */\r\n private handleChangeEvent() {\r\n this.cacheHasChanged = true;\r\n }\r\n\r\n /**\r\n * Merge in memory cache with the cache snapshot.\r\n * @param oldState - cache before changes\r\n * @param currentState - current cache state in the library\r\n */\r\n private mergeState(oldState: JsonCache, currentState: JsonCache): JsonCache {\r\n this.logger.trace(\"Merging in-memory cache with cache snapshot\");\r\n const stateAfterRemoval = this.mergeRemovals(oldState, currentState);\r\n return this.mergeUpdates(stateAfterRemoval, currentState);\r\n }\r\n\r\n /**\r\n * Deep update of oldState based on newState values\r\n * @param oldState - cache before changes\r\n * @param newState - updated cache\r\n */\r\n private mergeUpdates(oldState: object, newState: object): JsonCache {\r\n Object.keys(newState).forEach((newKey: string) => {\r\n const newValue = newState[newKey];\r\n\r\n // if oldState does not contain value but newValue does, add it\r\n if (!oldState.hasOwnProperty(newKey)) {\r\n if (newValue !== null) {\r\n oldState[newKey] = newValue;\r\n }\r\n } else {\r\n // both oldState and newState contain the key, do deep update\r\n const newValueNotNull = newValue !== null;\r\n const newValueIsObject = typeof newValue === \"object\";\r\n const newValueIsNotArray = !Array.isArray(newValue);\r\n const oldStateNotUndefinedOrNull = typeof oldState[newKey] !== \"undefined\" && oldState[newKey] !== null;\r\n\r\n if (newValueNotNull && newValueIsObject && newValueIsNotArray && oldStateNotUndefinedOrNull) {\r\n this.mergeUpdates(oldState[newKey], newValue);\r\n } else {\r\n oldState[newKey] = newValue;\r\n }\r\n }\r\n });\r\n\r\n return oldState as JsonCache;\r\n }\r\n\r\n /**\r\n * Removes entities in oldState that the were removed from newState. If there are any unknown values in root of\r\n * oldState that are not recognized, they are left untouched.\r\n * @param oldState - cache before changes\r\n * @param newState - updated cache\r\n */\r\n private mergeRemovals(oldState: JsonCache, newState: JsonCache): JsonCache {\r\n this.logger.trace(\"Remove updated entries in cache\");\r\n const accounts = oldState.Account ? this.mergeRemovalsDict(oldState.Account, newState.Account) : oldState.Account;\r\n const accessTokens = oldState.AccessToken ? this.mergeRemovalsDict(oldState.AccessToken, newState.AccessToken) : oldState.AccessToken;\r\n const refreshTokens = oldState.RefreshToken ? this.mergeRemovalsDict(oldState.RefreshToken, newState.RefreshToken) : oldState.RefreshToken;\r\n const idTokens = oldState.IdToken ? this.mergeRemovalsDict(oldState.IdToken, newState.IdToken) : oldState.IdToken;\r\n const appMetadata = oldState.AppMetadata ? this.mergeRemovalsDict(oldState.AppMetadata, newState.AppMetadata) : oldState.AppMetadata;\r\n\r\n return {\r\n ...oldState,\r\n Account: accounts,\r\n AccessToken: accessTokens,\r\n RefreshToken: refreshTokens,\r\n IdToken: idTokens,\r\n AppMetadata: appMetadata\r\n };\r\n }\r\n\r\n /**\r\n * Helper to merge new cache with the old one\r\n * @param oldState - cache before changes\r\n * @param newState - updated cache\r\n */\r\n private mergeRemovalsDict(oldState: Record, newState?: Record): Record {\r\n const finalState = { ...oldState };\r\n Object.keys(oldState).forEach((oldKey) => {\r\n if (!newState || !(newState.hasOwnProperty(oldKey))) {\r\n delete finalState[oldKey];\r\n }\r\n });\r\n return finalState;\r\n }\r\n\r\n /**\r\n * Helper to overlay as a part of cache merge\r\n * @param passedInCache - cache read from the blob\r\n */\r\n private overlayDefaults(passedInCache: JsonCache): JsonCache {\r\n this.logger.trace(\"Overlaying input cache with the default cache\");\r\n return {\r\n Account: {\r\n ...defaultSerializedCache.Account,\r\n ...passedInCache.Account,\r\n },\r\n IdToken: {\r\n ...defaultSerializedCache.IdToken,\r\n ...passedInCache.IdToken,\r\n },\r\n AccessToken: {\r\n ...defaultSerializedCache.AccessToken,\r\n ...passedInCache.AccessToken,\r\n },\r\n RefreshToken: {\r\n ...defaultSerializedCache.RefreshToken,\r\n ...passedInCache.RefreshToken,\r\n },\r\n AppMetadata: {\r\n ...defaultSerializedCache.AppMetadata,\r\n ...passedInCache.AppMetadata,\r\n },\r\n };\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"@azure/msal-common\";\r\n\r\n/**\r\n * NodeAuthErrorMessage class containing string constants used by error codes and messages.\r\n */\r\nexport const NodeAuthErrorMessage = {\r\n invalidLoopbackAddressType: {\r\n code: \"invalid_loopback_server_address_type\",\r\n desc: \"Loopback server address is not type string. This is unexpected.\"\r\n },\r\n unableToLoadRedirectUri: {\r\n code: \"unable_to_load_redirectUrl\",\r\n desc: \"Loopback server callback was invoked without a url. This is unexpected.\"\r\n },\r\n noAuthCodeInResponse: {\r\n code: \"no_auth_code_in_response\",\r\n desc: \"No auth code found in the server response. Please check your network trace to determine what happened.\"\r\n },\r\n noLoopbackServerExists: {\r\n code: \"no_loopback_server_exists\",\r\n desc: \"No loopback server exists yet.\"\r\n },\r\n loopbackServerAlreadyExists: {\r\n code: \"loopback_server_already_exists\",\r\n desc: \"Loopback server already exists. Cannot create another.\"\r\n },\r\n loopbackServerTimeout: {\r\n code: \"loopback_server_timeout\",\r\n desc: \"Timed out waiting for auth code listener to be registered.\"\r\n },\r\n stateNotFoundError: {\r\n code: \"state_not_found\",\r\n desc: \"State not found. Please verify that the request originated from msal.\"\r\n },\r\n};\r\n\r\nexport class NodeAuthError extends AuthError {\r\n constructor(errorCode: string, errorMessage?: string) {\r\n super(errorCode, errorMessage);\r\n this.name = \"NodeAuthError\";\r\n }\r\n\r\n /**\r\n * Creates an error thrown if loopback server address is of type string.\r\n */\r\n static createInvalidLoopbackAddressTypeError(): NodeAuthError {\r\n return new NodeAuthError(NodeAuthErrorMessage.invalidLoopbackAddressType.code,\r\n `${NodeAuthErrorMessage.invalidLoopbackAddressType.desc}`);\r\n }\r\n\r\n /**\r\n * Creates an error thrown if the loopback server is unable to get a url.\r\n */\r\n static createUnableToLoadRedirectUrlError(): NodeAuthError {\r\n return new NodeAuthError(NodeAuthErrorMessage.unableToLoadRedirectUri.code,\r\n `${NodeAuthErrorMessage.unableToLoadRedirectUri.desc}`);\r\n }\r\n\r\n /**\r\n * Creates an error thrown if the server response does not contain an auth code.\r\n */\r\n static createNoAuthCodeInResponseError(): NodeAuthError {\r\n return new NodeAuthError(NodeAuthErrorMessage.noAuthCodeInResponse.code,\r\n `${NodeAuthErrorMessage.noAuthCodeInResponse.desc}`);\r\n }\r\n\r\n /**\r\n * Creates an error thrown if the loopback server has not been spun up yet.\r\n */\r\n static createNoLoopbackServerExistsError(): NodeAuthError {\r\n return new NodeAuthError(NodeAuthErrorMessage.noLoopbackServerExists.code,\r\n `${NodeAuthErrorMessage.noLoopbackServerExists.desc}`);\r\n }\r\n\r\n /**\r\n * Creates an error thrown if a loopback server already exists when attempting to create another one.\r\n */\r\n static createLoopbackServerAlreadyExistsError(): NodeAuthError {\r\n return new NodeAuthError(NodeAuthErrorMessage.loopbackServerAlreadyExists.code,\r\n `${NodeAuthErrorMessage.loopbackServerAlreadyExists.desc}`);\r\n }\r\n\r\n /**\r\n * Creates an error thrown if the loopback server times out registering the auth code listener.\r\n */\r\n static createLoopbackServerTimeoutError(): NodeAuthError {\r\n return new NodeAuthError(NodeAuthErrorMessage.loopbackServerTimeout.code,\r\n `${NodeAuthErrorMessage.loopbackServerTimeout.desc}`);\r\n }\r\n\r\n /**\r\n * Creates an error thrown when the state is not present.\r\n */\r\n static createStateNotFoundError(): NodeAuthError {\r\n return new NodeAuthError(NodeAuthErrorMessage.stateNotFoundError.code, NodeAuthErrorMessage.stateNotFoundError.desc);\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AuthorizationCodeClient,\r\n ClientConfiguration,\r\n RefreshTokenClient,\r\n AuthenticationResult,\r\n Authority,\r\n AuthorityFactory,\r\n BaseAuthRequest,\r\n SilentFlowClient,\r\n Logger,\r\n ServerTelemetryManager,\r\n ServerTelemetryRequest,\r\n CommonSilentFlowRequest,\r\n CommonRefreshTokenRequest,\r\n CommonAuthorizationCodeRequest,\r\n CommonAuthorizationUrlRequest,\r\n CommonUsernamePasswordRequest,\r\n UsernamePasswordClient,\r\n AuthenticationScheme,\r\n ResponseMode,\r\n AuthorityOptions,\r\n OIDC_DEFAULT_SCOPES,\r\n AzureRegionConfiguration,\r\n AuthError,\r\n AzureCloudOptions,\r\n AuthorizationCodePayload,\r\n StringUtils,\r\n ClientAuthError,\r\n Constants, } from \"@azure/msal-common\";\r\nimport { Configuration, buildAppConfiguration, NodeConfiguration } from \"../config/Configuration\";\r\nimport { CryptoProvider } from \"../crypto/CryptoProvider\";\r\nimport { NodeStorage } from \"../cache/NodeStorage\";\r\nimport { Constants as NodeConstants, ApiId } from \"../utils/Constants\";\r\nimport { TokenCache } from \"../cache/TokenCache\";\r\nimport { ClientAssertion } from \"./ClientAssertion\";\r\nimport { AuthorizationUrlRequest } from \"../request/AuthorizationUrlRequest\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest\";\r\nimport { RefreshTokenRequest } from \"../request/RefreshTokenRequest\";\r\nimport { SilentFlowRequest } from \"../request/SilentFlowRequest\";\r\nimport { version, name } from \"../packageMetadata\";\r\nimport { UsernamePasswordRequest } from \"../request/UsernamePasswordRequest\";\r\nimport { NodeAuthError } from \"../error/NodeAuthError\";\r\n\r\n/**\r\n * Base abstract class for all ClientApplications - public and confidential\r\n * @public\r\n */\r\nexport abstract class ClientApplication {\r\n\r\n protected readonly cryptoProvider: CryptoProvider;\r\n private tokenCache: TokenCache;\r\n\r\n /**\r\n * Platform storage object\r\n */\r\n protected storage: NodeStorage;\r\n /**\r\n * Logger object to log the application flow\r\n */\r\n protected logger: Logger;\r\n /**\r\n * Platform configuration initialized by the application\r\n */\r\n protected config: NodeConfiguration;\r\n /**\r\n * Client assertion passed by the user for confidential client flows\r\n */\r\n protected clientAssertion: ClientAssertion;\r\n /**\r\n * Client secret passed by the user for confidential client flows\r\n */\r\n protected clientSecret: string;\r\n\r\n /**\r\n * Constructor for the ClientApplication\r\n */\r\n protected constructor(configuration: Configuration) {\r\n this.config = buildAppConfiguration(configuration);\r\n this.cryptoProvider = new CryptoProvider();\r\n this.logger = new Logger(this.config.system.loggerOptions, name, version);\r\n this.storage = new NodeStorage(this.logger, this.config.auth.clientId, this.cryptoProvider);\r\n this.tokenCache = new TokenCache(\r\n this.storage,\r\n this.logger,\r\n this.config.cache.cachePlugin\r\n );\r\n }\r\n\r\n /**\r\n * Creates the URL of the authorization request, letting the user input credentials and consent to the\r\n * application. The URL targets the /authorize endpoint of the authority configured in the\r\n * application object.\r\n *\r\n * Once the user inputs their credentials and consents, the authority will send a response to the redirect URI\r\n * sent in the request and should contain an authorization code, which can then be used to acquire tokens via\r\n * `acquireTokenByCode(AuthorizationCodeRequest)`.\r\n */\r\n async getAuthCodeUrl(request: AuthorizationUrlRequest): Promise {\r\n this.logger.info(\"getAuthCodeUrl called\", request.correlationId);\r\n const validRequest: CommonAuthorizationUrlRequest = {\r\n ...request,\r\n ... await this.initializeBaseRequest(request),\r\n responseMode: request.responseMode || ResponseMode.QUERY,\r\n authenticationScheme: AuthenticationScheme.BEARER\r\n };\r\n\r\n const authClientConfig = await this.buildOauthClientConfiguration(\r\n validRequest.authority,\r\n validRequest.correlationId,\r\n undefined,\r\n undefined,\r\n request.azureCloudOptions\r\n );\r\n const authorizationCodeClient = new AuthorizationCodeClient(\r\n authClientConfig\r\n );\r\n this.logger.verbose(\"Auth code client created\", validRequest.correlationId);\r\n return authorizationCodeClient.getAuthCodeUrl(validRequest);\r\n }\r\n\r\n /**\r\n * Acquires a token by exchanging the Authorization Code received from the first step of OAuth2.0\r\n * Authorization Code flow.\r\n *\r\n * `getAuthCodeUrl(AuthorizationCodeUrlRequest)` can be used to create the URL for the first step of OAuth2.0\r\n * Authorization Code flow. Ensure that values for redirectUri and scopes in AuthorizationCodeUrlRequest and\r\n * AuthorizationCodeRequest are the same.\r\n */\r\n async acquireTokenByCode(request: AuthorizationCodeRequest, authCodePayLoad?: AuthorizationCodePayload): Promise {\r\n this.logger.info(\"acquireTokenByCode called\");\r\n if (request.state && authCodePayLoad){\r\n this.logger.info(\"acquireTokenByCode - validating state\");\r\n this.validateState(request.state, authCodePayLoad.state || \"\");\r\n // eslint-disable-next-line no-param-reassign\r\n authCodePayLoad= {...authCodePayLoad, state: \"\"};\r\n }\r\n const validRequest: CommonAuthorizationCodeRequest = {\r\n ...request,\r\n ... await this.initializeBaseRequest(request),\r\n authenticationScheme: AuthenticationScheme.BEARER\r\n };\r\n\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByCode, validRequest.correlationId);\r\n try {\r\n const authClientConfig = await this.buildOauthClientConfiguration(\r\n validRequest.authority,\r\n validRequest.correlationId,\r\n serverTelemetryManager,\r\n undefined,\r\n request.azureCloudOptions\r\n );\r\n const authorizationCodeClient = new AuthorizationCodeClient(\r\n authClientConfig\r\n );\r\n this.logger.verbose(\"Auth code client created\", validRequest.correlationId);\r\n return authorizationCodeClient.acquireToken(validRequest, authCodePayLoad);\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(validRequest.correlationId);\r\n }\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Acquires a token by exchanging the refresh token provided for a new set of tokens.\r\n *\r\n * This API is provided only for scenarios where you would like to migrate from ADAL to MSAL. Otherwise, it is\r\n * recommended that you use `acquireTokenSilent()` for silent scenarios. When using `acquireTokenSilent()`, MSAL will\r\n * handle the caching and refreshing of tokens automatically.\r\n */\r\n async acquireTokenByRefreshToken(request: RefreshTokenRequest): Promise {\r\n this.logger.info(\"acquireTokenByRefreshToken called\", request.correlationId);\r\n const validRequest: CommonRefreshTokenRequest = {\r\n ...request,\r\n ... await this.initializeBaseRequest(request),\r\n authenticationScheme: AuthenticationScheme.BEARER\r\n };\r\n\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByRefreshToken, validRequest.correlationId);\r\n try {\r\n const refreshTokenClientConfig = await this.buildOauthClientConfiguration(\r\n validRequest.authority,\r\n validRequest.correlationId,\r\n serverTelemetryManager,\r\n undefined,\r\n request.azureCloudOptions\r\n );\r\n const refreshTokenClient = new RefreshTokenClient(\r\n refreshTokenClientConfig\r\n );\r\n this.logger.verbose(\"Refresh token client created\", validRequest.correlationId);\r\n return refreshTokenClient.acquireToken(validRequest);\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(validRequest.correlationId);\r\n }\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Acquires a token silently when a user specifies the account the token is requested for.\r\n *\r\n * This API expects the user to provide an account object and looks into the cache to retrieve the token if present.\r\n * There is also an optional \"forceRefresh\" boolean the user can send to bypass the cache for access_token and id_token.\r\n * In case the refresh_token is expired or not found, an error is thrown\r\n * and the guidance is for the user to call any interactive token acquisition API (eg: `acquireTokenByCode()`).\r\n */\r\n async acquireTokenSilent(request: SilentFlowRequest): Promise {\r\n const validRequest: CommonSilentFlowRequest = {\r\n ...request,\r\n ... await this.initializeBaseRequest(request),\r\n forceRefresh: request.forceRefresh || false\r\n };\r\n\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenSilent, validRequest.correlationId, validRequest.forceRefresh);\r\n try {\r\n const silentFlowClientConfig = await this.buildOauthClientConfiguration(\r\n validRequest.authority,\r\n validRequest.correlationId,\r\n serverTelemetryManager,\r\n undefined,\r\n request.azureCloudOptions\r\n );\r\n const silentFlowClient = new SilentFlowClient(\r\n silentFlowClientConfig\r\n );\r\n this.logger.verbose(\"Silent flow client created\", validRequest.correlationId);\r\n return silentFlowClient.acquireToken(validRequest);\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(validRequest.correlationId);\r\n }\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Acquires tokens with password grant by exchanging client applications username and password for credentials\r\n *\r\n * The latest OAuth 2.0 Security Best Current Practice disallows the password grant entirely.\r\n * More details on this recommendation at https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13#section-3.4\r\n * Microsoft's documentation and recommendations are at:\r\n * https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#usernamepassword\r\n *\r\n * @param request - UsenamePasswordRequest\r\n */\r\n async acquireTokenByUsernamePassword(request: UsernamePasswordRequest): Promise {\r\n this.logger.info(\"acquireTokenByUsernamePassword called\", request.correlationId);\r\n const validRequest: CommonUsernamePasswordRequest = {\r\n ...request,\r\n ... await this.initializeBaseRequest(request)\r\n };\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByUsernamePassword, validRequest.correlationId);\r\n try {\r\n const usernamePasswordClientConfig = await this.buildOauthClientConfiguration(\r\n validRequest.authority,\r\n validRequest.correlationId,\r\n serverTelemetryManager,\r\n undefined,\r\n request.azureCloudOptions\r\n );\r\n const usernamePasswordClient = new UsernamePasswordClient(usernamePasswordClientConfig);\r\n this.logger.verbose(\"Username password client created\", validRequest.correlationId);\r\n return usernamePasswordClient.acquireToken(validRequest);\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(validRequest.correlationId);\r\n }\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the token cache for the application.\r\n */\r\n getTokenCache(): TokenCache {\r\n this.logger.info(\"getTokenCache called\");\r\n return this.tokenCache;\r\n }\r\n\r\n /**\r\n * Validates OIDC state by comparing the user cached state with the state received from the server.\r\n * \r\n * This API is provided for scenarios where you would use OAuth2.0 state parameter to mitigate against\r\n * CSRF attacks.\r\n * For more information about state, visit https://datatracker.ietf.org/doc/html/rfc6819#section-3.6.\r\n * @param state\r\n * @param cachedState\r\n */\r\n protected validateState(state: string, cachedState: string): void {\r\n if(!state) {\r\n throw NodeAuthError.createStateNotFoundError();\r\n }\r\n\r\n if(state !== cachedState) {\r\n throw ClientAuthError.createStateMismatchError();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the logger instance\r\n */\r\n getLogger(): Logger {\r\n return this.logger;\r\n }\r\n\r\n /**\r\n * Replaces the default logger set in configurations with new Logger with new configurations\r\n * @param logger - Logger instance\r\n */\r\n setLogger(logger: Logger): void {\r\n this.logger = logger;\r\n }\r\n\r\n /**\r\n * Builds the common configuration to be passed to the common component based on the platform configurarion\r\n * @param authority - user passed authority in configuration\r\n * @param serverTelemetryManager - initializes servertelemetry if passed\r\n */\r\n protected async buildOauthClientConfiguration(\r\n authority: string,\r\n requestCorrelationId?: string, \r\n serverTelemetryManager?: ServerTelemetryManager,\r\n azureRegionConfiguration?: AzureRegionConfiguration, \r\n azureCloudOptions?: AzureCloudOptions): Promise {\r\n \r\n this.logger.verbose(\"buildOauthClientConfiguration called\", requestCorrelationId);\r\n\r\n // precedence - azureCloudInstance + tenant >> authority and request >> config\r\n const userAzureCloudOptions = azureCloudOptions ? azureCloudOptions : this.config.auth.azureCloudOptions;\r\n\r\n // using null assertion operator as we ensure that all config values have default values in buildConfiguration()\r\n this.logger.verbose(`building oauth client configuration with the authority: ${authority}`, requestCorrelationId);\r\n const discoveredAuthority = await this.createAuthority(authority, azureRegionConfiguration, requestCorrelationId, userAzureCloudOptions);\r\n\r\n serverTelemetryManager?.updateRegionDiscoveryMetadata(discoveredAuthority.regionDiscoveryMetadata);\r\n\r\n const clientConfiguration: ClientConfiguration = {\r\n authOptions: {\r\n clientId: this.config.auth.clientId,\r\n authority: discoveredAuthority,\r\n clientCapabilities: this.config.auth.clientCapabilities\r\n },\r\n loggerOptions: {\r\n logLevel: this.config.system.loggerOptions.logLevel ,\r\n loggerCallback: this.config.system.loggerOptions.loggerCallback ,\r\n piiLoggingEnabled: this.config.system.loggerOptions.piiLoggingEnabled ,\r\n correlationId: requestCorrelationId\r\n },\r\n cacheOptions: {\r\n claimsBasedCachingEnabled: this.config.cache.claimsBasedCachingEnabled,\r\n },\r\n cryptoInterface: this.cryptoProvider,\r\n networkInterface: this.config.system.networkClient,\r\n storageInterface: this.storage,\r\n serverTelemetryManager: serverTelemetryManager,\r\n clientCredentials: {\r\n clientSecret: this.clientSecret,\r\n clientAssertion: this.clientAssertion ? this.getClientAssertion(discoveredAuthority) : undefined,\r\n },\r\n libraryInfo: {\r\n sku: NodeConstants.MSAL_SKU,\r\n version: version,\r\n cpu: process.arch || Constants.EMPTY_STRING,\r\n os: process.platform || Constants.EMPTY_STRING,\r\n },\r\n telemetry: this.config.telemetry,\r\n persistencePlugin: this.config.cache.cachePlugin,\r\n serializableCache: this.tokenCache \r\n };\r\n\r\n return clientConfiguration;\r\n }\r\n\r\n private getClientAssertion(authority: Authority): { assertion: string, assertionType: string } {\r\n return {\r\n assertion: this.clientAssertion.getJwt(this.cryptoProvider, this.config.auth.clientId, authority.tokenEndpoint),\r\n assertionType: NodeConstants.JWT_BEARER_ASSERTION_TYPE\r\n };\r\n }\r\n\r\n /**\r\n * Generates a request with the default scopes & generates a correlationId.\r\n * @param authRequest - BaseAuthRequest for initialization\r\n */\r\n protected async initializeBaseRequest(authRequest: Partial): Promise {\r\n this.logger.verbose(\"initializeRequestScopes called\", authRequest.correlationId);\r\n // Default authenticationScheme to Bearer, log that POP isn't supported yet\r\n if (authRequest.authenticationScheme && authRequest.authenticationScheme === AuthenticationScheme.POP) {\r\n this.logger.verbose(\"Authentication Scheme 'pop' is not supported yet, setting Authentication Scheme to 'Bearer' for request\", authRequest.correlationId);\r\n }\r\n\r\n authRequest.authenticationScheme = AuthenticationScheme.BEARER;\r\n\r\n // Set requested claims hash if claims-based caching is enabled and claims were requested\r\n if (this.config.cache.claimsBasedCachingEnabled &&\r\n authRequest.claims &&\r\n // Checks for empty stringified object \"{}\" which doesn't qualify as requested claims\r\n !StringUtils.isEmptyObj(authRequest.claims)) {\r\n authRequest.requestedClaimsHash = await this.cryptoProvider.hashString(authRequest.claims);\r\n }\r\n\r\n return {\r\n ...authRequest,\r\n scopes: [...((authRequest && authRequest.scopes) || []), ...OIDC_DEFAULT_SCOPES],\r\n correlationId: authRequest && authRequest.correlationId || this.cryptoProvider.createNewGuid(),\r\n authority: authRequest.authority || this.config.auth.authority\r\n };\r\n }\r\n\r\n /**\r\n * Initializes the server telemetry payload\r\n * @param apiId - Id for a specific request\r\n * @param correlationId - GUID\r\n * @param forceRefresh - boolean to indicate network call\r\n */\r\n protected initializeServerTelemetryManager(apiId: number, correlationId: string, forceRefresh?: boolean): ServerTelemetryManager {\r\n const telemetryPayload: ServerTelemetryRequest = {\r\n clientId: this.config.auth.clientId,\r\n correlationId: correlationId,\r\n apiId: apiId,\r\n forceRefresh: forceRefresh || false\r\n };\r\n\r\n return new ServerTelemetryManager(telemetryPayload, this.storage);\r\n }\r\n\r\n /**\r\n * Create authority instance. If authority not passed in request, default to authority set on the application\r\n * object. If no authority set in application object, then default to common authority.\r\n * @param authorityString - authority from user configuration\r\n */\r\n private async createAuthority(authorityString: string, azureRegionConfiguration?: AzureRegionConfiguration, requestCorrelationId?: string, azureCloudOptions?: AzureCloudOptions): Promise {\r\n this.logger.verbose(\"createAuthority called\", requestCorrelationId);\r\n\r\n // build authority string based on auth params - azureCloudInstance is prioritized if provided\r\n const authorityUrl = Authority.generateAuthority(authorityString, azureCloudOptions);\r\n\r\n const authorityOptions: AuthorityOptions = {\r\n protocolMode: this.config.auth.protocolMode,\r\n knownAuthorities: this.config.auth.knownAuthorities,\r\n cloudDiscoveryMetadata: this.config.auth.cloudDiscoveryMetadata,\r\n authorityMetadata: this.config.auth.authorityMetadata,\r\n azureRegionConfiguration,\r\n skipAuthorityMetadataCache: this.config.auth.skipAuthorityMetadataCache,\r\n };\r\n\r\n return await AuthorityFactory.createDiscoveredInstance(authorityUrl, this.config.system.networkClient, this.storage, authorityOptions, this.logger);\r\n }\r\n\r\n /**\r\n * Clear the cache\r\n */\r\n clearCache(): void {\r\n this.storage.clear();\r\n }\r\n}\r\n","/* eslint-disable header/header */\r\nexport const name = \"@azure/msal-node\";\r\nexport const version = \"1.18.4\";\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Constants as CommonConstants, ServerAuthorizationCodeResponse, UrlString } from \"@azure/msal-common\";\r\nimport { createServer, IncomingMessage, Server, ServerResponse } from \"http\";\r\nimport { NodeAuthError } from \"../error/NodeAuthError\";\r\nimport { Constants, HttpStatus, LOOPBACK_SERVER_CONSTANTS } from \"../utils/Constants\";\r\nimport { ILoopbackClient } from \"./ILoopbackClient\";\r\n\r\nexport class LoopbackClient implements ILoopbackClient {\r\n private server: Server;\r\n\r\n /**\r\n * Spins up a loopback server which returns the server response when the localhost redirectUri is hit\r\n * @param successTemplate\r\n * @param errorTemplate\r\n * @returns\r\n */\r\n async listenForAuthCode(successTemplate?: string, errorTemplate?: string): Promise {\r\n if (!!this.server) {\r\n throw NodeAuthError.createLoopbackServerAlreadyExistsError();\r\n }\r\n\r\n const authCodeListener = new Promise((resolve, reject) => {\r\n this.server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\r\n const url = req.url;\r\n if (!url) {\r\n res.end(errorTemplate || \"Error occurred loading redirectUrl\");\r\n reject(NodeAuthError.createUnableToLoadRedirectUrlError());\r\n return;\r\n } else if (url === CommonConstants.FORWARD_SLASH) {\r\n res.end(successTemplate || \"Auth code was successfully acquired. You can close this window now.\");\r\n return;\r\n }\r\n\r\n const authCodeResponse = UrlString.getDeserializedQueryString(url);\r\n if (authCodeResponse.code) {\r\n const redirectUri = await this.getRedirectUri();\r\n res.writeHead(HttpStatus.REDIRECT, { location: redirectUri }); // Prevent auth code from being saved in the browser history\r\n res.end();\r\n }\r\n resolve(authCodeResponse);\r\n });\r\n this.server.listen(0); // Listen on any available port\r\n });\r\n\r\n // Wait for server to be listening\r\n await new Promise((resolve) => {\r\n let ticks = 0;\r\n const id = setInterval(() => {\r\n if ((LOOPBACK_SERVER_CONSTANTS.TIMEOUT_MS / LOOPBACK_SERVER_CONSTANTS.INTERVAL_MS) < ticks) {\r\n throw NodeAuthError.createLoopbackServerTimeoutError();\r\n }\r\n\r\n if (this.server.listening) {\r\n clearInterval(id);\r\n resolve();\r\n }\r\n ticks++;\r\n }, LOOPBACK_SERVER_CONSTANTS.INTERVAL_MS);\r\n });\r\n\r\n return authCodeListener;\r\n }\r\n\r\n /**\r\n * Get the port that the loopback server is running on\r\n * @returns\r\n */\r\n getRedirectUri(): string {\r\n if (!this.server) {\r\n throw NodeAuthError.createNoLoopbackServerExistsError();\r\n }\r\n\r\n const address = this.server.address();\r\n if (!address || typeof address === \"string\" || !address.port) {\r\n this.closeServer();\r\n throw NodeAuthError.createInvalidLoopbackAddressTypeError();\r\n }\r\n\r\n const port = address && address.port;\r\n\r\n return `${Constants.HTTP_PROTOCOL}${Constants.LOCALHOST}:${port}`;\r\n }\r\n\r\n /**\r\n * Close the loopback server\r\n */\r\n closeServer(): void {\r\n if (!!this.server) {\r\n this.server.close();\r\n }\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { JwtHeader, sign } from \"jsonwebtoken\";\r\nimport { TimeUtils, ClientAuthError, Constants } from \"@azure/msal-common\";\r\nimport { CryptoProvider } from \"../crypto/CryptoProvider\";\r\nimport { EncodingUtils } from \"../utils/EncodingUtils\";\r\nimport { JwtConstants } from \"../utils/Constants\";\r\n\r\n/**\r\n * Client assertion of type jwt-bearer used in confidential client flows\r\n * @public\r\n */\r\nexport class ClientAssertion {\r\n\r\n private jwt: string;\r\n private privateKey: string;\r\n private thumbprint: string;\r\n private expirationTime: number;\r\n private issuer: string;\r\n private jwtAudience: string;\r\n private publicCertificate: Array;\r\n\r\n /**\r\n * Initialize the ClientAssertion class from the clientAssertion passed by the user\r\n * @param assertion - refer https://tools.ietf.org/html/rfc7521\r\n */\r\n public static fromAssertion(assertion: string): ClientAssertion {\r\n const clientAssertion = new ClientAssertion();\r\n clientAssertion.jwt = assertion;\r\n return clientAssertion;\r\n }\r\n\r\n /**\r\n * Initialize the ClientAssertion class from the certificate passed by the user\r\n * @param thumbprint - identifier of a certificate\r\n * @param privateKey - secret key\r\n * @param publicCertificate - electronic document provided to prove the ownership of the public key\r\n */\r\n public static fromCertificate(thumbprint: string, privateKey: string, publicCertificate?: string): ClientAssertion {\r\n const clientAssertion = new ClientAssertion();\r\n clientAssertion.privateKey = privateKey;\r\n clientAssertion.thumbprint = thumbprint;\r\n if (publicCertificate) {\r\n clientAssertion.publicCertificate = this.parseCertificate(publicCertificate);\r\n }\r\n return clientAssertion;\r\n }\r\n\r\n /**\r\n * Update JWT for certificate based clientAssertion, if passed by the user, uses it as is\r\n * @param cryptoProvider - library's crypto helper\r\n * @param issuer - iss claim\r\n * @param jwtAudience - aud claim\r\n */\r\n public getJwt(cryptoProvider: CryptoProvider, issuer: string, jwtAudience: string): string {\r\n // if assertion was created from certificate, check if jwt is expired and create new one.\r\n if (this.privateKey && this.thumbprint) {\r\n\r\n if (this.jwt && !this.isExpired() && issuer === this.issuer && jwtAudience === this.jwtAudience) {\r\n return this.jwt;\r\n }\r\n\r\n return this.createJwt(cryptoProvider, issuer, jwtAudience);\r\n }\r\n\r\n /*\r\n * if assertion was created by caller, then we just append it. It is up to the caller to\r\n * ensure that it contains necessary claims and that it is not expired.\r\n */\r\n if (this.jwt) {\r\n return this.jwt;\r\n }\r\n\r\n throw ClientAuthError.createInvalidAssertionError();\r\n }\r\n\r\n /**\r\n * JWT format and required claims specified: https://tools.ietf.org/html/rfc7523#section-3\r\n */\r\n private createJwt(cryptoProvider: CryptoProvider, issuer: string, jwtAudience: string): string {\r\n\r\n this.issuer = issuer;\r\n this.jwtAudience = jwtAudience;\r\n const issuedAt = TimeUtils.nowSeconds();\r\n this.expirationTime = issuedAt + 600;\r\n\r\n const header: JwtHeader = {\r\n alg: JwtConstants.RSA_256,\r\n x5t: EncodingUtils.base64EncodeUrl(this.thumbprint, \"hex\")\r\n };\r\n\r\n if (this.publicCertificate) {\r\n Object.assign(header, {\r\n x5c: this.publicCertificate\r\n } as Partial);\r\n }\r\n\r\n const payload = {\r\n [JwtConstants.AUDIENCE]: this.jwtAudience,\r\n [JwtConstants.EXPIRATION_TIME]: this.expirationTime,\r\n [JwtConstants.ISSUER]: this.issuer,\r\n [JwtConstants.SUBJECT]: this.issuer,\r\n [JwtConstants.NOT_BEFORE]: issuedAt,\r\n [JwtConstants.JWT_ID]: cryptoProvider.createNewGuid()\r\n };\r\n\r\n this.jwt = sign(payload, this.privateKey, { header });\r\n return this.jwt;\r\n }\r\n\r\n /**\r\n * Utility API to check expiration\r\n */\r\n private isExpired(): boolean {\r\n return this.expirationTime < TimeUtils.nowSeconds();\r\n }\r\n\r\n /**\r\n * Extracts the raw certs from a given certificate string and returns them in an array.\r\n * @param publicCertificate - electronic document provided to prove the ownership of the public key\r\n */\r\n public static parseCertificate(publicCertificate: string): Array {\r\n /**\r\n * This is regex to identify the certs in a given certificate string.\r\n * We want to look for the contents between the BEGIN and END certificate strings, without the associated newlines.\r\n * The information in parens \"(.+?)\" is the capture group to represent the cert we want isolated.\r\n * \".\" means any string character, \"+\" means match 1 or more times, and \"?\" means the shortest match.\r\n * The \"g\" at the end of the regex means search the string globally, and the \"s\" enables the \".\" to match newlines.\r\n */\r\n const regexToFindCerts = /-----BEGIN CERTIFICATE-----\\r*\\n(.+?)\\r*\\n-----END CERTIFICATE-----/gs;\r\n const certs: string[] = [];\r\n\r\n let matches;\r\n while ((matches = regexToFindCerts.exec(publicCertificate)) !== null) {\r\n // matches[1] represents the first parens capture group in the regex.\r\n certs.push(matches[1].replace(/\\r*\\n/g, Constants.EMPTY_STRING));\r\n }\r\n\r\n return certs;\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ClientApplication } from \"./ClientApplication\";\r\nimport { Configuration } from \"../config/Configuration\";\r\nimport { ClientAssertion } from \"./ClientAssertion\";\r\nimport { Constants as NodeConstants, ApiId, REGION_ENVIRONMENT_VARIABLE } from \"../utils/Constants\";\r\nimport {\r\n ClientCredentialClient,\r\n OnBehalfOfClient,\r\n CommonClientCredentialRequest,\r\n CommonOnBehalfOfRequest,\r\n AuthenticationResult,\r\n StringUtils,\r\n ClientAuthError,\r\n AzureRegionConfiguration,\r\n AuthError,\r\n Constants,\r\n IAppTokenProvider,\r\n OIDC_DEFAULT_SCOPES\r\n} from \"@azure/msal-common\";\r\nimport { IConfidentialClientApplication } from \"./IConfidentialClientApplication\";\r\nimport { OnBehalfOfRequest } from \"../request/OnBehalfOfRequest\";\r\nimport { ClientCredentialRequest } from \"../request/ClientCredentialRequest\";\r\n\r\n/**\r\n * This class is to be used to acquire tokens for confidential client applications (webApp, webAPI). Confidential client applications\r\n * will configure application secrets, client certificates/assertions as applicable\r\n * @public\r\n */\r\nexport class ConfidentialClientApplication extends ClientApplication implements IConfidentialClientApplication {\r\n private appTokenProvider?: IAppTokenProvider;\r\n\r\n /**\r\n * Constructor for the ConfidentialClientApplication\r\n *\r\n * Required attributes in the Configuration object are:\r\n * - clientID: the application ID of your application. You can obtain one by registering your application with our application registration portal\r\n * - authority: the authority URL for your application.\r\n * - client credential: Must set either client secret, certificate, or assertion for confidential clients. You can obtain a client secret from the application registration portal.\r\n *\r\n * In Azure AD, authority is a URL indicating of the form https://login.microsoftonline.com/\\{Enter_the_Tenant_Info_Here\\}.\r\n * If your application supports Accounts in one organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).\r\n * If your application supports Accounts in any organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with organizations.\r\n * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace \"Enter_the_Tenant_Info_Here\" value with common.\r\n * To restrict support to Personal Microsoft accounts only, replace \"Enter_the_Tenant_Info_Here\" value with consumers.\r\n *\r\n * In Azure B2C, authority is of the form https://\\{instance\\}/tfp/\\{tenant\\}/\\{policyName\\}/\r\n * Full B2C functionality will be available in this library in future versions.\r\n *\r\n * @param Configuration - configuration object for the MSAL ConfidentialClientApplication instance\r\n */\r\n constructor(configuration: Configuration) {\r\n super(configuration);\r\n this.setClientCredential(this.config);\r\n this.appTokenProvider = undefined;\r\n }\r\n\r\n /** \r\n * This extensibility point only works for the client_credential flow, i.e. acquireTokenByClientCredential and\r\n * is meant for Azure SDK to enhance Managed Identity support.\r\n * \r\n * @param IAppTokenProvider - Extensibility interface, which allows the app developer to return a token from a custom source. \r\n */\r\n SetAppTokenProvider(provider: IAppTokenProvider): void {\r\n this.appTokenProvider = provider;\r\n }\r\n\r\n /**\r\n * Acquires tokens from the authority for the application (not for an end user).\r\n */\r\n public async acquireTokenByClientCredential(request: ClientCredentialRequest): Promise {\r\n this.logger.info(\"acquireTokenByClientCredential called\", request.correlationId);\r\n\r\n // If there is a client assertion present in the request, it overrides the one present in the client configuration\r\n let clientAssertion;\r\n if (request.clientAssertion) {\r\n clientAssertion = {\r\n assertion: request.clientAssertion,\r\n assertionType: NodeConstants.JWT_BEARER_ASSERTION_TYPE\r\n };\r\n }\r\n\r\n const baseRequest = await this.initializeBaseRequest(request);\r\n\r\n // valid base request should not contain oidc scopes in this grant type\r\n const validBaseRequest = {\r\n ...baseRequest,\r\n scopes: baseRequest.scopes.filter((scope: string) => !OIDC_DEFAULT_SCOPES.includes(scope))\r\n };\r\n\r\n const validRequest: CommonClientCredentialRequest = {\r\n ...request,\r\n ...validBaseRequest,\r\n clientAssertion\r\n };\r\n\r\n const azureRegionConfiguration: AzureRegionConfiguration = {\r\n azureRegion: validRequest.azureRegion,\r\n environmentRegion: process.env[REGION_ENVIRONMENT_VARIABLE]\r\n };\r\n\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByClientCredential, validRequest.correlationId, validRequest.skipCache);\r\n try {\r\n const clientCredentialConfig = await this.buildOauthClientConfiguration(\r\n validRequest.authority,\r\n validRequest.correlationId,\r\n serverTelemetryManager,\r\n azureRegionConfiguration,\r\n request.azureCloudOptions\r\n );\r\n const clientCredentialClient = new ClientCredentialClient(clientCredentialConfig, this.appTokenProvider);\r\n this.logger.verbose(\"Client credential client created\", validRequest.correlationId);\r\n return clientCredentialClient.acquireToken(validRequest);\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(validRequest.correlationId);\r\n }\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Acquires tokens from the authority for the application.\r\n *\r\n * Used in scenarios where the current app is a middle-tier service which was called with a token\r\n * representing an end user. The current app can use the token (oboAssertion) to request another\r\n * token to access downstream web API, on behalf of that user.\r\n *\r\n * The current middle-tier app has no user interaction to obtain consent.\r\n * See how to gain consent upfront for your middle-tier app from this article.\r\n * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#gaining-consent-for-the-middle-tier-application\r\n */\r\n public async acquireTokenOnBehalfOf(request: OnBehalfOfRequest): Promise {\r\n this.logger.info(\"acquireTokenOnBehalfOf called\", request.correlationId);\r\n const validRequest: CommonOnBehalfOfRequest = {\r\n ...request,\r\n ... await this.initializeBaseRequest(request)\r\n };\r\n try {\r\n const onBehalfOfConfig = await this.buildOauthClientConfiguration(\r\n validRequest.authority,\r\n validRequest.correlationId,\r\n undefined,\r\n undefined,\r\n request.azureCloudOptions\r\n );\r\n const oboClient = new OnBehalfOfClient(onBehalfOfConfig);\r\n this.logger.verbose(\"On behalf of client created\", validRequest.correlationId);\r\n return oboClient.acquireToken(validRequest);\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(validRequest.correlationId);\r\n }\r\n throw e;\r\n }\r\n }\r\n\r\n private setClientCredential(configuration: Configuration): void {\r\n const clientSecretNotEmpty = !StringUtils.isEmpty(configuration.auth.clientSecret);\r\n const clientAssertionNotEmpty = !StringUtils.isEmpty(configuration.auth.clientAssertion);\r\n const certificate = configuration.auth.clientCertificate || {\r\n thumbprint: Constants.EMPTY_STRING,\r\n privateKey: Constants.EMPTY_STRING\r\n };\r\n const certificateNotEmpty = !StringUtils.isEmpty(certificate.thumbprint) || !StringUtils.isEmpty(certificate.privateKey);\r\n\r\n /*\r\n * If app developer configures this callback, they don't need a credential\r\n * i.e. AzureSDK can get token from Managed Identity without a cert / secret\r\n */\r\n if (this.appTokenProvider) {\r\n return;\r\n }\r\n\r\n // Check that at most one credential is set on the application\r\n if (\r\n clientSecretNotEmpty && clientAssertionNotEmpty ||\r\n clientAssertionNotEmpty && certificateNotEmpty ||\r\n clientSecretNotEmpty && certificateNotEmpty) {\r\n throw ClientAuthError.createInvalidCredentialError();\r\n }\r\n\r\n if (configuration.auth.clientSecret) {\r\n this.clientSecret = configuration.auth.clientSecret;\r\n return;\r\n }\r\n\r\n if (configuration.auth.clientAssertion) {\r\n this.clientAssertion = ClientAssertion.fromAssertion(configuration.auth.clientAssertion);\r\n return;\r\n }\r\n\r\n if (!certificateNotEmpty) {\r\n throw ClientAuthError.createInvalidCredentialError();\r\n } else {\r\n this.clientAssertion = ClientAssertion.fromCertificate(certificate.thumbprint, certificate.privateKey, configuration.auth.clientCertificate?.x5c);\r\n }\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AccountEntity, ICachePlugin, TokenCacheContext } from \"@azure/msal-common\";\r\nimport { TokenCache } from \"../TokenCache\";\r\nimport { IPartitionManager } from \"./IPartitionManager\";\r\nimport { ICacheClient } from \"./ICacheClient\";\r\n\r\nexport class DistributedCachePlugin implements ICachePlugin {\r\n private client: ICacheClient;\r\n private partitionManager: IPartitionManager;\r\n\r\n constructor(client: ICacheClient, partitionManager: IPartitionManager) {\r\n this.client = client;\r\n this.partitionManager = partitionManager;\r\n }\r\n \r\n public async beforeCacheAccess(cacheContext: TokenCacheContext): Promise {\r\n const partitionKey = await this.partitionManager.getKey();\r\n const cacheData = await this.client.get(partitionKey);\r\n cacheContext.tokenCache.deserialize(cacheData);\r\n }\r\n \r\n public async afterCacheAccess(cacheContext: TokenCacheContext): Promise {\r\n if (cacheContext.cacheHasChanged) {\r\n const kvStore = (cacheContext.tokenCache as TokenCache).getKVStore();\r\n const accountEntities = Object.values(kvStore).filter(value => AccountEntity.isAccountEntity(value as object));\r\n\r\n if (accountEntities.length > 0) {\r\n const accountEntity = accountEntities[0] as AccountEntity;\r\n const partitionKey = await this.partitionManager.extractKey(accountEntity);\r\n \r\n await this.client.set(partitionKey, cacheContext.tokenCache.serialize()); \r\n }\r\n }\r\n }\r\n}\r\n","/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ApiId, Constants } from \"../utils/Constants\";\r\nimport {\r\n DeviceCodeClient,\r\n AuthenticationResult,\r\n CommonDeviceCodeRequest,\r\n AuthError,\r\n ResponseMode,\r\n OIDC_DEFAULT_SCOPES,\r\n CodeChallengeMethodValues,\r\n Constants as CommonConstants,\r\n ServerError,\r\n NativeRequest,\r\n NativeSignOutRequest,\r\n AccountInfo,\r\n INativeBrokerPlugin\r\n} from \"@azure/msal-common\";\r\nimport { Configuration } from \"../config/Configuration\";\r\nimport { ClientApplication } from \"./ClientApplication\";\r\nimport { IPublicClientApplication } from \"./IPublicClientApplication\";\r\nimport { DeviceCodeRequest } from \"../request/DeviceCodeRequest\";\r\nimport { AuthorizationUrlRequest } from \"../request/AuthorizationUrlRequest\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest\";\r\nimport { InteractiveRequest } from \"../request/InteractiveRequest\";\r\nimport { NodeAuthError } from \"../error/NodeAuthError\";\r\nimport { LoopbackClient } from \"../network/LoopbackClient\";\r\nimport { SilentFlowRequest } from \"../request/SilentFlowRequest\";\r\nimport { SignOutRequest } from \"../request/SignOutRequest\";\r\nimport { ILoopbackClient } from \"../network/ILoopbackClient\";\r\n\r\n/**\r\n * This class is to be used to acquire tokens for public client applications (desktop, mobile). Public client applications\r\n * are not trusted to safely store application secrets, and therefore can only request tokens in the name of an user.\r\n * @public\r\n */\r\nexport class PublicClientApplication extends ClientApplication implements IPublicClientApplication {\r\n private nativeBrokerPlugin?: INativeBrokerPlugin;\r\n /**\r\n * Important attributes in the Configuration object for auth are:\r\n * - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal.\r\n * - authority: the authority URL for your application.\r\n *\r\n * AAD authorities are of the form https://login.microsoftonline.com/\\{Enter_the_Tenant_Info_Here\\}.\r\n * - If your application supports Accounts in one organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).\r\n * - If your application supports Accounts in any organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with organizations.\r\n * - If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace \"Enter_the_Tenant_Info_Here\" value with common.\r\n * - To restrict support to Personal Microsoft accounts only, replace \"Enter_the_Tenant_Info_Here\" value with consumers.\r\n *\r\n * Azure B2C authorities are of the form https://\\{instance\\}/\\{tenant\\}/\\{policy\\}. Each policy is considered\r\n * its own authority. You will have to set the all of the knownAuthorities at the time of the client application\r\n * construction.\r\n *\r\n * ADFS authorities are of the form https://\\{instance\\}/adfs.\r\n */\r\n constructor(configuration: Configuration) {\r\n super(configuration);\r\n if (this.config.broker.nativeBrokerPlugin) {\r\n if (this.config.broker.nativeBrokerPlugin.isBrokerAvailable) {\r\n this.nativeBrokerPlugin = this.config.broker.nativeBrokerPlugin;\r\n this.nativeBrokerPlugin.setLogger(this.config.system.loggerOptions); \r\n } else {\r\n this.logger.warning(\"NativeBroker implementation was provided but the broker is unavailable.\");\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Acquires a token from the authority using OAuth2.0 device code flow.\r\n * This flow is designed for devices that do not have access to a browser or have input constraints.\r\n * The authorization server issues a DeviceCode object with a verification code, an end-user code,\r\n * and the end-user verification URI. The DeviceCode object is provided through a callback, and the end-user should be\r\n * instructed to use another device to navigate to the verification URI to input credentials.\r\n * Since the client cannot receive incoming requests, it polls the authorization server repeatedly\r\n * until the end-user completes input of credentials.\r\n */\r\n public async acquireTokenByDeviceCode(request: DeviceCodeRequest): Promise {\r\n this.logger.info(\"acquireTokenByDeviceCode called\", request.correlationId);\r\n const validRequest: CommonDeviceCodeRequest = Object.assign(request, await this.initializeBaseRequest(request));\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByDeviceCode, validRequest.correlationId);\r\n try {\r\n const deviceCodeConfig = await this.buildOauthClientConfiguration(\r\n validRequest.authority,\r\n validRequest.correlationId,\r\n serverTelemetryManager,\r\n undefined,\r\n request.azureCloudOptions\r\n );\r\n const deviceCodeClient = new DeviceCodeClient(deviceCodeConfig);\r\n this.logger.verbose(\"Device code client created\", validRequest.correlationId);\r\n return deviceCodeClient.acquireToken(validRequest);\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(validRequest.correlationId);\r\n }\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Acquires a token interactively via the browser by requesting an authorization code then exchanging it for a token.\r\n */\r\n async acquireTokenInteractive(request: InteractiveRequest): Promise {\r\n const correlationId = request.correlationId || this.cryptoProvider.createNewGuid();\r\n this.logger.trace(\"acquireTokenInteractive called\", correlationId);\r\n const { openBrowser, successTemplate, errorTemplate, windowHandle, loopbackClient: customLoopbackClient, ...remainingProperties } = request;\r\n\r\n if (this.nativeBrokerPlugin) {\r\n const brokerRequest: NativeRequest = {\r\n ...remainingProperties,\r\n clientId: this.config.auth.clientId,\r\n scopes: request.scopes || OIDC_DEFAULT_SCOPES,\r\n redirectUri: `${Constants.HTTP_PROTOCOL}${Constants.LOCALHOST}`,\r\n authority: request.authority || this.config.auth.authority,\r\n correlationId: correlationId,\r\n extraParameters: {\r\n ...remainingProperties.extraQueryParameters,\r\n ...remainingProperties.tokenQueryParameters\r\n },\r\n accountId: remainingProperties.account?.nativeAccountId\r\n };\r\n return this.nativeBrokerPlugin.acquireTokenInteractive(brokerRequest, windowHandle);\r\n }\r\n\r\n const { verifier, challenge } = await this.cryptoProvider.generatePkceCodes();\r\n\r\n const loopbackClient: ILoopbackClient = customLoopbackClient || new LoopbackClient();\r\n\r\n try {\r\n const authCodeListener = loopbackClient.listenForAuthCode(successTemplate, errorTemplate);\r\n const redirectUri = loopbackClient.getRedirectUri();\r\n \r\n const validRequest: AuthorizationUrlRequest = {\r\n ...remainingProperties,\r\n correlationId: correlationId,\r\n scopes: request.scopes || OIDC_DEFAULT_SCOPES,\r\n redirectUri: redirectUri,\r\n responseMode: ResponseMode.QUERY,\r\n codeChallenge: challenge,\r\n codeChallengeMethod: CodeChallengeMethodValues.S256\r\n };\r\n \r\n const authCodeUrl = await this.getAuthCodeUrl(validRequest);\r\n await openBrowser(authCodeUrl);\r\n const authCodeResponse = await authCodeListener.finally(() => {\r\n loopbackClient.closeServer();\r\n });\r\n \r\n if (authCodeResponse.error) {\r\n throw new ServerError(authCodeResponse.error, authCodeResponse.error_description, authCodeResponse.suberror);\r\n } else if (!authCodeResponse.code) {\r\n throw NodeAuthError.createNoAuthCodeInResponseError();\r\n }\r\n \r\n const clientInfo = authCodeResponse.client_info;\r\n const tokenRequest: AuthorizationCodeRequest = {\r\n code: authCodeResponse.code,\r\n codeVerifier: verifier,\r\n clientInfo: clientInfo || CommonConstants.EMPTY_STRING,\r\n ...validRequest\r\n };\r\n return this.acquireTokenByCode(tokenRequest);\r\n } catch (e) {\r\n loopbackClient.closeServer();\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a token retrieved either from the cache or by exchanging the refresh token for a fresh access token. If brokering is enabled the token request will be serviced by the broker.\r\n * @param request \r\n * @returns \r\n */\r\n async acquireTokenSilent(request: SilentFlowRequest): Promise {\r\n const correlationId = request.correlationId || this.cryptoProvider.createNewGuid();\r\n this.logger.trace(\"acquireTokenSilent called\", correlationId);\r\n\r\n if (this.nativeBrokerPlugin) {\r\n const brokerRequest: NativeRequest = {\r\n ...request,\r\n clientId: this.config.auth.clientId,\r\n scopes: request.scopes || OIDC_DEFAULT_SCOPES,\r\n redirectUri: `${Constants.HTTP_PROTOCOL}${Constants.LOCALHOST}`,\r\n authority: request.authority || this.config.auth.authority,\r\n correlationId: correlationId,\r\n extraParameters: request.tokenQueryParameters,\r\n accountId: request.account.nativeAccountId,\r\n forceRefresh: request.forceRefresh || false\r\n };\r\n return this.nativeBrokerPlugin.acquireTokenSilent(brokerRequest);\r\n }\r\n\r\n return super.acquireTokenSilent(request);\r\n }\r\n\r\n /**\r\n * Removes cache artifacts associated with the given account\r\n * @param request \r\n * @returns \r\n */\r\n async signOut(request: SignOutRequest): Promise {\r\n if (this.nativeBrokerPlugin && request.account.nativeAccountId) {\r\n const signoutRequest: NativeSignOutRequest = {\r\n clientId: this.config.auth.clientId,\r\n accountId: request.account.nativeAccountId,\r\n correlationId: request.correlationId || this.cryptoProvider.createNewGuid()\r\n };\r\n await this.nativeBrokerPlugin.signOut(signoutRequest);\r\n }\r\n\r\n await this.getTokenCache().removeAccount(request.account);\r\n }\r\n\r\n /**\r\n * Returns all cached accounts for this application. If brokering is enabled this request will be serviced by the broker.\r\n * @returns \r\n */\r\n async getAllAccounts(): Promise {\r\n if (this.nativeBrokerPlugin) {\r\n const correlationId = this.cryptoProvider.createNewGuid();\r\n return this.nativeBrokerPlugin.getAllAccounts(this.config.auth.clientId, correlationId);\r\n }\r\n\r\n return this.getTokenCache().getAllAccounts();\r\n }\r\n}\r\n"],"names":["HttpMethod","HttpStatus","ProxyStatus","CharSet","ApiId","NetworkUtils","[object Object]","headers","body","statusCode","status","url","options","protocol","hostname","startsWith","slice","hash","search","pathname","path","href","port","Number","username","password","auth","decodeURIComponent","HttpClient","constructor","proxyUrl","customAgentOptions","this","networkRequestViaProxy","GET","networkRequestViaHttps","cancellationToken","POST","destinationUrlString","proxyUrlString","httpMethod","agentOptions","timeout","destinationUrl","URL","tunnelRequestOptions","host","method","Object","keys","length","agent","http","Agent","postRequestStringContent","outgoingRequestString","toUpperCase","Promise","resolve","reject","request","on","destroy","Error","end","response","socket","proxyStatusCode","SERVER_ERROR","SUCCESS_RANGE_START","SUCCESS_RANGE_END","statusMessage","setTimeout","write","data","chunk","push","dataStringArray","Buffer","concat","toString","split","httpStatusCode","parseInt","join","headersArray","entries","Map","forEach","header","headerKeyValue","RegExp","headerKey","headerValue","object","JSON","parse","e","set","fromEntries","networkResponse","getNetworkResponse","parseBody","urlString","isPostRequest","customOptions","urlToHttpOptions","https","Content-Length","parsedBody","error","errorType","errorDescriptionHelper","CLIENT_ERROR_RANGE_START","CLIENT_ERROR_RANGE_END","SERVER_ERROR_RANGE_START","SERVER_ERROR_RANGE_END","error_description","stringify","DEFAULT_AUTH_OPTIONS","clientId","Constants","EMPTY_STRING","authority","DEFAULT_AUTHORITY","clientSecret","clientAssertion","clientCertificate","thumbprint","privateKey","x5c","knownAuthorities","cloudDiscoveryMetadata","authorityMetadata","clientCapabilities","protocolMode","ProtocolMode","AAD","azureCloudOptions","azureCloudInstance","AzureCloudInstance","None","tenant","skipAuthorityMetadataCache","DEFAULT_CACHE_OPTIONS","claimsBasedCachingEnabled","DEFAULT_LOGGER_OPTIONS","loggerCallback","piiLoggingEnabled","logLevel","LogLevel","Info","DEFAULT_SYSTEM_OPTIONS","loggerOptions","networkClient","DEFAULT_TELEMETRY_OPTIONS","application","appName","appVersion","buildAppConfiguration","broker","cache","system","telemetry","systemOptions","GuidGenerator","generateGuid","uuidv4","isGuid","guid","test","EncodingUtils","str","encoding","from","base64Encode","replace","base64Str","base64Decode","HashUtils","sha256","buffer","crypto","createHash","update","digest","PkceGenerator","hashUtils","verifier","generateCodeVerifier","challenge","generateCodeChallengeFromVerifier","charArr","maxNumber","byte","randomBytes","base64EncodeUrl","codeVerifier","CryptoProvider","pkceGenerator","guidGenerator","createNewGuid","input","generatePkceCodes","getPublicKeyThumbprint","removeTokenBindingKey","clearKeystore","signJwt","plainText","Deserializer","jsonFile","StringUtils","isEmpty","accounts","accountObjects","map","key","serializedAcc","mappedAcc","homeAccountId","home_account_id","environment","realm","localAccountId","local_account_id","authorityType","authority_type","name","clientInfo","client_info","lastModificationTime","last_modification_time","lastModificationApp","last_modification_app","account","AccountEntity","CacheManager","toObject","idTokens","idObjects","serializedIdT","mappedIdT","credentialType","credential_type","client_id","secret","idToken","IdTokenEntity","accessTokens","atObjects","serializedAT","mappedAT","target","cachedAt","cached_at","expiresOn","expires_on","extendedExpiresOn","extended_expires_on","refreshOn","refresh_on","keyId","key_id","tokenType","token_type","requestedClaims","requestedClaimsHash","userAssertionHash","accessToken","AccessTokenEntity","refreshTokens","rtObjects","serializedRT","mappedRT","familyId","family_id","refreshToken","RefreshTokenEntity","appMetadata","appMetadataObjects","serializedAmdt","mappedAmd","amd","AppMetadataEntity","jsonCache","Account","deserializeAccounts","IdToken","deserializeIdTokens","AccessToken","deserializeAccessTokens","RefreshToken","deserializeRefreshTokens","AppMetadata","deserializeAppMetadata","Serializer","accCache","accountEntity","idTCache","idTEntity","atCache","atEntity","rtCache","rtEntity","amdtCache","amdtEntity","inMemCache","serializeAccounts","serializeIdTokens","serializeAccessTokens","serializeRefreshTokens","serializeAppMetadata","NodeStorage","logger","cryptoImpl","super","registerChangeEmitter","func","changeEmitters","emitChange","call","cacheToInMemoryCache","inMemoryCache","inMemoryCacheToCache","getCache","getInMemoryCache","trace","setInMemoryCache","setCache","getItem","tracePii","setItem","value","getAccountKeys","getTokenKeys","getAccount","accountKey","isAccountEntity","setAccount","generateAccountKey","getIdTokenCredential","idTokenKey","isIdTokenEntity","setIdTokenCredential","generateCredentialKey","getAccessTokenCredential","accessTokenKey","isAccessTokenEntity","setAccessTokenCredential","getRefreshTokenCredential","refreshTokenKey","isRefreshTokenEntity","setRefreshTokenCredential","getAppMetadata","appMetadataKey","isAppMetadataEntity","setAppMetadata","generateAppMetadataKey","getServerTelemetry","serverTelemetrykey","serverTelemetryEntity","ServerTelemetryEntity","isServerTelemetryEntity","setServerTelemetry","serverTelemetryKey","serverTelemetry","getAuthorityMetadata","authorityMetadataEntity","AuthorityMetadataEntity","isAuthorityMetadataEntity","getAuthorityMetadataKeys","getKeys","filter","isAuthorityMetadata","setAuthorityMetadata","metadata","getThrottlingCache","throttlingCacheKey","throttlingCache","ThrottlingEntity","isThrottlingEntity","setThrottlingCache","removeItem","result","containsKey","includes","deserializeAllCache","deserializeJSONBlob","serializeAllCache","updateCredentialCacheKey","currentCacheKey","credential","updatedCacheKey","cacheItem","verbose","defaultSerializedCache","TokenCache","storage","cachePlugin","cacheHasChanged","handleChangeEvent","bind","persistence","hasChanged","serialize","finalState","cacheSnapshot","mergeState","deserialize","deserializedCache","overlayDefaults","getKVStore","cacheContext","TokenCacheContext","beforeCacheAccess","getAllAccounts","afterCacheAccess","allAccounts","accountObj","removeAccount","generateAccountCacheKey","oldState","currentState","stateAfterRemoval","mergeRemovals","mergeUpdates","newState","newKey","newValue","hasOwnProperty","newValueNotNull","newValueIsObject","newValueIsNotArray","Array","isArray","oldStateNotUndefinedOrNull","mergeRemovalsDict","oldKey","passedInCache","NodeAuthError","AuthError","errorCode","errorMessage","ClientApplication","configuration","config","cryptoProvider","Logger","tokenCache","info","correlationId","validRequest","initializeBaseRequest","responseMode","ResponseMode","QUERY","authenticationScheme","AuthenticationScheme","BEARER","authClientConfig","buildOauthClientConfiguration","undefined","authorizationCodeClient","AuthorizationCodeClient","getAuthCodeUrl","authCodePayLoad","state","validateState","serverTelemetryManager","initializeServerTelemetryManager","acquireTokenByCode","acquireToken","setCorrelationId","cacheFailedRequest","acquireTokenByRefreshToken","refreshTokenClientConfig","refreshTokenClient","RefreshTokenClient","forceRefresh","acquireTokenSilent","silentFlowClientConfig","silentFlowClient","SilentFlowClient","acquireTokenByUsernamePassword","usernamePasswordClientConfig","usernamePasswordClient","UsernamePasswordClient","getTokenCache","cachedState","createStateNotFoundError","ClientAuthError","createStateMismatchError","getLogger","setLogger","requestCorrelationId","azureRegionConfiguration","userAzureCloudOptions","discoveredAuthority","createAuthority","updateRegionDiscoveryMetadata","regionDiscoveryMetadata","authOptions","cacheOptions","cryptoInterface","networkInterface","storageInterface","clientCredentials","getClientAssertion","libraryInfo","sku","version","cpu","process","arch","os","platform","persistencePlugin","serializableCache","assertion","getJwt","tokenEndpoint","assertionType","authRequest","POP","claims","isEmptyObj","hashString","scopes","OIDC_DEFAULT_SCOPES","apiId","ServerTelemetryManager","authorityString","authorityUrl","Authority","generateAuthority","authorityOptions","AuthorityFactory","createDiscoveredInstance","clearCache","clear","LoopbackClient","successTemplate","errorTemplate","server","createLoopbackServerAlreadyExistsError","authCodeListener","createServer","async","req","res","createUnableToLoadRedirectUrlError","CommonConstants","FORWARD_SLASH","authCodeResponse","UrlString","getDeserializedQueryString","code","redirectUri","getRedirectUri","writeHead","REDIRECT","location","listen","ticks","id","setInterval","LOOPBACK_SERVER_CONSTANTS","createLoopbackServerTimeoutError","listening","clearInterval","createNoLoopbackServerExistsError","address","closeServer","createInvalidLoopbackAddressTypeError","close","ClientAssertion","jwt","publicCertificate","parseCertificate","issuer","jwtAudience","isExpired","createJwt","createInvalidAssertionError","issuedAt","TimeUtils","nowSeconds","expirationTime","alg","x5t","assign","payload","aud","exp","iss","sub","nbf","jti","sign","regexToFindCerts","certs","matches","exec","setClientCredential","appTokenProvider","SetAppTokenProvider","provider","baseRequest","validBaseRequest","scope","azureRegion","environmentRegion","env","acquireTokenByClientCredential","skipCache","clientCredentialConfig","clientCredentialClient","ClientCredentialClient","onBehalfOfConfig","oboClient","OnBehalfOfClient","clientSecretNotEmpty","clientAssertionNotEmpty","certificate","certificateNotEmpty","createInvalidCredentialError","fromAssertion","fromCertificate","_configuration$auth$c","client","partitionManager","partitionKey","getKey","cacheData","get","kvStore","accountEntities","values","extractKey","nativeBrokerPlugin","isBrokerAvailable","warning","acquireTokenByDeviceCode","deviceCodeConfig","deviceCodeClient","DeviceCodeClient","openBrowser","windowHandle","loopbackClient","customLoopbackClient","remainingProperties","brokerRequest","extraParameters","extraQueryParameters","tokenQueryParameters","accountId","_remainingProperties$","nativeAccountId","acquireTokenInteractive","listenForAuthCode","codeChallenge","codeChallengeMethod","CodeChallengeMethodValues","S256","authCodeUrl","finally","ServerError","suberror","createNoAuthCodeInResponseError","tokenRequest","signoutRequest","signOut"],"mappings":"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"}