File tree Expand file tree Collapse file tree 6 files changed +91
-2
lines changed Expand file tree Collapse file tree 6 files changed +91
-2
lines changed Original file line number Diff line number Diff line change @@ -40,7 +40,9 @@ private static void ConfigureOpenIddict(IUmbracoBuilder builder)
4040 . SetLogoutEndpointUris (
4141 Paths . MemberApi . LogoutEndpoint . TrimStart ( Constants . CharArrays . ForwardSlash ) )
4242 . SetRevocationEndpointUris (
43- Paths . MemberApi . RevokeEndpoint . TrimStart ( Constants . CharArrays . ForwardSlash ) ) ;
43+ Paths . MemberApi . RevokeEndpoint . TrimStart ( Constants . CharArrays . ForwardSlash ) )
44+ . SetUserinfoEndpointUris (
45+ Paths . MemberApi . UserinfoEndpoint . TrimStart ( Constants . CharArrays . ForwardSlash ) ) ;
4446
4547 // Enable authorization code flow with PKCE
4648 options
@@ -52,7 +54,8 @@ private static void ConfigureOpenIddict(IUmbracoBuilder builder)
5254 options
5355 . UseAspNetCore ( )
5456 . EnableAuthorizationEndpointPassthrough ( )
55- . EnableLogoutEndpointPassthrough ( ) ;
57+ . EnableLogoutEndpointPassthrough ( )
58+ . EnableUserinfoEndpointPassthrough ( ) ;
5659
5760 // Enable reference tokens
5861 // - see https://documentation.openiddict.com/configuration/token-storage.html
Original file line number Diff line number Diff line change @@ -14,6 +14,8 @@ public static class MemberApi
1414
1515 public static readonly string RevokeEndpoint = EndpointPath ( $ "{ EndpointTemplate } /revoke") ;
1616
17+ public static readonly string UserinfoEndpoint = EndpointPath ( $ "{ EndpointTemplate } /userinfo") ;
18+
1719 // NOTE: we're NOT using /api/v1.0/ here because it will clash with the Delivery API docs
1820 private static string EndpointPath ( string relativePath ) => $ "/umbraco/delivery/api/v1/{ relativePath } ";
1921 }
Original file line number Diff line number Diff line change 1+ using Asp . Versioning ;
2+ using Microsoft . AspNetCore . Authorization ;
3+ using Microsoft . AspNetCore . Mvc ;
4+ using OpenIddict . Server . AspNetCore ;
5+ using Umbraco . Cms . Api . Delivery . Routing ;
6+ using Umbraco . Cms . Api . Delivery . Services ;
7+
8+ namespace Umbraco . Cms . Api . Delivery . Controllers . Security ;
9+
10+ [ ApiVersion ( "1.0" ) ]
11+ [ ApiController ]
12+ [ VersionedDeliveryApiRoute ( Common . Security . Paths . MemberApi . EndpointTemplate ) ]
13+ [ ApiExplorerSettings ( IgnoreApi = true ) ]
14+ [ Authorize ( AuthenticationSchemes = OpenIddictServerAspNetCoreDefaults . AuthenticationScheme ) ]
15+ public class CurrentMemberController : DeliveryApiControllerBase
16+ {
17+ private readonly ICurrentMemberClaimsProvider _currentMemberClaimsProvider ;
18+
19+ public CurrentMemberController ( ICurrentMemberClaimsProvider currentMemberClaimsProvider )
20+ => _currentMemberClaimsProvider = currentMemberClaimsProvider ;
21+
22+ [ HttpGet ( "userinfo" ) ]
23+ public async Task < IActionResult > Userinfo ( )
24+ {
25+ Dictionary < string , object > claims = await _currentMemberClaimsProvider . GetClaimsAsync ( ) ;
26+ return Ok ( claims ) ;
27+ }
28+ }
Original file line number Diff line number Diff line change @@ -60,6 +60,7 @@ public static IUmbracoBuilder AddDeliveryApi(this IUmbracoBuilder builder)
6060 builder . Services . AddSingleton < IApiMediaQueryService , ApiMediaQueryService > ( ) ;
6161 builder . Services . AddTransient < IMemberApplicationManager , MemberApplicationManager > ( ) ;
6262 builder . Services . AddTransient < IRequestMemberAccessService , RequestMemberAccessService > ( ) ;
63+ builder . Services . AddTransient < ICurrentMemberClaimsProvider , CurrentMemberClaimsProvider > ( ) ;
6364
6465 builder . Services . ConfigureOptions < ConfigureUmbracoDeliveryApiSwaggerGenOptions > ( ) ;
6566 builder . AddUmbracoApiOpenApiUI ( ) ;
Original file line number Diff line number Diff line change 1+ using OpenIddict . Abstractions ;
2+ using Umbraco . Cms . Core . Security ;
3+
4+ namespace Umbraco . Cms . Api . Delivery . Services ;
5+
6+ // NOTE: this is public and unsealed to allow overriding the default claims with minimal effort.
7+ public class CurrentMemberClaimsProvider : ICurrentMemberClaimsProvider
8+ {
9+ private readonly IMemberManager _memberManager ;
10+
11+ public CurrentMemberClaimsProvider ( IMemberManager memberManager )
12+ => _memberManager = memberManager ;
13+
14+ public virtual async Task < Dictionary < string , object > > GetClaimsAsync ( )
15+ {
16+ MemberIdentityUser ? memberIdentityUser = await _memberManager . GetCurrentMemberAsync ( ) ;
17+ return memberIdentityUser is not null
18+ ? await GetClaimsForMemberIdentityAsync ( memberIdentityUser )
19+ : throw new InvalidOperationException ( "Could not retrieve the current member. This method should only ever be invoked when a member has been authorized." ) ;
20+ }
21+
22+ protected virtual async Task < Dictionary < string , object > > GetClaimsForMemberIdentityAsync ( MemberIdentityUser memberIdentityUser )
23+ {
24+ var claims = new Dictionary < string , object >
25+ {
26+ [ OpenIddictConstants . Claims . Subject ] = memberIdentityUser . Key
27+ } ;
28+
29+ if ( memberIdentityUser . Name is not null )
30+ {
31+ claims [ OpenIddictConstants . Claims . Name ] = memberIdentityUser . Name ;
32+ }
33+
34+ if ( memberIdentityUser . Email is not null )
35+ {
36+ claims [ OpenIddictConstants . Claims . Email ] = memberIdentityUser . Email ;
37+ }
38+
39+ claims [ OpenIddictConstants . Claims . Role ] = await _memberManager . GetRolesAsync ( memberIdentityUser ) ;
40+
41+ return claims ;
42+ }
43+ }
Original file line number Diff line number Diff line change 1+ namespace Umbraco . Cms . Api . Delivery . Services ;
2+
3+ public interface ICurrentMemberClaimsProvider
4+ {
5+ /// <summary>
6+ /// Retrieves the claims for the currently logged in member.
7+ /// </summary>
8+ /// <remarks>
9+ /// This is used by the OIDC user info endpoint to supply "current user" info.
10+ /// </remarks>
11+ Task < Dictionary < string , object > > GetClaimsAsync ( ) ;
12+ }
You can’t perform that action at this time.
0 commit comments