Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added token revocation functionality to Managed Identity's App Service and Service Fabric sources #7679

Open
wants to merge 13 commits into
base: dev
Choose a base branch
from

Conversation

Robbie-Microsoft
Copy link
Collaborator

@Robbie-Microsoft Robbie-Microsoft commented Apr 2, 2025

@github-actions github-actions bot added documentation Related to documentation. msal-node Related to msal-node package labels Apr 2, 2025
@Robbie-Microsoft Robbie-Microsoft changed the title Added token revocation functionality to Managed Identity's App Service and Service Fabric Sources Added token revocation functionality to Managed Identity's App Service and Service Fabric sources Apr 2, 2025
@Robbie-Microsoft Robbie-Microsoft marked this pull request as ready for review April 3, 2025 22:08
@github-actions github-actions bot added the msal-common Related to msal-common package label Apr 7, 2025
@@ -389,3 +389,8 @@ export const ONE_DAY_IN_MS = 86400000;

// Token renewal offset default in seconds
export const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;

export const EncodingTypes = {
HEX: "hex",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be making another PR where I replace every instance of "hex" with this new constant, and make "base64" value as well.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend to create a github issue and link it here for reference

@@ -2215,6 +2215,17 @@ const emptyInputScopesError = "empty_input_scopes_error";
// @public (undocumented)
const emptyInputScopeSet = "empty_input_scopeset";

// Warning: (ae-missing-release-tag) "EncodingTypes" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "EncodingTypes" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Duplicate line.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything in this file is auto-generated; we don't touch this file. But I'll re-run the apiExtractor and see if it removes the duplicate line.

* @param refreshAccessToken - Optional flag indicating whether to force a refresh of the access token.
* @returns A promise that resolves to an AuthenticationResult containing the acquired token and related information.
*/
private async acquireTokenFromManagedIdentity(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this method needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extracted the functionality for the network request since it's being used multiple times.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allowed me to write better docs for it

@AzureAD AzureAD deleted a comment from julesblancphin Apr 10, 2025
@@ -176,6 +178,70 @@ describe("Acquires a token successfully via an App Service Managed Identity", ()
});
});

describe("Miscellaneous", () => {
test("ignores a cached token when claims are provided and the Managed Identity does support token revocation, and ensures the token revocation query parameter token_sha256_to_refresh was included in the network request to the Managed Identity", async () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add test when just the capabilities are set and claims are not passed?

} from "../../utils/Constants.js";
import { CryptoProvider } from "../../crypto/CryptoProvider.js";
import { ManagedIdentityRequestParameters } from "../../config/ManagedIdentityRequestParameters.js";
import { ManagedIdentityId } from "../../config/ManagedIdentityId.js";
import { NodeStorage } from "../../cache/NodeStorage.js";

// MSI Constants. Docs for MSI are available here https://docs.microsoft.com/azure/app-service/overview-managed-identity
const APP_SERVICE_MSI_API_VERSION: string = "2019-08-01";
const APP_SERVICE_MSI_API_VERSION: string = "2025-03-30";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please do not merge this

Copy link

@gladjohn gladjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, the PR looks solid. It adds a clear, consistent approach for token revocation. If you remove 'app service' the PR can be merged. Else,. please mark it as 'Do Not Merge'


const SOURCES_THAT_SUPPORT_TOKEN_REVOCATION: Array<ManagedIdentitySourceNames> =
[
ManagedIdentitySourceNames.APP_SERVICE,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you remove app service, you can merge the PR. we can add app service later

* Check if there is a cached token and if the Managed Identity source supports token revocation.
* If so, hash the cached access token and add it to the request.
*/
if (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GOOD - if claims are set and you have a cached token, you skip the cache for that request, if the source supports revocation, you also send the old token’s SHA-256 to the server. This ensures the old token is invalidated on the RP

expect(networkManagedIdentityResult.accessToken).toEqual(
DEFAULT_SYSTEM_ASSIGNED_MANAGED_IDENTITY_AUTHENTICATION_RESULT.accessToken
);

expect(sendGetRequestAsyncSpy.mock.calls.length).toEqual(1);
const firstNetworkRequestUrlParams: URLSearchParams =

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of spies and verifying the final URLSearchParams

import { ManagedIdentityId } from "../config/ManagedIdentityId.js";
import { HashUtils } from "../crypto/HashUtils.js";

const SOURCES_THAT_SUPPORT_TOKEN_REVOCATION: Array<ManagedIdentitySourceNames> =

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great that you have a dedicated list of sources that handle revocation. If more services adopt it, it should be trivial to add them to SOURCES_THAT_SUPPORT_TOKEN_REVOCATION.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Related to documentation. msal-common Related to msal-common package msal-node Related to msal-node package
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants