Skip to content

Commit 4901bd6

Browse files
authored
Merge pull request #29 from jokk-itu/feature/refactor-discovery
Feature/refactor discovery
2 parents fb53f4c + c3020b9 commit 4901bd6

File tree

56 files changed

+839
-385
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+839
-385
lines changed

src/AuthServer.TestIdentityProvider/Program.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
{
2626
var identitySection = builder.Configuration.GetSection("Identity");
2727
options.Issuer = identitySection.GetValue<string>("Issuer")!;
28+
options.OpPolicyUri = identitySection.GetValue<string>("PolicyUri");
29+
options.OpTosUri = identitySection.GetValue<string>("TosUri");
2830
options.ClaimsSupported = ClaimNameConstants.SupportedEndUserClaims;
2931
options.AcrValuesSupported =
3032
[
@@ -33,6 +35,7 @@
3335
AuthenticationContextReferenceConstants.LevelOfAssuranceStrict
3436
];
3537
options.ScopesSupported = identitySection.GetSection("ScopesSupported").Get<ICollection<string>>() ?? [];
38+
options.ProtectedResources = identitySection.GetSection("ProtectedResources").Get<ICollection<string>>() ?? [];
3639

3740
ICollection<string> signingAlgorithms =
3841
[JwsAlgConstants.RsaSha256, JwsAlgConstants.EcdsaSha256, JwsAlgConstants.RsaSsaPssSha256];
@@ -50,10 +53,12 @@
5053
options.IdTokenEncryptionAlgValuesSupported = encryptionAlgorithms;
5154
options.RequestObjectEncryptionAlgValuesSupported = encryptionAlgorithms;
5255
options.UserinfoEncryptionAlgValuesSupported = encryptionAlgorithms;
56+
options.TokenEndpointAuthEncryptionAlgValuesSupported = encryptionAlgorithms;
5357

5458
options.IdTokenEncryptionEncValuesSupported = encoderAlgorithms;
5559
options.RequestObjectEncryptionEncValuesSupported = encoderAlgorithms;
5660
options.UserinfoEncryptionEncValuesSupported = encoderAlgorithms;
61+
options.TokenEndpointAuthEncryptionEncValuesSupported = encoderAlgorithms;
5762
});
5863

5964
var ecdsa = ECDsa.Create();

src/AuthServer.TestIdentityProvider/appsettings.Integration.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"Default": ""
44
},
55
"Identity": {
6-
"ScopesSupported": ["weather:read"]
6+
"ScopesSupported": [ "weather:read" ],
7+
"ProtectedResources": ["https://weather.authserver.dk"]
78
}
89
}

