Skip to content

Commit 488551b

Browse files
committed
Add ClaimType to the options
- Add the possibility to override the ClaimType for `User.Identity.Name` field - Update Sample +semver: feature
1 parent 4740931 commit 488551b

8 files changed

Lines changed: 68 additions & 39 deletions

File tree

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,22 @@ public string UserName()
8383

8484
If you want to add roles to the `User` property you can have a look in `Transformers/ClaimsTransformer.cs` in the Sample project. There you can see an example how to get started with this.
8585

86+
### Custom options
87+
88+
You can provide additional options vor the middleware:
89+
90+
```
91+
).AddEasyAuth(
92+
options =>
93+
{
94+
// Override the default claim for the User.Identity.Name field
95+
options.NameClaimType = ClaimTypes.Email;
96+
}
97+
);
98+
```
99+
100+
The `NameClaimType` is the ClaimType of the value which one will be used to fill the `User.Identity.Name` field.
101+
86102
### Local Debugging
87103

88104
For debugging your application you can place a `me.json` in the `wwwroot/.auth` folder of your web app and add some configuration to the `AddEasyAuth` call.

src/KK.AspNetCore.EasyAuthAuthentication.Sample/Startup.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace KK.AspNetCore.EasyAuthAuthentication.Sample
1212
using Microsoft.AspNetCore.Authentication;
1313
using KK.AspNetCore.EasyAuthAuthentication.Sample.Transformers;
1414
using KK.AspNetCore.EasyAuthAuthentication.Sample.Repositories;
15+
using System.Security.Claims;
1516

1617
public class Startup
1718
{
@@ -51,6 +52,9 @@ public void ConfigureServices(IServiceCollection services)
5152
// in publish site output which is desirable in this case.
5253
options.AuthEndpoint = ".auth/me.json";
5354
}
55+
56+
// Override the default claim for the User.Identity.Name field
57+
options.NameClaimType = ClaimTypes.Email;
5458
}
5559
);
5660

@@ -76,9 +80,9 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env)
7680
{
7781
app.UseExceptionHandler("/Error");
7882
app.UseHsts();
83+
app.UseHttpsRedirection();
7984
}
8085

81-
app.UseHttpsRedirection();
8286
app.UseStaticFiles();
8387
app.UseSpaStaticFiles();
8488

src/KK.AspNetCore.EasyAuthAuthentication.Sample/Transformers/ClaimsTransformer.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
3131
{
3232
if (principal.Identity.IsAuthenticated)
3333
{
34-
35-
3634
var claimsIdentity = (ClaimsIdentity)principal.Identity;
3735
var userIdentifier = claimsIdentity.Name;
3836
List<string> roles;
@@ -47,8 +45,6 @@ public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
4745
var dbRoles = await this.repository.GetRoles(userIdentifier);
4846

4947
roles.AddRange(dbRoles);
50-
51-
5248
}
5349

5450
roles.AddRange(claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value));

src/KK.AspNetCore.EasyAuthAuthentication/AuthenticationTicketBuilder.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,20 @@ internal static class AuthenticationTicketBuilder
1212
/// Build a `AuthenticationTicket` from the given payload, the principal name and the provider name.
1313
/// </summary>
1414
/// <param name="claimsPayload">A array of JObjects that have a `type` and a `val` property.</param>
15-
/// <param name="userid">The user ID of the current user.</param>
1615
/// <param name="providerName">The provider name of the current auth provider.</param>
16+
/// <param name="options">The <c>EasyAuthAuthenticationOptions</c> to use.</param>
1717
/// <returns>A `AuthenticationTicket`.</returns>
18-
public static AuthenticationTicket Build(IEnumerable<JObject> claimsPayload, string userid, string providerName)
18+
public static AuthenticationTicket Build(IEnumerable<JObject> claimsPayload, string providerName, EasyAuthAuthenticationOptions options)
1919
{
2020
// setting ClaimsIdentity.AuthenticationType to value that Azure AD non-EasyAuth setups use
2121
var identity = new ClaimsIdentity(
2222
CreateClaims(claimsPayload),
2323
AuthenticationTypesNames.Federation,
24-
ClaimTypes.Upn,
25-
ClaimTypes.Role
24+
options.NameClaimType,
25+
options.RoleClaimType
2626
);
2727

2828
AddScopeClaim(identity);
29-
AddUserIdClaim(identity, userid);
3029
AddProviderNameClaim(identity, providerName);
3130
var genericPrincipal = new ClaimsPrincipal(identity);
3231

@@ -79,11 +78,11 @@ private static void AddProviderNameClaim(ClaimsIdentity identity, string provide
7978
}
8079
}
8180

