Skip to content

Commit 5fb2f04

Browse files
authored
Merge pull request #31 from bornlogic/feature/validate-scopes-consider-user-role
validate if user hasRoleToBypassScopeValidation to skip client scope …
2 parents 37abea8 + 7aa0277 commit 5fb2f04

9 files changed

+47
-17
lines changed

Bornlogic.IdentityServer/Extensions/IClientStoreExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static async Task<Client> FindEnabledClientByIdAsync(this IClientStore st
3333

3434
if (clientUserRoleService != null && !string.IsNullOrEmpty(userID))
3535
{
36-
var userHasLoginByPassRoleInClient = await clientUserRoleService.UserHasLoginByPassRoleInClient(userID, client);
36+
var userHasLoginByPassRoleInClient = await clientUserRoleService.UserHasLoginByPassRoleInClient(userID, client, null);
3737

3838
if (userHasLoginByPassRoleInClient)
3939
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Bornlogic.IdentityServer.Models
2+
{
3+
public class ClientRoleOptions
4+
{
5+
public string[] ValidUserRolesToBypassClientScopeValidation { get; set; }
6+
}
7+
}

Bornlogic.IdentityServer/Services/Default/DefaultClientUserRoleService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace Bornlogic.IdentityServer.Services.Default
44
{
55
public class DefaultClientUserRoleService : IClientUserRoleService
66
{
7-
public Task<bool> UserHasLoginByPassRoleInClient(string userID, Client client)
7+
public Task<bool> UserHasLoginByPassRoleInClient(string userID, Client client, string[] validRoles)
88
{
99
return Task.FromResult(false);
1010
}

Bornlogic.IdentityServer/Services/IClientUserRoleService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ namespace Bornlogic.IdentityServer.Services
66
{
77
public interface IClientUserRoleService
88
{
9-
Task<bool> UserHasLoginByPassRoleInClient(string userID, Client client);
9+
Task<bool> UserHasLoginByPassRoleInClient(string userID, Client client, string[] validRoles);
1010
}
1111
}

Bornlogic.IdentityServer/Validation/Default/AuthorizeRequestValidator.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,8 @@ private async Task<AuthorizeRequestValidationResult> ValidateScopeAsync(Validate
621621
{
622622
Client = request.Client,
623623
Scopes = request.RequestedScopes,
624-
RequiredRequestScopes = request.Raw.Get("required_scope")?.Split(' ') ?? Array.Empty<string>()
624+
RequiredRequestScopes = request.Raw.Get("required_scope")?.Split(' ') ?? Array.Empty<string>(),
625+
Subject = request.Subject
625626
});
626627

627628
if (!validatedResources.Succeeded)

Bornlogic.IdentityServer/Validation/Default/DefaultResourceValidator.cs

+28-11
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33

44

55
using Bornlogic.IdentityServer.Extensions;
6+
using Bornlogic.IdentityServer.Models;
7+
using Bornlogic.IdentityServer.Services;
68
using Bornlogic.IdentityServer.Storage.Models;
79
using Bornlogic.IdentityServer.Storage.Stores;
810
using Bornlogic.IdentityServer.Validation.Models;
911
using Microsoft.Extensions.Logging;
12+
using Microsoft.Extensions.Options;
1013

1114
namespace Bornlogic.IdentityServer.Validation.Default
1215
{
@@ -16,6 +19,8 @@ namespace Bornlogic.IdentityServer.Validation.Default
1619
public class DefaultResourceValidator : IResourceValidator
1720
{
1821
private readonly ILogger _logger;
22+
private readonly IClientUserRoleService _clientUserRoleService;
23+
private readonly IOptions<ClientRoleOptions> _clientRoleOptions;
1924
private readonly IScopeParser _scopeParser;
2025
private readonly IResourceStore _store;
2126

@@ -25,9 +30,11 @@ public class DefaultResourceValidator : IResourceValidator
2530
/// <param name="store">The store.</param>
2631
/// <param name="scopeParser"></param>
2732
/// <param name="logger">The logger.</param>
28-
public DefaultResourceValidator(IResourceStore store, IScopeParser scopeParser, ILogger<DefaultResourceValidator> logger)
33+
public DefaultResourceValidator(IResourceStore store, IScopeParser scopeParser, ILogger<DefaultResourceValidator> logger, IClientUserRoleService clientUserRoleService, IOptions<ClientRoleOptions> clientRoleOptions)
2934
{
3035
_logger = logger;
36+
_clientUserRoleService = clientUserRoleService;
37+
_clientRoleOptions = clientRoleOptions;
3138
_scopeParser = scopeParser;
3239
_store = store;
3340
}
@@ -65,20 +72,30 @@ public virtual async Task<ResourceValidationResult> ValidateRequestedResourcesAs
6572
return result;
6673
}
6774

68-
var scopeNames = parsedScopesResult.ParsedScopes.Select(x => x.ParsedName).Distinct().ToArray();
69-
var resourcesFromStore = await _store.FindEnabledResourcesByScopeAsync(scopeNames);
75+
var subjectIdOrDefault = request.Subject?.GetSubjectIdOrDefault();
7076

71-
foreach (var scope in parsedScopesResult.ParsedScopes)
77+
if (!string.IsNullOrEmpty(subjectIdOrDefault))
7278
{
73-
await ValidateScopeAsync(request.Client, resourcesFromStore, scope, result, request.RequiredRequestScopes.Any(a => a == scope.ParsedName));
74-
}
79+
var hasRoleToBypassScopeValidation = await _clientUserRoleService.UserHasLoginByPassRoleInClient(subjectIdOrDefault, request.Client, _clientRoleOptions?.Value?.ValidUserRolesToBypassClientScopeValidation);
7580

76-
var requiredRequestScopeNames = parsedRequiredRequestScopesResult.ParsedScopes.Select(x => x.ParsedName).Distinct().ToArray();
77-
var requiredRequestResourcesFromStore = await _store.FindEnabledResourcesByScopeAsync(requiredRequestScopeNames);
81+
if (!hasRoleToBypassScopeValidation)
82+
{
83+
var scopeNames = parsedScopesResult.ParsedScopes.Select(x => x.ParsedName).Distinct().ToArray();
84+
var resourcesFromStore = await _store.FindEnabledResourcesByScopeAsync(scopeNames);
7885

79-
foreach (var scope in parsedRequiredRequestScopesResult.ParsedScopes)
80-
{
81-
await ValidateRequestRequiredScopeAsync(request.Client, requiredRequestResourcesFromStore, scope, result);
86+
foreach (var scope in parsedScopesResult.ParsedScopes)
87+
{
88+
await ValidateScopeAsync(request.Client, resourcesFromStore, scope, result, request.RequiredRequestScopes.Any(a => a == scope.ParsedName));
89+
}
90+
91+
var requiredRequestScopeNames = parsedRequiredRequestScopesResult.ParsedScopes.Select(x => x.ParsedName).Distinct().ToArray();
92+
var requiredRequestResourcesFromStore = await _store.FindEnabledResourcesByScopeAsync(requiredRequestScopeNames);
93+
94+
foreach (var scope in parsedRequiredRequestScopesResult.ParsedScopes)
95+
{
96+
await ValidateRequestRequiredScopeAsync(request.Client, requiredRequestResourcesFromStore, scope, result);
97+
}
98+
}
8299
}
83100

84101
if (result.InvalidScopes.Count > 0)

Bornlogic.IdentityServer/Validation/Default/DeviceAuthorizationRequestValidator.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ private async Task<DeviceAuthorizationRequestValidationResult> ValidateScopeAsyn
151151
//////////////////////////////////////////////////////////
152152
var validatedResources = await _resourceValidator.ValidateRequestedResourcesAsync(new ResourceValidationRequest{
153153
Client = request.Client,
154-
Scopes = request.RequestedScopes
154+
Scopes = request.RequestedScopes,
155+
Subject = request.Subject
155156
});
156157

157158
if (!validatedResources.Succeeded)

Bornlogic.IdentityServer/Validation/Default/TokenRequestValidator.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,8 @@ private async Task<bool> ValidateRequestedScopesAsync(NameValueCollection parame
721721

722722
var resourceValidationResult = await _resourceValidator.ValidateRequestedResourcesAsync(new ResourceValidationRequest {
723723
Client = _validatedRequest.Client,
724-
Scopes = requestedScopes
724+
Scopes = requestedScopes,
725+
Subject = _validatedRequest.Subject
725726
});
726727

727728
if (!resourceValidationResult.Succeeded)

Bornlogic.IdentityServer/Validation/Models/ResourceValidationRequest.cs

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
33

44

5+
using System.Security.Claims;
56
using Bornlogic.IdentityServer.Storage.Models;
67

78
namespace Bornlogic.IdentityServer.Validation.Models
@@ -16,6 +17,8 @@ public class ResourceValidationRequest
1617
/// </summary>
1718
public Client Client { get; set; }
1819

20+
public ClaimsPrincipal Subject { get; set; }
21+
1922
/// <summary>
2023
/// The requested scope values.
2124
/// </summary>

0 commit comments

Comments
 (0)