src/AuthServer.TestIdentityProvider/appsettings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
},
1010
"Identity": {
1111
"Issuer": "https://localhost:7254",
12+
"ServiceDocumentation": "http://localhost:5300/",
13+
"PolicyUri": "https://localhost:7254/policy",
14+
"TosUri": "https://localhost:7254/tos",
1215
"AccountSelectionUri": "https://localhost:7254/SelectAccount",
1316
"LoginUri": "https://localhost:7254/SignIn",
1417
"EndSessionUri": "https://localhost:7254/SignOut",

src/AuthServer/Authorization/BaseAuthorizeValidator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ protected bool HasValidGrantManagementAction(string? grantId, string? grantManag
114114
GrantManagementActionConstants.Merge,
115115
GrantManagementActionConstants.Replace
116116
}
117-
.Intersect(_discoveryDocumentOptions.Value.GrantManagementActionsSupported)
117+
.Intersect(GrantManagementActionConstants.GrantManagementActions)
118118
.ToList();
119119

120120
if (!string.IsNullOrEmpty(grantManagementAction)

src/AuthServer/Authorize/AuthorizeEndpointHandler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ public async Task<IResult> Handle(HttpContext httpContext, CancellationToken can
5656

5757
return error switch
5858
{
59-
{ Error: ErrorCode.LoginRequired } => Results.Extensions.LocalRedirectWithForwardSubstitutedRequest(_userInteractionOptions.Value.LoginUri, httpContext, substituteRequest),
60-
{ Error: ErrorCode.ConsentRequired } => Results.Extensions.LocalRedirectWithForwardSubstitutedRequest(_userInteractionOptions.Value.ConsentUri, httpContext, substituteRequest),
61-
_ => Results.Extensions.LocalRedirectWithForwardSubstitutedRequest(_userInteractionOptions.Value.AccountSelectionUri, httpContext, substituteRequest)
59+
{ Error: ErrorCode.LoginRequired } => Results.Extensions.LocalRedirectWithForwardSubstitutedRequest(_userInteractionOptions.Value.LoginUri!, httpContext, substituteRequest),
60+
{ Error: ErrorCode.ConsentRequired } => Results.Extensions.LocalRedirectWithForwardSubstitutedRequest(_userInteractionOptions.Value.ConsentUri!, httpContext, substituteRequest),
61+
_ => Results.Extensions.LocalRedirectWithForwardSubstitutedRequest(_userInteractionOptions.Value.AccountSelectionUri!, httpContext, substituteRequest)
6262
};
6363
}
6464

src/AuthServer/Authorize/AuthorizeRequestValidator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public async Task<ProcessResult<AuthorizeValidatedRequest, ProcessError>> Valida
111111

112112
private async Task<ProcessResult<AuthorizeRequest, ProcessError>> SubstituteRequestObject(AuthorizeRequest request, CancellationToken cancellationToken)
113113
{
114-
var newRequest = await _secureRequestService.GetRequestByObject(request.RequestObject!, request.ClientId!, ClientTokenAudience.AuthorizeEndpoint, cancellationToken);
114+
var newRequest = await _secureRequestService.GetRequestByObject(request.RequestObject!, request.ClientId!, ClientTokenAudience.AuthorizationEndpoint, cancellationToken);
115115
if (newRequest is null)
116116
{
117117
return AuthorizeError.InvalidRequest;
@@ -132,7 +132,7 @@ private async Task<ProcessResult<AuthorizeRequest, ProcessError>> SubstituteRequ
132132
return AuthorizeError.UnauthorizedRequestUri;
133133
}
134134

135-
var newRequest = await _secureRequestService.GetRequestByReference(requestUri, request.ClientId!, ClientTokenAudience.AuthorizeEndpoint, cancellationToken);
135+
var newRequest = await _secureRequestService.GetRequestByReference(requestUri, request.ClientId!, ClientTokenAudience.AuthorizationEndpoint, cancellationToken);
136136
if (newRequest is null)
137137
{
138138
return AuthorizeError.InvalidRequestObjectFromRequestUri;

src/AuthServer/Constants/ClaimNameConstants.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using AuthServer.Enums;
2-
3-
namespace AuthServer.Constants;
1+
namespace AuthServer.Constants;
42

53
/// <summary>
64
/// Constants defined at IANA.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace AuthServer.Constants;
2+
3+
internal static class ClaimTypeConstants
4+
{
5+
public const string Normal = "normal";
6+
7+
public static readonly string[] ClaimTypes = [ Normal ];
8+
}

src/AuthServer/Constants/GrantManagementActionConstants.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ public static class GrantManagementActionConstants
77
public const string Replace = "replace";
88
public const string Merge = "merge";
99
public const string Create = "create";
10+
11+
public static readonly string[] GrantManagementActions = [ Query, Revoke, Replace, Merge, Create ];
1012
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using AuthServer.Constants;
2+
using AuthServer.Core;
3+
using AuthServer.Core.Abstractions;
4+
using AuthServer.Endpoints.Abstractions;
5+
using AuthServer.Endpoints.Responses;
6+
using AuthServer.Options;
7+
using Microsoft.AspNetCore.Http;
8+
using Microsoft.Extensions.Options;
9+
using Microsoft.FeatureManagement;
10+
11+
namespace AuthServer.Discovery;
12+
13+
internal class DiscoveryEndpointHandler : IEndpointHandler
14+
{
15+
private readonly IOptionsSnapshot<DiscoveryDocument> _discoveryDocumentOptions;
16+
private readonly IFeatureManagerSnapshot _featureManagerSnapshot;
17+
private readonly IEndpointResolver _endpointResolver;
18+
19+
public DiscoveryEndpointHandler(
20+
IOptionsSnapshot<DiscoveryDocument> discoveryDocumentOptions,
21+
IFeatureManagerSnapshot featureManagerSnapshot,
22+
IEndpointResolver endpointResolver)
23+
{
24+
_discoveryDocumentOptions = discoveryDocumentOptions;
25+
_featureManagerSnapshot = featureManagerSnapshot;
26+
_endpointResolver = endpointResolver;
27+
}
28+
29+
private DiscoveryDocument DiscoveryDocument => _discoveryDocumentOptions.Value;
30+
31+
public async Task<IResult> Handle(HttpContext httpContext, CancellationToken cancellationToken)
32+
{
33+
var response = new GetDiscoveryResponse
34+
{
35+
Issuer = DiscoveryDocument.Issuer,
36+
ServiceDocumentation = DiscoveryDocument.ServiceDocumentation,
37+
OpPolicyUri = DiscoveryDocument.OpPolicyUri,
38+
OpTosUri = DiscoveryDocument.OpTosUri,
39+
AuthorizationEndpoint = await Filter(_endpointResolver.AuthorizationEndpoint, FeatureFlags.Authorize),
40+
TokenEndpoint = await Filter(_endpointResolver.TokenEndpoint, FeatureFlags.AuthorizationCode, FeatureFlags.RefreshToken, FeatureFlags.ClientCredentials),
41+
UserinfoEndpoint = await Filter(_endpointResolver.UserinfoEndpoint, FeatureFlags.Userinfo),
42+
JwksUri = await Filter(_endpointResolver.JwksEndpoint, FeatureFlags.Jwks),
43+
RegistrationEndpoint = await Filter(_endpointResolver.RegistrationEndpoint, FeatureFlags.RegisterGet, FeatureFlags.RegisterDelete, FeatureFlags.RegisterPost, FeatureFlags.RegisterPut),
44+
EndSessionEndpoint = await Filter(_endpointResolver.EndSessionEndpoint, FeatureFlags.EndSession),
45+
IntrospectionEndpoint = await Filter(_endpointResolver.IntrospectionEndpoint, FeatureFlags.TokenIntrospection),
46+
RevocationEndpoint = await Filter(_endpointResolver.RevocationEndpoint, FeatureFlags.TokenRevocation),
47+
PushedAuthorizationRequestEndpoint = await Filter(_endpointResolver.PushedAuthorizationEndpoint, FeatureFlags.PushedAuthorization),
48+
GrantManagementEndpoint = await Filter(_endpointResolver.GrantManagementEndpoint, FeatureFlags.GrantManagementRevoke, FeatureFlags.GrantManagementQuery),
49+
ProtectedResources = DiscoveryDocument.ProtectedResources,
50+
ClaimsSupported = DiscoveryDocument.ClaimsSupported,
51+
ScopesSupported = DiscoveryDocument.ScopesSupported,
52+
AcrValuesSupported = DiscoveryDocument.AcrValuesSupported,
53+
ClaimTypesSupported = ClaimTypeConstants.ClaimTypes,
54+
PromptValuesSupported = PromptConstants.Prompts,
55+
DisplayValuesSupported = DisplayConstants.DisplayValues,
56+
SubjectTypesSupported = SubjectTypeConstants.SubjectTypes,
57+
GrantTypesSupported = GrantTypeConstants.GrantTypes,
58+
ChallengeMethodsSupported = CodeChallengeMethodConstants.CodeChallengeMethods,
59+
ResponseTypesSupported = ResponseTypeConstants.ResponseTypes,
60+
ResponseModesSupported = ResponseModeConstants.ResponseModes,
61+
IntrospectionEndpointAuthMethodsSupported = TokenEndpointAuthMethodConstants.SecureAuthMethods,
62+
RevocationEndpointAuthMethodsSupported = TokenEndpointAuthMethodConstants.SecureAuthMethods,
63+
TokenEndpointAuthMethodsSupported = TokenEndpointAuthMethodConstants.AuthMethods,
64+
GrantManagementActionsSupported = GrantManagementActionConstants.GrantManagementActions,
65+
IdTokenSigningAlgValuesSupported = DiscoveryDocument.IdTokenSigningAlgValuesSupported,
66+
IdTokenEncryptionAlgValuesSupported = DiscoveryDocument.IdTokenEncryptionAlgValuesSupported,
67+
IdTokenEncryptionEncValuesSupported = DiscoveryDocument.IdTokenEncryptionEncValuesSupported,
68+
UserinfoSigningAlgValuesSupported = DiscoveryDocument.UserinfoSigningAlgValuesSupported,
69+
UserinfoEncryptionAlgValuesSupported = DiscoveryDocument.UserinfoEncryptionAlgValuesSupported,
70+
UserinfoEncryptionEncValuesSupported = DiscoveryDocument.UserinfoEncryptionEncValuesSupported,
71+
RequestObjectSigningAlgValuesSupported = DiscoveryDocument.RequestObjectSigningAlgValuesSupported,
72+
RequestObjectEncryptionAlgValuesSupported = DiscoveryDocument.RequestObjectEncryptionAlgValuesSupported,
73+
RequestObjectEncryptionEncValuesSupported = DiscoveryDocument.RequestObjectEncryptionEncValuesSupported,
74+
TokenEndpointAuthSigningAlgValuesSupported = DiscoveryDocument.TokenEndpointAuthSigningAlgValuesSupported,
75+
TokenEndpointAuthEncryptionAlgValuesSupported = DiscoveryDocument.TokenEndpointAuthEncryptionAlgValuesSupported,
76+
TokenEndpointAuthEncryptionEncValuesSupported = DiscoveryDocument.TokenEndpointAuthEncryptionEncValuesSupported,
77+
AuthorizationResponseIssParameterSupported = true,
78+
BackchannelLogoutSupported = true,
79+
RequireRequestUriRegistration = true,
80+
ClaimsParameterSupported = false,
81+
RequestParameterSupported = true,
82+
RequestUriParameterSupported = true,
83+
RequireSignedRequestObject = DiscoveryDocument.RequireSignedRequestObject,
84+
RequirePushedAuthorizationRequests = DiscoveryDocument.RequirePushedAuthorizationRequests,
85+
GrantManagementActionRequired = DiscoveryDocument.GrantManagementActionRequired
86+
};
87+
88+
return Results.Ok(response);
89+
}
90+
91+
private async Task<T?> Filter<T>(T value, params string[] featureFlags)
92+
{
93+
foreach (var featureFlag in featureFlags)
94+
{
95+
if (await _featureManagerSnapshot.IsEnabledAsync(featureFlag))
96+
{
97+
return value;
98+
}
99+
}
100+
101+
return default;
102+
}
103+
}

0 commit comments

Comments
 (0)