Skip to content

Commit 3e47595

Browse files
committed
Use correct metadata interface for RequiredScopeOrAppPermission extension
formatting
1 parent 180ec45 commit 3e47595

2 files changed

Lines changed: 85 additions & 1 deletion

File tree

src/Microsoft.Identity.Web/Policy/RequiredScopeOrAppPermissionExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static TBuilder RequireScopeOrAppPermission<TBuilder>(this TBuilder endpo
4545
return endpointConventionBuilder.WithMetadata(new RequiredScopeOrAppPermissionMetadata(scope, appPermission));
4646
}
4747

48-
private sealed class RequiredScopeOrAppPermissionMetadata : IAuthRequiredScopeMetadata
48+
private sealed class RequiredScopeOrAppPermissionMetadata : IAuthRequiredScopeOrAppPermissionMetadata
4949
{
5050
public RequiredScopeOrAppPermissionMetadata(string[] scope, string[] appPermission)
5151
{
@@ -57,6 +57,7 @@ public RequiredScopeOrAppPermissionMetadata(string[] scope, string[] appPermissi
5757
public string[]? AcceptedAppPermission { get; }
5858

5959
public string? RequiredScopesConfigurationKey { get; }
60+
public string? RequiredAppPermissionsConfigurationKey { get; }
6061
}
6162
}
6263
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Security.Claims;
7+
using System.Threading.Tasks;
8+
9+
using Microsoft.AspNetCore.Authorization;
10+
using Microsoft.AspNetCore.Builder;
11+
using Microsoft.AspNetCore.Routing.Patterns;
12+
using Microsoft.AspNetCore.Routing;
13+
using Microsoft.Extensions.DependencyInjection;
14+
using Microsoft.Extensions.Hosting;
15+
using Microsoft.IdentityModel.Tokens;
16+
17+
using Xunit;
18+
19+
namespace Microsoft.Identity.Web.Test.Resource
20+
{
21+
public class RequiredScopeOrAppPermissionExtensionsTests
22+
{
23+
private const string PolicyName = "foo";
24+
private const string AppPermission = "access_as_app";
25+
private const string Scope = "user.read";
26+
27+
[Fact]
28+
public async Task RequireScopeOrAppPermission_WithAppPermission_SucceedsAsync()
29+
{
30+
// Arrange
31+
var authorizationService = BuildAuthorizationService(PolicyName, null, Scope);
32+
33+
var user = new ClaimsPrincipal(
34+
new CaseSensitiveClaimsIdentity([new Claim(ClaimConstants.Role, AppPermission)]));
35+
36+
var testBuilder = new TestEndpointConventionBuilder()
37+
.RequireScopeOrAppPermission([], [AppPermission]);
38+
39+
var convention = Assert.Single(testBuilder.Conventions);
40+
41+
var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);
42+
convention(endpointModel);
43+
var endpoint = endpointModel.Build();
44+
45+
// Act
46+
var allowed = await authorizationService.AuthorizeAsync(user, endpoint, PolicyName);
47+
48+
// Assert
49+
Assert.True(allowed.Succeeded);
50+
}
51+
52+
private static IAuthorizationService BuildAuthorizationService(string policy, string? appPermission, string? scope)
53+
{
54+
IHostBuilder hostBuilder = Host.CreateDefaultBuilder()
55+
.ConfigureServices(services =>
56+
{
57+
services.AddAuthorization(options =>
58+
{
59+
options.AddPolicy(policy, policyBuilder =>
60+
{
61+
policyBuilder.RequireScopeOrAppPermission(scope?.Split(' ')!, appPermission?.Split(' ')!);
62+
});
63+
});
64+
services.AddLogging();
65+
services.AddOptions();
66+
services.AddRequiredScopeOrAppPermissionAuthorization();
67+
});
68+
69+
var provider = hostBuilder.Build().Services;
70+
return provider.GetRequiredService<IAuthorizationService>();
71+
}
72+
73+
private class TestEndpointConventionBuilder : IEndpointConventionBuilder
74+
{
75+
public List<Action<EndpointBuilder>> Conventions { get; } = [];
76+
77+
public void Add(Action<EndpointBuilder> convention)
78+
{
79+
Conventions.Add(convention);
80+
}
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)