82-
private static void AddUserIdClaim(ClaimsIdentity identity, string userid)
81+
private static void AddUserIdClaim(ClaimsIdentity identity, string claimType, string userid)
8382
{
84-
if (!identity.Claims.Any(claim => claim.Type == ClaimTypes.Upn))
83+
if (!identity.Claims.Any(claim => claim.Type == claimType))
8584
{
86-
identity.AddClaim(new Claim(ClaimTypes.Upn, userid));
85+
identity.AddClaim(new Claim(claimType, userid));
8786
}
8887
}
8988
}

src/KK.AspNetCore.EasyAuthAuthentication/EasyAuthAuthenticationHandler.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ public class EasyAuthAuthenticationHandler : AuthenticationHandler<EasyAuthAuthe
2121
private static readonly Func<IHeaderDictionary, string, bool> IsHeaderSet =
2222
(headers, headerName) => !string.IsNullOrEmpty(headers[headerName].ToString());
2323

24-
private static readonly Func<IHeaderDictionary, ClaimsPrincipal, HttpRequest, string, bool> CanUseEasyAuthJson =
25-
(headers, user, request, authEndpoint) =>
24+
private static readonly Func<IHeaderDictionary, ClaimsPrincipal, HttpRequest, EasyAuthAuthenticationOptions, bool> CanUseEasyAuthJson =
25+
(headers, user, request, options) =>
2626
IsContextUserNotAuthenticated(user)
2727
&& !IsHeaderSet(headers, AuthTokenHeaderNames.AADIdToken)
28-
&& request.Path != "/" + $"{authEndpoint}";
28+
&& request.Path != "/" + $"{options.AuthEndpoint}";
2929

3030
private readonly Func<IHeaderDictionary, ClaimsPrincipal, bool> canUseHeaderAuth =
3131
(headers, user) => IsContextUserNotAuthenticated(user) &&
@@ -53,11 +53,11 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
5353

5454
if (this.canUseHeaderAuth(this.Context.Request.Headers, this.Context.User))
5555
{
56-
return EasyAuthWithHeaderService.AuthUser(this.Logger, this.Context);
56+
return EasyAuthWithHeaderService.AuthUser(this.Logger, this.Context, this.Options);
5757
}
58-
else if (CanUseEasyAuthJson(this.Context.Request.Headers, this.Context.User, this.Context.Request, this.Options.AuthEndpoint))
58+
else if (CanUseEasyAuthJson(this.Context.Request.Headers, this.Context.User, this.Context.Request, this.Options))
5959
{
60-
return await EasyAuthWithAuthMeService.AuthUser(this.Logger, this.Context, this.Options.AuthEndpoint);
60+
return await EasyAuthWithAuthMeService.AuthUser(this.Logger, this.Context, this.Options);
6161
}
6262
else
6363
{

src/KK.AspNetCore.EasyAuthAuthentication/EasyAuthAuthenticationOptions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace KK.AspNetCore.EasyAuthAuthentication
22
{
33
using System;
4+
using System.Security.Claims;
45
using Microsoft.AspNetCore.Authentication;
56

67
/// <summary>
@@ -13,5 +14,17 @@ public class EasyAuthAuthenticationOptions : AuthenticationSchemeOptions
1314
/// </summary>
1415
/// <value>A relative path to the <c>wwwroot</c> folder.</value>
1516
public string AuthEndpoint { get; set; } = ".auth/me";
17+
18+
/// <summary>
19+
/// The <c>ClaimType</c> for the Idendity User.
20+
/// </summary>
21+
/// <value>The Claim Type to use for the User. Default is <c>ClaimTypes.Name</c>.</value>
22+
public string NameClaimType { get; set; } = ClaimTypes.Name;
23+
24+
/// <summary>
25+
/// The <c>ClaimType</c> for the Idendity Role.
26+
/// </summary>
27+
/// <value>The Claim Type to use for the Roles. Default is <c>ClaimTypes.Role</c>.</value>
28+
public string RoleClaimType { get; set; } = ClaimTypes.Role;
1629
}
1730
}

