Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/browser/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ export class BrowserAuthorizationClient implements AuthorizationClient {
userManagerSettings = { ...userManagerSettings, ...advancedSettings };
}

// Note: extraHeaders in UserManagerSettings is passed through to token requests.
Comment thread
ben-polinsky marked this conversation as resolved.
Comment thread
ben-polinsky marked this conversation as resolved.
// oidc-client-ts supports functions for ExtraHeader values, which will be invoked
// per request to generate dynamic headers.
if (!userManagerSettings.extraHeaders) {
userManagerSettings.extraHeaders = {}; // eslint-disable-line @typescript-eslint/naming-convention
}
/* eslint-disable @typescript-eslint/naming-convention */
userManagerSettings.extraHeaders["x-correlation-id"] = () => crypto.randomUUID();
/* eslint-enable @typescript-eslint/naming-convention */

return userManagerSettings;
}

Expand Down
13 changes: 7 additions & 6 deletions packages/electron/src/main/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ import {
RevokeTokenRequest,
TokenRequest,
} from "@openid/appauth";
import { NodeCrypto, NodeRequestor } from "@openid/appauth/built/node_support";
import { NodeCrypto } from "@openid/appauth/built/node_support";
import { ElectronAuthorizationEvents } from "./Events";
import { ElectronMainAuthorizationRequestHandler } from "./ElectronMainAuthorizationRequestHandler";
import { RefreshTokenStore } from "./TokenStore";
import { LoopbackWebServer } from "./LoopbackWebServer";
import { CorrelationIdRequestor } from "./CorrelationIdRequestor";
import * as electron from "electron";
import { defaultExpiryBufferInSeconds } from "../common/constants";
import type { IpcChannelNames } from "../common/IpcChannelNames";
Expand Down Expand Up @@ -352,7 +353,7 @@ export class ElectronMainAuthorization implements AuthorizationClient {
*/
public async signIn(): Promise<void> {
if (!this._configuration) {
const tokenRequestor = new NodeRequestor(); // the Node.js based HTTP client
const tokenRequestor = new CorrelationIdRequestor(); // the Node.js based HTTP client
this._configuration =
await AuthorizationServiceConfiguration.fetchFromIssuer(
this._issuerUrl,
Expand Down Expand Up @@ -470,7 +471,7 @@ export class ElectronMainAuthorization implements AuthorizationClient {
*/
public async signInSilent(): Promise<void> {
if (!this._configuration) {
const tokenRequestor = new NodeRequestor(); // the Node.js based HTTP client
const tokenRequestor = new CorrelationIdRequestor(); // the Node.js based HTTP client
this._configuration =
await AuthorizationServiceConfiguration.fetchFromIssuer(
this._issuerUrl,
Expand Down Expand Up @@ -610,7 +611,7 @@ export class ElectronMainAuthorization implements AuthorizationClient {
};

const tokenRequest = new TokenRequest(tokenRequestJson);
const tokenRequestor = new NodeRequestor();
const tokenRequestor = new CorrelationIdRequestor();
const tokenHandler: TokenRequestHandler = new BaseTokenRequestHandler(
tokenRequestor,
);
Expand Down Expand Up @@ -649,7 +650,7 @@ export class ElectronMainAuthorization implements AuthorizationClient {
};

const tokenRequest = new TokenRequest(tokenRequestJson);
const tokenRequestor = new NodeRequestor();
const tokenRequestor = new CorrelationIdRequestor();
const tokenHandler: TokenRequestHandler = new BaseTokenRequestHandler(
tokenRequestor,
);
Expand All @@ -671,7 +672,7 @@ export class ElectronMainAuthorization implements AuthorizationClient {
};

const revokeTokenRequest = new RevokeTokenRequest(revokeTokenRequestJson);
const tokenRequestor = new NodeRequestor();
const tokenRequestor = new CorrelationIdRequestor();
const tokenHandler: TokenRequestHandler = new BaseTokenRequestHandler(
tokenRequestor,
);
Expand Down
27 changes: 27 additions & 0 deletions packages/electron/src/main/CorrelationIdRequestor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/

import { randomUUID } from "node:crypto";
import { NodeRequestor } from "@openid/appauth/built/node_support";

/**
* A Node.js HTTP client that automatically adds x-correlation-id header to all requests.
* @internal
*/
export class CorrelationIdRequestor extends NodeRequestor {
// eslint-disable-next-line @typescript-eslint/promise-function-async
public override xhr<T>(settings: JQueryAjaxSettings): Promise<T> {
// Add x-correlation-id header to all requests to IMS
const enhancedSettings = {
...settings,
headers: {
...settings.headers,
// eslint-disable-next-line @typescript-eslint/naming-convention
"x-correlation-id": randomUUID(),
},
};
return super.xhr<T>(enhancedSettings);
}
}
9 changes: 5 additions & 4 deletions packages/node-cli/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import {
AuthorizationServiceConfiguration, BaseTokenRequestHandler, BasicQueryStringUtils, GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_REFRESH_TOKEN,
TokenRequest,
} from "@openid/appauth";
import { NodeCrypto, NodeRequestor } from "@openid/appauth/built/node_support";
import { NodeCrypto } from "@openid/appauth/built/node_support";
import { TokenStore } from "./TokenStore";
import { CorrelationIdRequestor } from "./CorrelationIdRequestor";

import type { AccessToken } from "@itwin/core-bentley";
import type { AuthorizationClient } from "@itwin/core-common";
Expand Down Expand Up @@ -166,7 +167,7 @@ export class NodeCliAuthorizationClient implements AuthorizationClient {
private async initialize() {
// Would ideally set up in constructor, but async...
if (!this._configuration)
this._configuration = await AuthorizationServiceConfiguration.fetchFromIssuer(this._bakedConfig.issuerUrl, new NodeRequestor());
this._configuration = await AuthorizationServiceConfiguration.fetchFromIssuer(this._bakedConfig.issuerUrl, new CorrelationIdRequestor());

await this._tokenStore.initialize();
}
Expand Down Expand Up @@ -251,7 +252,7 @@ export class NodeCliAuthorizationClient implements AuthorizationClient {
assert(authRequest.internal !== undefined);
assert(this._configuration !== undefined);
try {
const tokenHandler: TokenRequestHandler = new BaseTokenRequestHandler(new NodeRequestor());
const tokenHandler: TokenRequestHandler = new BaseTokenRequestHandler(new CorrelationIdRequestor());
const tokenResponse = await tokenHandler.performTokenRequest(this._configuration, new TokenRequest({
/* eslint-disable @typescript-eslint/naming-convention */
grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
Expand Down Expand Up @@ -283,7 +284,7 @@ export class NodeCliAuthorizationClient implements AuthorizationClient {
/* eslint-enable @typescript-eslint/naming-convention */

const tokenRequest = new TokenRequest(tokenRequestJson);
const tokenRequestor = new NodeRequestor();
const tokenRequestor = new CorrelationIdRequestor();
const tokenHandler: TokenRequestHandler = new BaseTokenRequestHandler(tokenRequestor);
return tokenHandler.performTokenRequest(this._configuration, tokenRequest);
}
Expand Down
27 changes: 27 additions & 0 deletions packages/node-cli/src/CorrelationIdRequestor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/

import { randomUUID } from "node:crypto";
import { NodeRequestor } from "@openid/appauth/built/node_support";

/**
* A Node.js HTTP client that automatically adds x-correlation-id header to all requests.
* @internal
*/
export class CorrelationIdRequestor extends NodeRequestor {
// eslint-disable-next-line @typescript-eslint/promise-function-async
public override xhr<T>(settings: JQueryAjaxSettings): Promise<T> {
// Add x-correlation-id header to all requests to IMS
const enhancedSettings = {
...settings,
headers: {
...settings.headers,
// eslint-disable-next-line @typescript-eslint/naming-convention
"x-correlation-id": randomUUID(),
Comment thread
ben-polinsky marked this conversation as resolved.
},
};
return super.xhr<T>(enhancedSettings);
}
}
Comment thread
ben-polinsky marked this conversation as resolved.
7 changes: 5 additions & 2 deletions packages/service/src/OIDCDiscoveryClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { URL } from "node:url";
import { randomUUID } from "node:crypto";

const requiredProperties = ["issuer", "authorization_endpoint", "jwks_uri", "response_types_supported", "subject_types_supported", "id_token_signing_alg_values_supported"] as const;
const stringProperties = ["issuer", "authorization_endpoint", "jwks_uri", "token_endpoint",
Expand Down Expand Up @@ -75,8 +76,10 @@ export class OIDCDiscoveryClient {
issuerUrl.pathname = `${issuerUrl.pathname?.replace(/\/$/, "")}/.well-known/openid-configuration`;
const response = await (await import("got")).default(issuerUrl, {
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention
Accept: "application/json",
/* eslint-disable @typescript-eslint/naming-convention */
"Accept": "application/json",
"x-correlation-id": randomUUID(),
Comment thread
ben-polinsky marked this conversation as resolved.
/* eslint-enable @typescript-eslint/naming-convention */
...additionalHeaders,
},
throwHttpErrors: false,
Expand Down
2 changes: 2 additions & 0 deletions packages/service/src/ServiceAuthorizationClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { ServiceAuthorizationClientConfiguration } from "./ServiceAuthoriza
// It also won't show up in the resulting .d.ts file because we don't re-export this type.
import type { Options as GotOptions } from "got" with { "resolution-mode": "import" };
import { OIDCDiscoveryClient } from "./OIDCDiscoveryClient";
import { randomUUID } from "node:crypto";

/**
* Utility to generate OIDC/OAuth tokens for service or service applications
Expand Down Expand Up @@ -74,6 +75,7 @@ export class ServiceAuthorizationClient implements AuthorizationClient {
/* eslint-disable @typescript-eslint/naming-convention */
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": authHeader,
"x-correlation-id": randomUUID(),
Comment thread
ben-polinsky marked this conversation as resolved.
...additionalHeaders,
/* eslint-enable @typescript-eslint/naming-convention */
},
Expand Down
Loading