From 742aa615d90b0ba37bebb87921b7d83de8df751b Mon Sep 17 00:00:00 2001 From: Joe DeCock Date: Mon, 8 Dec 2025 13:25:33 -0600 Subject: [PATCH] Simplify making dpop optional --- .../DPoP/DPoPJwtBearerEvents.cs | 14 +++++++------- .../DPoP/DPoPMode.cs | 19 ------------------- .../DPoP/DPoPOptions.cs | 6 ++++-- .../DPoPIntegrationTests.cs | 2 +- 4 files changed, 12 insertions(+), 29 deletions(-) delete mode 100644 aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPMode.cs diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPJwtBearerEvents.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPJwtBearerEvents.cs index 1c5ef1ca7..9aa90cfef 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPJwtBearerEvents.cs +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPJwtBearerEvents.cs @@ -24,7 +24,7 @@ internal class DPoPJwtBearerEvents private readonly ILogger _logger; /// - /// Constructs a new instance of . + /// Constructs a new instance of . /// public DPoPJwtBearerEvents(IOptionsMonitor optionsMonitor, IDPoPProofValidator validator, ILogger logger) { @@ -47,10 +47,10 @@ internal class DPoPJwtBearerEvents { context.Token = token; } - else if (dpopOptions.TokenMode == DPoPMode.DPoPOnly) + else if (!dpopOptions.AllowBearerTokens) { - // this rejects the attempt for this handler, - // since we don't want to attempt Bearer given the Mode + // this rejects the attempt for this handler. + // we don't want to attempt Bearer when it is disabled by configuration. context.NoResult(); } @@ -114,10 +114,10 @@ internal class DPoPJwtBearerEvents } } } - else if (dPoPOptions.TokenMode == DPoPMode.DPoPAndBearer) + else if (dPoPOptions.AllowBearerTokens) { // if the scheme used was not DPoP, then it was Bearer - // and if an access token was presented with a cnf, then the + // and if an access token was presented with a cnf, then the // client should have sent it as DPoP, so we fail the request if (context.Principal?.HasClaim(x => x.Type == JwtClaimTypes.Confirmation) ?? false) { @@ -172,7 +172,7 @@ internal class DPoPJwtBearerEvents _logger.LogDebug("Challenge invoked in a JWT bearer authentication scheme using DPoP"); var dPoPOptions = _optionsMonitor.Get(context.Scheme.Name); - if (dPoPOptions.TokenMode == DPoPMode.DPoPOnly) + if (!dPoPOptions.AllowBearerTokens) { // if we are using DPoP only, then we don't need/want the default // JwtBearerHandler to add its WWW-Authenticate response header, diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPMode.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPMode.cs deleted file mode 100644 index 99846e9bd..000000000 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPMode.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace Duende.AspNetCore.Authentication.JwtBearer.DPoP; - -/// -/// Determines if DPoP and Bearer tokens are allowed, or only DPoP tokens. -/// -public enum DPoPMode -{ - /// - /// Only DPoP tokens will be accepted - /// - DPoPOnly, - /// - /// Both DPoP and Bearer tokens will be accepted - /// - DPoPAndBearer -} diff --git a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPOptions.cs b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPOptions.cs index 9b4c28892..7717ce3fd 100644 --- a/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPOptions.cs +++ b/aspnetcore-authentication-jwtbearer/src/AspNetCore.Authentication.JwtBearer/DPoP/DPoPOptions.cs @@ -12,9 +12,11 @@ namespace Duende.AspNetCore.Authentication.JwtBearer.DPoP; public sealed class DPoPOptions { /// - /// Controls if both DPoP and Bearer tokens are allowed, or only DPoP. Defaults to . + /// Controls if bearer tokens are accepted in addition to DPoP tokens. If + /// set, both Bearer and DPoP tokens can be used for authentication. If not, + /// DPoP tokens must be used. Defaults to false. /// - public DPoPMode TokenMode { get; set; } = DPoPMode.DPoPOnly; + public bool AllowBearerTokens { get; set; } /// /// The amount of time that a proof token is valid for. Defaults to 1 second. diff --git a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoPIntegrationTests.cs b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoPIntegrationTests.cs index 753d455b9..492b00a5e 100644 --- a/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoPIntegrationTests.cs +++ b/aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/DPoPIntegrationTests.cs @@ -232,7 +232,7 @@ public class DPoPIntegrationTests(ITestOutputHelper testOutputHelper) services.ConfigureDPoPTokensForScheme(ApiHost.AuthenticationScheme, opt => { - opt.TokenMode = DPoPMode.DPoPOnly; + opt.AllowBearerTokens = false; configureDPoP?.Invoke(opt); });