src/KK.AspNetCore.EasyAuthAuthentication/Services/EasyAuthWithAuthMeService.cs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ private EasyAuthWithAuthMeService(
1919
string host,
2020
IRequestCookieCollection cookies,
2121
IHeaderDictionary headers,
22-
string authEndPoint)
22+
EasyAuthAuthenticationOptions options)
2323
{
2424
this.HttpSchema = httpSchema;
2525
this.Host = host;
2626
this.Cookies = cookies;
2727
this.Headers = headers;
28-
this.AuthEndPoint = authEndPoint;
28+
this.Options = options;
2929
this.Logger = logger;
3030
}
3131

@@ -35,7 +35,7 @@ private EasyAuthWithAuthMeService(
3535

3636
private IHeaderDictionary Headers { get; }
3737

38-
private string AuthEndPoint { get; }
38+
private EasyAuthAuthenticationOptions Options { get; }
3939

4040
private ILogger Logger { get; }
4141

@@ -47,9 +47,9 @@ private EasyAuthWithAuthMeService(
4747
/// </summary>
4848
/// <param name="logger">An instance of <see cref="ILogger"/>.</param>
4949
/// <param name="context">The http context with the missing user claim.</param>
50-
/// <param name="authEndpoint">The auth endpoint where we find the easy auth json.</param>
50+
/// <param name="options">The <c>EasyAuthAuthenticationOptions</c> to use.</param>
5151
/// <returns>An <see cref="AuthenticateResult" />.</returns>
52-
public static async Task<AuthenticateResult> AuthUser(ILogger logger, HttpContext context, string authEndpoint)
52+
public static async Task<AuthenticateResult> AuthUser(ILogger logger, HttpContext context, EasyAuthAuthenticationOptions options)
5353
{
5454
try
5555
{
@@ -59,7 +59,7 @@ public static async Task<AuthenticateResult> AuthUser(ILogger logger, HttpContex
5959
context.Request.Host.ToString(),
6060
context.Request.Cookies,
6161
context.Request.Headers,
62-
authEndpoint);
62+
options);
6363

6464
var ticket = await authService.CreateUserTicket();
6565
logger.LogInformation("Set identity to user context object.");
@@ -91,16 +91,14 @@ private async Task<AuthenticationTicket> CreateUserTicket()
9191

9292
private AuthenticationTicket BuildIdentityFromEasyAuthMeJson(JObject payload)
9393
{
94-
var userid = payload["user_id"].Value<string>();
95-
this.Logger.LogDebug($"payload was fetched from easyauth me json, name: {userid}");
9694
var providerName = payload["provider_name"].Value<string>();
9795
this.Logger.LogDebug($"payload was fetched from easyauth me json, provider: {providerName}");
9896

9997
this.Logger.LogInformation("building claims from payload...");
10098
return AuthenticationTicketBuilder.Build(
10199
payload["user_claims"].Children<JObject>(),
102-
userid,
103-
providerName
100+
providerName,
101+
this.Options
104102
);
105103
}
106104

@@ -132,7 +130,7 @@ private async Task<JArray> GetAuthMe(HttpClientHandler handler, HttpRequestMessa
132130

133131
private HttpRequestMessage CreateAuthRequest(ref CookieContainer cookieContainer)
134132
{
135-
this.Logger.LogInformation($"identity not found, attempting to fetch from auth endpoint '/{this.AuthEndPoint}'");
133+
this.Logger.LogInformation($"identity not found, attempting to fetch from auth endpoint '/{this.Options.AuthEndpoint}'");
136134

137135
var uriString = $"{this.HttpSchema}://{this.Host}";
138136

@@ -152,13 +150,13 @@ private HttpRequestMessage CreateAuthRequest(ref CookieContainer cookieContainer
152150

153151
// fetch value from endpoint
154152
var authMeEndpoint = string.Empty;
155-
if (this.AuthEndPoint.StartsWith("http"))
153+
if (this.Options.AuthEndpoint.StartsWith("http"))
156154
{
157-
authMeEndpoint = this.AuthEndPoint; // enable pulling from places like storage account private blob container
155+
authMeEndpoint = this.Options.AuthEndpoint; // enable pulling from places like storage account private blob container
158156
}
159157
else
160158
{
161-
authMeEndpoint = $"{uriString}/{this.AuthEndPoint}"; // localhost relative path, e.g. wwwroot/.auth/me.json
159+
authMeEndpoint = $"{uriString}/{this.Options.AuthEndpoint}"; // localhost relative path, e.g. wwwroot/.auth/me.json
162160
}
163161

164162
var request = new HttpRequestMessage(HttpMethod.Get, authMeEndpoint);

src/KK.AspNetCore.EasyAuthAuthentication/Services/EasyAuthWithHeaderService.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,30 @@ internal class EasyAuthWithHeaderService
1515

1616
private EasyAuthWithHeaderService(
1717
ILogger logger,
18-
IHeaderDictionary headers)
18+
IHeaderDictionary headers,
19+
EasyAuthAuthenticationOptions options)
1920
{
2021
this.Logger = logger;
2122
this.Headers = headers;
23+
this.Options = options;
2224
}
2325

2426
private ILogger Logger { get; }
2527

2628
private IHeaderDictionary Headers { get; }
2729

30+
private EasyAuthAuthenticationOptions Options { get; }
31+
2832
/// <summary>
2933
/// build up identity from X-MS-TOKEN-AAD-ID-TOKEN header set by EasyAuth filters if user openId connect session cookie or oauth bearer token authenticated ...
3034
/// </summary>
3135
/// <param name="logger">An instance of <see cref="ILogger"/>.</param>
3236
/// <param name="context">Http context of the request.</param>
37+
/// <param name="options">The <c>EasyAuthAuthenticationOptions</c> to use.</param>
3338
/// <returns>An <see cref="AuthenticateResult" />.</returns>
34-
public static AuthenticateResult AuthUser(ILogger logger, HttpContext context)
39+
public static AuthenticateResult AuthUser(ILogger logger, HttpContext context, EasyAuthAuthenticationOptions options)
3540
{
36-
var service = new EasyAuthWithHeaderService(logger, context.Request.Headers);
41+
var service = new EasyAuthWithHeaderService(logger, context.Request.Headers, options);
3742
var ticket = service.BuildIdentityFromEasyAuthRequestHeaders();
3843

3944
logger.LogInformation("Set identity to user context object.");
@@ -45,8 +50,6 @@ public static AuthenticateResult AuthUser(ILogger logger, HttpContext context)
4550

4651
private AuthenticationTicket BuildIdentityFromEasyAuthRequestHeaders()
4752
{
48-
var userid = this.Headers[PrincipalNameHeader][0];
49-
this.Logger.LogDebug($"payload was fetched from EasyAuth headers, name: {userid}");
5053
var providerName = this.Headers[PrincipalIdpHeaderName][0];
5154
this.Logger.LogDebug($"payload was fetched from easyauth me json, provider: {providerName}");
5255

@@ -59,7 +62,7 @@ private AuthenticationTicket BuildIdentityFromEasyAuthRequestHeaders()
5962

6063
var claims = xMsClientPrincipal["claims"].Children<JObject>();
6164

62-
return AuthenticationTicketBuilder.Build(claims, userid, providerName);
65+
return AuthenticationTicketBuilder.Build(claims, providerName, this.Options);
6366
}
6467
}
6568
}

0 commit comments

Comments
 (0)