From 9bde900abfef549080dd78ca92d3eef44254ceb0 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:03:36 -0400 Subject: [PATCH 1/3] Add guidance on V1 and V2 STS tokens --- .../security/blazor-web-app-with-entra.md | 54 ++++++++++++++++++- .../security/blazor-web-app-with-oidc.md | 10 ++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 767dfcf9c61f..b9b615f11da0 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -138,12 +138,22 @@ jwtOptions.Authority = "{AUTHORITY}"; The following examples use a Tenant ID of `aaaabbbb-0000-cccc-1111-dddd2222eeee` and a directory name of `contoso`. -If the app is registered in an ME-ID tenant, the authority should match the issurer (`iss`) of the JWT returned by the identity provider: +If the app is registered in an ME-ID tenant, the authority should match the issurer (`iss`) of the JWT returned by the identity provider. + +V1 STS token format: ```csharp jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee"; ``` +V2 STS token format: + +```csharp +jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0"; +``` + +For more information on V2 STS tokens, see the [STS token version](#sts-token-version) section. + If the app is registered in a Microsoft Entra External ID tenant: ```csharp @@ -434,12 +444,22 @@ jwtOptions.Authority = "{AUTHORITY}"; The following examples use a Tenant ID of `aaaabbbb-0000-cccc-1111-dddd2222eeee` and a directory name of `contoso`. -If the app is registered in an ME-ID tenant, the authority should match the issurer (`iss`) of the JWT returned by the identity provider: +If the app is registered in an ME-ID tenant, the authority should match the issurer (`iss`) of the JWT returned by the identity provider. + +V1 STS token format: ```csharp jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee"; ``` +V2 STS token format: + +```csharp +jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0"; +``` + +For more information on V2 STS tokens, see the [STS token version](#sts-token-version) section. + If the app is registered in a Microsoft Entra External ID tenant: ```csharp @@ -849,6 +869,8 @@ In the `MinimalApiJwt` project, add the following app settings configuration to }, ``` +The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see the [STS token version](#sts-token-version) section. + Update the placeholders in the preceding configuration to match the values that the app uses in the `Program` file: * `{TENANT ID (WEB API)}`: The Tenant Id of the web API. @@ -860,6 +882,8 @@ Authority formats adopt the following patterns: * Microsoft Entra External ID: `https://{DIRECTORY NAME}.ciamlogin.com/{TENANT ID}/v2.0` * B2C tenant type: `https://login.microsoftonline.com/{TENANT ID}/v2.0` +The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see the [STS token version](#sts-token-version) section. + Audience formats adopt the following patterns (`{CLIENT ID}` is the Client Id of the web API; `{DIRECTORY NAME}` is the directory name, for example, `contoso`): * ME-ID tenant type: `api://{CLIENT ID}` @@ -1157,6 +1181,32 @@ Server-side Blazor Web Apps hosted in a web farm or cluster of machines must ado We also recommend using a shared [Data Protection](xref:security/data-protection/introduction) key ring in production, even when the app uses the Interactive WebAssembly render mode exclusively for client-side rendering (no Blazor circuits). +## STS token version + +There are two types of token formats, named Version 1 (V1) and Version 2 (V2). In Azure's security token services (STS), the V1 format uses the `sts.windows.net` domain as the issuer, while the V2 format uses the `login.microsoftonline.com` domain as issuer. V2 supports additional features, such as authenticating personal accounts and OpenID protocols. + +This article and its accompanying sample apps adopt V1 STS tokens. To adopt V2 tokens, make the following changes: + +* The STS version must be changed in the apps' registrations in the Azure portal. Set the value of `requestedAccessTokenVersion` to `2` in the apps' manifests, both in the app's registration and the web API's (`MinimalApiJwt`) registration. +* Use the V2 authority URL format (example: `https://login.microsoftonline.com/{TENANT ID}/v2.0`, where the `{TENANT ID}` placeholder is the tenant ID). +* In the web API (`MinimalApiJwt`), explicitly validate the issuer: + + ```csharp + jwtOptions.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + // Ensure the issuer ends with /v2.0 if using the V2 endpoint + ValidIssuer = "https://login.microsoftonline.com/{TENANT ID}/v2.0", + ValidateAudience = true, + ValidAudience = "{WEB API CLIENT ID}", + ValidateLifetime = true + }; + ``` + + The `{WEB API CLIENT ID}` placeholder in the preceding example is only the client ID, not the full value passed to the `Audience` property. + +For more information, see [Access tokens in the Microsoft identity platform: Token formats](/entra/identity-platform/access-tokens#token-formats). + ## Troubleshoot [!INCLUDE[](~/blazor/security/includes/troubleshoot-server.md)] diff --git a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md index 81e79bf26364..88b6b59e0425 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md @@ -181,6 +181,8 @@ ME-ID tenant Authority example: jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee"; ``` +The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see . + AAD B2C tenant Authority example: ```csharp @@ -529,6 +531,8 @@ ME-ID tenant Authority example: jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee"; ``` +The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see . + AAD B2C tenant Authority example: ```csharp @@ -876,6 +880,8 @@ ME-ID tenant Authority example: jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee"; ``` +The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see . + AAD B2C tenant Authority example: ```csharp @@ -1200,6 +1206,8 @@ In the `MinimalApiJwt` project, add the following app settings configuration to }, ``` +The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see . + Update the placeholders in the preceding configuration to match the values that the app uses in the `Program` file: * `{TENANT ID (WEB API)}`: The Tenant Id of the web API. @@ -1211,6 +1219,8 @@ Authority formats adopt the following patterns: * Microsoft Entra External ID: `https://{DIRECTORY NAME}.ciamlogin.com/{TENANT ID}/v2.0` * B2C tenant type: `https://login.microsoftonline.com/{TENANT ID}/v2.0` +The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see . + Audience formats adopt the following patterns (`{CLIENT ID}` is the Client Id of the web API; `{DIRECTORY NAME}` is the directory name, for example, `contoso`): * ME-ID tenant type: `api://{CLIENT ID}` From c57d86e9b20ec48d7cdc14fcf4a43bab4e50370d Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:16:40 -0400 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index b9b615f11da0..80cedca838a4 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -138,7 +138,7 @@ jwtOptions.Authority = "{AUTHORITY}"; The following examples use a Tenant ID of `aaaabbbb-0000-cccc-1111-dddd2222eeee` and a directory name of `contoso`. -If the app is registered in an ME-ID tenant, the authority should match the issurer (`iss`) of the JWT returned by the identity provider. +If the app is registered in an ME-ID tenant, the authority should match the issuer (`iss`) of the JWT returned by the identity provider. V1 STS token format: @@ -444,7 +444,7 @@ jwtOptions.Authority = "{AUTHORITY}"; The following examples use a Tenant ID of `aaaabbbb-0000-cccc-1111-dddd2222eeee` and a directory name of `contoso`. -If the app is registered in an ME-ID tenant, the authority should match the issurer (`iss`) of the JWT returned by the identity provider. +If the app is registered in an ME-ID tenant, the authority should match the issuer (`iss`) of the JWT returned by the identity provider. V1 STS token format: From ea681a1b0961bfced9d1dcf8f7946de9741c46b9 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:18:26 -0400 Subject: [PATCH 3/3] Updates --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 2 +- aspnetcore/blazor/security/blazor-web-app-with-oidc.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 80cedca838a4..c32151f21ed5 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -882,7 +882,7 @@ Authority formats adopt the following patterns: * Microsoft Entra External ID: `https://{DIRECTORY NAME}.ciamlogin.com/{TENANT ID}/v2.0` * B2C tenant type: `https://login.microsoftonline.com/{TENANT ID}/v2.0` -The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see the [STS token version](#sts-token-version) section. +The preceding example for the ME-ID tenant type uses the V1 STS token URL format. For guidance on V2 STS tokens, see the [STS token version](#sts-token-version) section. Audience formats adopt the following patterns (`{CLIENT ID}` is the Client Id of the web API; `{DIRECTORY NAME}` is the directory name, for example, `contoso`): diff --git a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md index 88b6b59e0425..2a08e3b4969c 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md @@ -1219,7 +1219,7 @@ Authority formats adopt the following patterns: * Microsoft Entra External ID: `https://{DIRECTORY NAME}.ciamlogin.com/{TENANT ID}/v2.0` * B2C tenant type: `https://login.microsoftonline.com/{TENANT ID}/v2.0` -The preceding example uses the V1 STS token URL format. For guidance on V2 STS tokens, see . +The preceding example for the ME-ID tenant type uses the V1 STS token URL format. For guidance on V2 STS tokens, see . Audience formats adopt the following patterns (`{CLIENT ID}` is the Client Id of the web API; `{DIRECTORY NAME}` is the directory name, for example, `contoso`):