|
using Duende.IdentityModel; |
|
using Duende.IdentityServer.Validation; |
|
|
|
namespace Sample.Idsrv.Validation; |
|
|
|
/* |
|
* To register this custom validator, use "AddCustomAuthorizeRequestValidator" when configuring IdentityServer: |
|
* |
|
* builder.Service.AddIdentityServer() |
|
* .AddCustomAuthorizeRequestValidator<LimitedAuthorizeRequestValidator>(); |
|
*/ |
|
|
|
public class LimitedAuthorizeRequestValidator : ICustomAuthorizeRequestValidator |
|
{ |
|
private readonly ILogger<CustomAuthorizeRequestValidator> _logger; |
|
|
|
private static readonly string[] AllowedGrantTypes = [ |
|
OidcConstants.GrantTypes.AuthorizationCode, |
|
OidcConstants.GrantTypes.Ciba, |
|
OidcConstants.GrantTypes.ClientCredentials, |
|
OidcConstants.GrantTypes.DeviceCode, |
|
OidcConstants.GrantTypes.JwtBearer, |
|
OidcConstants.GrantTypes.RefreshToken, |
|
OidcConstants.GrantTypes.TokenExchange |
|
]; |
|
|
|
public CustomAuthorizeRequestValidator(ILogger<CustomAuthorizeRequestValidator> logger) |
|
{ |
|
_logger = logger; |
|
} |
|
|
|
public Task ValidateAsync(CustomAuthorizeRequestValidationContext context) |
|
{ |
|
var result = context.Result; |
|
if (result is null) |
|
{ |
|
return Task.CompletedTask; |
|
} |
|
|
|
var request = result.ValidatedRequest; |
|
|
|
var grantTypeResult = ValidateGrantType(request); |
|
if (grantTypeResult.IsError) |
|
{ |
|
context.Result = grantTypeResult; |
|
return Task.CompletedTask; |
|
} |
|
|
|
var pkceResult = ValidatePkceMethod(request); |
|
if (pkceResult.IsError) |
|
{ |
|
context.Result = pkceResult; |
|
return Task.CompletedTask; |
|
} |
|
|
|
return Task.CompletedTask; |
|
} |
|
|
|
private AuthorizeRequestValidationResult ValidateGrantType(ValidatedAuthorizeRequest request) |
|
{ |
|
if (AllowedGrantTypes.Contains(request.GrantType)) |
|
{ |
|
return Valid(request); |
|
} |
|
|
|
_logger.LogError("grant_type {grant_type} is not allowed", request.GrantType); |
|
return Invalid(request, description: "Grant type not supported"); |
|
} |
|
|
|
private AuthorizeRequestValidationResult ValidatePkceMethod(ValidatedAuthorizeRequest request) |
|
{ |
|
if (request.CodeChallengeMethod == OidcConstants.CodeChallengeMethods.Sha256) |
|
{ |
|
return Valid(request); |
|
} |
|
|
|
_logger.LogError("code_challenge_method of plain is not allowed"); |
|
return Invalid(request, description: "Transform algorithm not supported"); |
|
} |
|
|
|
private AuthorizeRequestValidationResult Invalid(ValidatedAuthorizeRequest request, |
|
string error = OidcConstants.AuthorizeErrors.InvalidRequest, |
|
string? description = null) => new(request, error, description); |
|
|
|
private AuthorizeRequestValidationResult Valid(ValidatedAuthorizeRequest request) => new(request); |
|
} |