From a414abcead453d648c22e40669d3a798e638f8db Mon Sep 17 00:00:00 2001 From: James Gunn Date: Wed, 10 Apr 2024 15:41:53 +0100 Subject: [PATCH] Allow API access with a token from Authorize access (#1274) --- .../src/TeachingRecordSystem.Api/Program.cs | 19 +++++++++++++++---- .../appsettings.Development.json | 1 + .../appsettings.Testing.json | 1 + .../Pages/OidcTest/SignedIn.cshtml | 18 ++++++++---------- .../Pages/OidcTest/SignedIn.cshtml.cs | 17 ++++++++++++++++- .../HostFixture.cs | 2 +- 6 files changed, 42 insertions(+), 16 deletions(-) diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/Program.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/Program.cs index 39bbaa660..63e0351e7 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/Program.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/Program.cs @@ -2,7 +2,6 @@ using FluentValidation; using FluentValidation.AspNetCore; using idunno.Authentication.Basic; -using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.Formatters; @@ -48,12 +47,18 @@ public static void Main(string[] args) services.AddAuthentication(ApiKeyAuthenticationHandler.AuthenticationScheme) .AddScheme(ApiKeyAuthenticationHandler.AuthenticationScheme, _ => { }) - .AddJwtBearer(options => + .AddJwtBearer(AuthenticationSchemeNames.IdAccessToken, options => { options.Authority = configuration["GetAnIdentity:BaseAddress"]; options.MapInboundClaims = false; options.TokenValidationParameters.ValidateAudience = false; }) + .AddJwtBearer(AuthenticationSchemeNames.AuthorizeAccessAccessToken, options => + { + options.Authority = configuration.GetRequiredValue("AuthorizeAccessIssuer"); + options.MapInboundClaims = false; + options.TokenValidationParameters.ValidateAudience = false; + }) .AddBasic(options => { options.Realm = "TeachingRecordSystem.Api"; @@ -101,11 +106,11 @@ public static void Main(string[] args) options.AddPolicy( AuthorizationPolicies.IdentityUserWithTrn, policy => policy - .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) + .AddAuthenticationSchemes(AuthenticationSchemeNames.IdAccessToken, AuthenticationSchemeNames.AuthorizeAccessAccessToken) .RequireAssertion(ctx => { var scopes = (ctx.User.FindFirstValue("scope") ?? string.Empty).Split(' ', StringSplitOptions.RemoveEmptyEntries); - return scopes.Contains("dqt:read"); + return scopes.Contains("dqt:read") || scopes.Contains("teaching_record"); }) .RequireClaim("trn")); @@ -298,3 +303,9 @@ ServiceClient GetCrmServiceClient() } } } + +file static class AuthenticationSchemeNames +{ + public const string IdAccessToken = nameof(IdAccessToken); + public const string AuthorizeAccessAccessToken = nameof(AuthorizeAccessAccessToken); +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/appsettings.Development.json b/TeachingRecordSystem/src/TeachingRecordSystem.Api/appsettings.Development.json index 3f9dd1936..cd9c1c223 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/appsettings.Development.json +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/appsettings.Development.json @@ -1,5 +1,6 @@ { "AllowVNextEndpoints": true, + "AuthorizeAccessIssuer": "https://localhost:7236", "DetailedErrors": true, "Serilog": { "MinimumLevel": { diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/appsettings.Testing.json b/TeachingRecordSystem/src/TeachingRecordSystem.Api/appsettings.Testing.json index 822912ba6..b8868d29c 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/appsettings.Testing.json +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/appsettings.Testing.json @@ -1,5 +1,6 @@ { "AllowVNextEndpoints": true, + "AuthorizeAccessIssuer": "https://dummy", "Serilog": { "MinimumLevel": { "Default": "Error", diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/OidcTest/SignedIn.cshtml b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/OidcTest/SignedIn.cshtml index 162e842ed..a87873f63 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/OidcTest/SignedIn.cshtml +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/OidcTest/SignedIn.cshtml @@ -3,25 +3,23 @@ @using TeachingRecordSystem.AuthorizeAccess.Pages.OidcTest @addTagHelper *, Joonasw.AspNetCore.SecurityHeaders @model SignedInModel -@{ - var claimsJson = JsonSerializer.Serialize( - User.Claims.ToDictionary(c => c.Type, c => c.Value), - new JsonSerializerOptions() { WriteIndented = true }); -} @section Styles { }

- - Claims - @claimsJson - + + +

diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/OidcTest/SignedIn.cshtml.cs b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/OidcTest/SignedIn.cshtml.cs index 9c3f9cbbe..9b8c077c1 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/OidcTest/SignedIn.cshtml.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/OidcTest/SignedIn.cshtml.cs @@ -1,12 +1,27 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json; +using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.RazorPages; +using static IdentityModel.OidcConstants; namespace TeachingRecordSystem.AuthorizeAccess.Pages.OidcTest; [Authorize(AuthenticationSchemes = TestAppConfiguration.AuthenticationSchemeName)] public class SignedInModel : PageModel { - public void OnGet() + [Display(Name = "Access token")] + public string? AccessToken { get; set; } + + [Display(Name = "Claims")] + public string? ClaimsJson { get; set; } + + public async Task OnGet() { + AccessToken = await HttpContext.GetTokenAsync(TestAppConfiguration.AuthenticationSchemeName, TokenTypes.AccessToken); + + ClaimsJson = JsonSerializer.Serialize( + User.Claims.ToDictionary(c => c.Type, c => c.Value), + new JsonSerializerOptions() { WriteIndented = true }); } } diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/HostFixture.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/HostFixture.cs index 1c57feeca..9d73dc348 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/HostFixture.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/HostFixture.cs @@ -87,7 +87,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) .AddHttpMessageHandler(_ => EvidenceFilesHttpClientInterceptorOptions.CreateHttpMessageHandler()) .ConfigurePrimaryHttpMessageHandler(_ => new NotFoundHandler()); - services.PostConfigure(JwtBearerDefaults.AuthenticationScheme, options => + services.PostConfigure("IdAccessToken", options => { options.TokenValidationParameters.ValidateIssuer = false; options.TokenValidationParameters.IssuerSigningKey = JwtSigningCredentials.Key;