diff --git a/samples/Web/Controllers/HomeController.cs b/samples/Web/Controllers/HomeController.cs index 76e9de8..67b8caf 100755 --- a/samples/Web/Controllers/HomeController.cs +++ b/samples/Web/Controllers/HomeController.cs @@ -1,11 +1,11 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; -using Duende.AccessTokenManagement.OpenIdConnect; using IdentityModel.Client; -using Microsoft.AspNetCore.Authentication; +using Duende.AccessTokenManagement.OpenIdConnect; namespace Web.Controllers; @@ -33,7 +33,7 @@ public async Task CallApiAsUserManual() var client = _httpClientFactory.CreateClient(); client.SetToken(token.AccessTokenType!, token.AccessToken!); - var response = await client.GetStringAsync($"{Startup.ApiBaseUrl}/test"); + var response = await client.GetStringAsync($"{Startup.ApiBaseUrl}test"); ViewBag.Json = PrettyPrint(response); return View("CallApi"); @@ -45,7 +45,7 @@ public async Task CallApiAsUserExtensionMethod() var client = _httpClientFactory.CreateClient(); client.SetToken(token.AccessTokenType!, token.AccessToken!); - var response = await client.GetStringAsync($"{Startup.ApiBaseUrl}/test"); + var response = await client.GetStringAsync($"{Startup.ApiBaseUrl}test"); ViewBag.Json = PrettyPrint(response); return View("CallApi"); @@ -53,7 +53,7 @@ public async Task CallApiAsUserExtensionMethod() public async Task CallApiAsUserFactory() { - var client = _httpClientFactory.CreateClient("user_client"); + var client = _httpClientFactory.CreateClient("user"); var response = await client.GetStringAsync("test"); ViewBag.Json = PrettyPrint(response); @@ -72,11 +72,8 @@ public async Task CallApiAsUserFactoryTyped([FromServices] TypedU [AllowAnonymous] public async Task CallApiAsUserResourceIndicator() { - var token = await HttpContext.GetUserAccessTokenAsync(new UserTokenRequestParameters { Resource = "urn:resource1" }); - var client = _httpClientFactory.CreateClient(); - client.SetToken(token.AccessTokenType!, token.AccessToken!); - - var response = await client.GetStringAsync($"{Startup.ApiBaseUrl}/test"); + var client = _httpClientFactory.CreateClient("user-resource"); + var response = await client.GetStringAsync("test"); ViewBag.Json = PrettyPrint(response); return View("CallApi"); @@ -90,7 +87,7 @@ public async Task CallApiAsClientExtensionMethod() var client = _httpClientFactory.CreateClient(); client.SetToken(token.AccessTokenType!, token.AccessToken!); - var response = await client.GetStringAsync($"{Startup.ApiBaseUrl}/test"); + var response = await client.GetStringAsync($"{Startup.ApiBaseUrl}test"); ViewBag.Json = PrettyPrint(response); return View("CallApi"); @@ -99,11 +96,8 @@ public async Task CallApiAsClientExtensionMethod() [AllowAnonymous] public async Task CallApiAsClientResourceIndicator() { - var token = await HttpContext.GetClientAccessTokenAsync(new UserTokenRequestParameters { Resource = "urn:resource1" }); - var client = _httpClientFactory.CreateClient(); - client.SetToken(token.AccessTokenType!, token.AccessToken!); - - var response = await client.GetStringAsync($"{Startup.ApiBaseUrl}/test"); + var client = _httpClientFactory.CreateClient("client-resource"); + var response = await client.GetStringAsync("test"); ViewBag.Json = PrettyPrint(response); return View("CallApi"); diff --git a/samples/Web/Startup.cs b/samples/Web/Startup.cs index 08dd251..cc7ef7b 100755 --- a/samples/Web/Startup.cs +++ b/samples/Web/Startup.cs @@ -5,6 +5,7 @@ using System.Security.Cryptography; using System.Text.Json; using System.Threading.Tasks; +using Duende.AccessTokenManagement.OpenIdConnect; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; @@ -16,11 +17,14 @@ namespace Web; public static class Startup { - public const bool UseDPoP = false; + public const bool UseDPoP = true; + + public const string BaseUrl = "https://localhost:5001"; + //public const string BaseUrl = "https://demo.duendesoftware.com"; public const string ApiBaseUrl = UseDPoP ? - "https://demo.duendesoftware.com/api/dpop/" : - "https://demo.duendesoftware.com/api/"; + $"{BaseUrl}/api/dpop/" : + $"{BaseUrl}/api/"; internal static WebApplication ConfigureServices(this WebApplicationBuilder builder) { @@ -39,8 +43,7 @@ internal static WebApplication ConfigureServices(this WebApplicationBuilder buil }) .AddOpenIdConnect("oidc", options => { - options.Authority = "https://demo.duendesoftware.com"; - //options.Authority = "https://localhost:5001"; + options.Authority = BaseUrl; options.ClientId = "interactive.confidential.short"; options.ClientSecret = "secret"; @@ -56,6 +59,8 @@ internal static WebApplication ConfigureServices(this WebApplicationBuilder buil options.Scope.Add("api"); options.Scope.Add("resource1.scope1"); + options.Resource = "urn:resource1"; + options.GetClaimsFromUserInfoEndpoint = true; options.SaveTokens = true; options.MapInboundClaims = false; @@ -65,12 +70,6 @@ internal static WebApplication ConfigureServices(this WebApplicationBuilder buil NameClaimType = "name", RoleClaimType = "role" }; - - options.Events.OnRedirectToIdentityProvider = ctx => - { - ctx.ProtocolMessage.Resource = "urn:resource1"; - return Task.CompletedTask; - }; }); var rsaKey = new RsaSecurityKey(RSA.Create(2048)); @@ -80,11 +79,22 @@ internal static WebApplication ConfigureServices(this WebApplicationBuilder buil builder.Services.AddOpenIdConnectAccessTokenManagement(options => { - options.DPoPJsonWebKey = UseDPoP ? jwk : null; ; + options.DPoPJsonWebKey = UseDPoP ? jwk : null; }); // registers HTTP client that uses the managed user access token - builder.Services.AddUserAccessTokenHttpClient("user_client", + builder.Services.AddUserAccessTokenHttpClient("user", + configureClient: client => { + client.BaseAddress = new Uri(ApiBaseUrl); + }); + + // registers HTTP client that uses the managed user access token and + // includes a resource indicator + builder.Services.AddUserAccessTokenHttpClient("user-resource", + new UserTokenRequestParameters + { + Resource = "urn:resource1" + }, configureClient: client => { client.BaseAddress = new Uri(ApiBaseUrl); }); @@ -93,6 +103,15 @@ internal static WebApplication ConfigureServices(this WebApplicationBuilder buil builder.Services.AddClientAccessTokenHttpClient("client", configureClient: client => { client.BaseAddress = new Uri(ApiBaseUrl); }); + // registers HTTP client that uses the managed client access token and + // includes a resource indicator + builder.Services.AddClientAccessTokenHttpClient("client-resource", + new UserTokenRequestParameters + { + Resource = "urn:resource1" + }, + configureClient: client => { client.BaseAddress = new Uri(ApiBaseUrl); }); + // registers a typed HTTP client with token management support builder.Services.AddHttpClient(client => { diff --git a/samples/Web/Views/Home/Index.cshtml b/samples/Web/Views/Home/Index.cshtml index e9563fd..2fb1c26 100755 --- a/samples/Web/Views/Home/Index.cshtml +++ b/samples/Web/Views/Home/Index.cshtml @@ -12,8 +12,5 @@ HTTP client factory @("|") HTTP client factory (typed) -@if (!Startup.UseDPoP) -{ - @("|") - Use resource indicator -} +@("|") +Use resource indicator diff --git a/samples/Web/Views/Home/Secure.cshtml b/samples/Web/Views/Home/Secure.cshtml index fc5de2c..d25aaff 100755 --- a/samples/Web/Views/Home/Secure.cshtml +++ b/samples/Web/Views/Home/Secure.cshtml @@ -12,11 +12,8 @@ HTTP client factory @("|") HTTP client factory (typed) -@if (!Startup.UseDPoP) -{ - @("|") - Use resource indicator -} +@("|") +Use resource indicator

Call API as Client

@@ -28,11 +25,8 @@ HTTP client factory @("|") HTTP client factory (typed) -@if (!Startup.UseDPoP) -{ - @("|") - Use resource indicator -} +@("|") +Use resource indicator

Claims

diff --git a/src/Duende.AccessTokenManagement.OpenIdConnect/AuthenticationSessionUserTokenStore.cs b/src/Duende.AccessTokenManagement.OpenIdConnect/AuthenticationSessionUserTokenStore.cs index 6cbf967..dc92447 100755 --- a/src/Duende.AccessTokenManagement.OpenIdConnect/AuthenticationSessionUserTokenStore.cs +++ b/src/Duende.AccessTokenManagement.OpenIdConnect/AuthenticationSessionUserTokenStore.cs @@ -89,11 +89,12 @@ public async Task GetTokenAsync( var tokenName = NamePrefixAndResourceSuffix(OpenIdConnectParameterNames.AccessToken, parameters); var tokenTypeName = NamePrefixAndResourceSuffix(OpenIdConnectParameterNames.TokenType, parameters); - var dpopKeyName = NamePrefixAndResourceSuffix(DPoPKeyName, parameters); var expiresName = NamePrefixAndResourceSuffix("expires_at", parameters); - // Note that we are not including the the resource suffix because there is no per-resource refresh token + // Note that we are not including the the resource suffix because + // there is no per-resource refresh token or dpop key var refreshTokenName = NamePrefix(OpenIdConnectParameterNames.RefreshToken); + var dpopKeyName = NamePrefix(DPoPKeyName); var appendChallengeScheme = AppendChallengeSchemeToTokenNames(parameters); @@ -189,12 +190,12 @@ public async Task StoreTokenAsync( var tokenName = NamePrefixAndResourceSuffix(OpenIdConnectParameterNames.AccessToken, parameters); var tokenTypeName = NamePrefixAndResourceSuffix(OpenIdConnectParameterNames.TokenType, parameters); - var dpopKeyName = NamePrefixAndResourceSuffix(DPoPKeyName, parameters); var expiresName = NamePrefixAndResourceSuffix("expires_at", parameters); // Note that we are not including the resource suffix because there - // is no per-resource refresh token + // is no per-resource refresh token or dpop key var refreshTokenName = NamePrefix(OpenIdConnectParameterNames.RefreshToken); + var dpopKeyName = NamePrefix(DPoPKeyName); if (AppendChallengeSchemeToTokenNames(parameters)) { diff --git a/src/Duende.AccessTokenManagement.OpenIdConnect/TokenManagementHttpContextExtensions.cs b/src/Duende.AccessTokenManagement.OpenIdConnect/TokenManagementHttpContextExtensions.cs index 2284563..4890ab1 100755 --- a/src/Duende.AccessTokenManagement.OpenIdConnect/TokenManagementHttpContextExtensions.cs +++ b/src/Duende.AccessTokenManagement.OpenIdConnect/TokenManagementHttpContextExtensions.cs @@ -9,7 +9,6 @@ using Duende.AccessTokenManagement; using Duende.AccessTokenManagement.OpenIdConnect; using Microsoft.Extensions.Options; -using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Authentication; diff --git a/src/Duende.AccessTokenManagement/AccessTokenHandler.cs b/src/Duende.AccessTokenManagement/AccessTokenHandler.cs index c544006..9095826 100644 --- a/src/Duende.AccessTokenManagement/AccessTokenHandler.cs +++ b/src/Duende.AccessTokenManagement/AccessTokenHandler.cs @@ -103,7 +103,7 @@ protected virtual async Task SetTokenAsync(HttpRequestMessage request, bool forc } // since AccessTokenType above in the token endpoint response (the token_type value) could be case insensitive, but - // when we send it as an Authoriization header in the API request it must be case sensitive, we + // when we send it as an Authorization header in the API request it must be case sensitive, we // are checking for that here and forcing it to the exact casing required. if (scheme.Equals(AuthenticationSchemes.AuthorizationHeaderBearer, System.StringComparison.OrdinalIgnoreCase)) {