Skip to content

Commit aa243d2

Browse files
paule96kirkone
andcommitted
cleanup the long development
Co-authored-by: Kirsten Kluge <live@kirk.one>
1 parent eab87af commit aa243d2

7 files changed

Lines changed: 112 additions & 58 deletions

File tree

src/KK.AspNetCore.EasyAuthAuthentication/EasyAuthAuthenticationExtensions.cs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static AuthenticationBuilder AddEasyAuth(this AuthenticationBuilder build
2929
/// <param name="authenticationScheme">The schema for the Easy Auth handler.</param>
3030
/// <returns>A reference to this instance after the operation has completed.</returns>
3131
public static AuthenticationBuilder AddEasyAuth(this AuthenticationBuilder builder, string authenticationScheme)
32-
=> builder.AddEasyAuth(authenticationScheme, configureOptions: (d) => {});
32+
=> builder.AddEasyAuth(authenticationScheme, configureOptions: (d) => { });
3333

3434
/// <summary>
3535
/// Adds the <see cref="EasyAuthAuthenticationHandler"/> for authentication.
@@ -86,26 +86,25 @@ public static AuthenticationBuilder AddEasyAuth(
8686
string displayName)
8787
{
8888
var options = new EasyAuthAuthenticationOptions
89-
{
90-
AuthEndpoint = configuration.GetValue<string>("easyAuthOptions:AuthEndpoint"),
89+
{
9190
ProviderOptions = configuration
92-
.GetSection("easyAuthOptions:providerOptions")
93-
.GetChildren()
94-
.Select(d =>
95-
{
96-
var name = d.GetValue<string>("ProviderName");
97-
var providerOptions = new ProviderOptions(name);
98-
d.Bind(providerOptions);
99-
return providerOptions;
100-
}).ToList()
101-
};
102-
if (string.IsNullOrWhiteSpace(options.AuthEndpoint))
103-
{
104-
throw new ArgumentNullException("The 'AuthEndpoint' in the configuraiton for easy auth can't be empty! please add the setting to your configuration providers.");
105-
}
91+
.GetSection("easyAuthOptions:providerOptions")
92+
.GetChildren()
93+
.Select(d =>
94+
{
95+
var name = d.GetValue<string>("ProviderName");
96+
var providerOptions = new ProviderOptions(name);
97+
d.Bind(providerOptions);
98+
return providerOptions;
99+
}).ToList(),
100+
LocalProviderOption = configuration
101+
.GetSection("easyAuthOptions:localProviderOption")
102+
.Get<LocalProviderOption>()
103+
104+
};
106105
return builder.AddEasyAuth(authenticationScheme, displayName, o =>
107106
{
108-
o.AuthEndpoint = options.AuthEndpoint;
107+
o.LocalProviderOption = options.LocalProviderOption;
109108
o.ProviderOptions = options.ProviderOptions;
110109
});
111110
}
@@ -119,9 +118,9 @@ public static AuthenticationBuilder AddEasyAuth(
119118
/// <param name="configureOptions">A callback to configure <see cref="EasyAuthAuthenticationOptions"/>.</param>
120119
/// <returns>A reference to this instance after the operation has completed.</returns>
121120
public static AuthenticationBuilder AddEasyAuth(
122-
this AuthenticationBuilder builder,
123-
string authenticationScheme,
124-
string displayName,
121+
this AuthenticationBuilder builder,
122+
string authenticationScheme,
123+
string displayName,
125124
Action<EasyAuthAuthenticationOptions> configureOptions)
126125
{
127126
var allAuthServicesToRegister = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())

src/KK.AspNetCore.EasyAuthAuthentication/EasyAuthAuthenticationHandler.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ public class EasyAuthAuthenticationHandler : AuthenticationHandler<EasyAuthAuthe
2828
private static Func<IHeaderDictionary, ClaimsPrincipal, HttpRequest, EasyAuthAuthenticationOptions, bool> CanUseEasyAuthJson =
2929
(headers, user, request, options) =>
3030
IsContextUserNotAuthenticated(user)
31-
&& !IsHeaderSet(headers, AuthTokenHeaderNames.AADIdToken)
32-
&& request.Path != "/" + $"{options.AuthEndpoint}";
31+
&& !IsHeaderSet(headers, AuthTokenHeaderNames.AADIdToken);
3332

3433
private readonly IEnumerable<IEasyAuthAuthentificationService> authenticationServices;
3534
private readonly IConfiguration appConfiguration;
@@ -87,7 +86,12 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
8786
}
8887
else if (CanUseEasyAuthJson(this.Context.Request.Headers, this.Context.User, this.Context.Request, this.Options))
8988
{
90-
return await EasyAuthWithAuthMeService.AuthUser(this.Logger, this.Context, this.Options);
89+
var service = new LocalAuthMeService(this.Logger,
90+
this.Context.Request.Scheme,
91+
this.Context.Request.Host.ToString(),
92+
this.Context.Request.Cookies,
93+
this.Context.Request.Headers);
94+
return await service.AuthUser(this.Context, this.Options.LocalProviderOption);
9195
}
9296
else
9397
{

src/KK.AspNetCore.EasyAuthAuthentication/EasyAuthAuthenticationOptions.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace KK.AspNetCore.EasyAuthAuthentication
1+
namespace KK.AspNetCore.EasyAuthAuthentication
22
{
33
using System;
44
using System.Collections;
@@ -13,17 +13,14 @@
1313
/// </summary>
1414
public class EasyAuthAuthenticationOptions : AuthenticationSchemeOptions
1515
{
16-
/// <summary>
17-
/// The endpoint where to look for the <c>JSON</c> with the authentification information.
18-
/// </summary>
19-
/// <value>A relative path to the <c>wwwroot</c> folder.</value>
20-
public string AuthEndpoint { get; set; } = ".auth/me";
2116

2217
/// <summary>
2318
/// A list of all provider options that should be used by easy auth.
2419
/// </summary>
2520
public IList<ProviderOptions> ProviderOptions { get; set; } = new List<ProviderOptions>();
2621

22+
public LocalProviderOption? LocalProviderOption { get; set; } = null;
23+
2724
/// <summary>
2825
/// Adds a new options object to the provider pipeline.
2926
/// It will replace exsisting options for the same provider. So be shure what you do.

src/KK.AspNetCore.EasyAuthAuthentication/Interfaces/IEasyAuthAuthentificationService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ public interface IEasyAuthAuthentificationService
2121
/// Try to create a <see cref="AuthenticateResult"/> out of the <see cref="HttpContext"/> from the incomming request.
2222
/// </summary>
2323
/// <param name="context">The <see cref="HttpContext"/> of the http request.</param>
24-
/// <returns>If the user can be authentificated it will returend a full <see cref="AuthenticateResult"/>. If not this will return a <see cref="AuthenticateResult.Fail(string)"/> result. (only the <see cref="EasyAuthWithAuthMeService"/> can return this.</returns>
24+
/// <returns>If the user can be authentificated it will returend a full <see cref="AuthenticateResult"/>. If not this will return a <see cref="AuthenticateResult.Fail(string)"/> result. (only the <see cref="LocalAuthMeService"/> can return this.</returns>
2525
AuthenticateResult AuthUser(HttpContext context);
2626

2727
/// <summary>
2828
/// Try to create a <see cref="AuthenticateResult"/> out of the <see cref="HttpContext"/> from the incomming request.
2929
/// </summary>
3030
/// <param name="context">The <see cref="HttpContext"/> of the http request.</param>
3131
/// <param name="options">The <see cref="ProviderOptions"/> that can change the behavior of the <see cref="AuthUser(HttpContext, ProviderOptions)"/> method.</param>
32-
/// <returns>If the user can be authentificated it will returend a full <see cref="AuthenticateResult"/>. If not this will return a <see cref="AuthenticateResult.Fail(string)"/> result. (only the <see cref="EasyAuthWithAuthMeService"/> can return this.</returns>
32+
/// <returns>If the user can be authentificated it will returend a full <see cref="AuthenticateResult"/>. If not this will return a <see cref="AuthenticateResult.Fail(string)"/> result. (only the <see cref="LocalAuthMeService"/> can return this.</returns>
3333
AuthenticateResult AuthUser(HttpContext context, ProviderOptions options);
3434
}
3535
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
namespace KK.AspNetCore.EasyAuthAuthentication.Models
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Text;
6+
using KK.AspNetCore.EasyAuthAuthentication.Services;
7+
8+
public class LocalProviderOption
9+
{
10+
public LocalProviderOption()
11+
{
12+
this.AuthEndpoint = string.Empty;
13+
this.NameClaimType =string.Empty;
14+
this.RoleClaimType = string.Empty;
15+
}
16+
public LocalProviderOption(string authEndpoint, string nameClaimType, string roleClaimType)
17+
{
18+
this.AuthEndpoint = authEndpoint;
19+
this.NameClaimType = nameClaimType;
20+
this.RoleClaimType = roleClaimType;
21+
}
22+
/// <summary>
23+
/// The endpoint where to look for the <c>JSON</c> with the authentification information.
24+
/// </summary>
25+
/// <value>A relative path to the <c>wwwroot</c> folder.</value>
26+
public string AuthEndpoint { get; set; }
27+
public string NameClaimType { get; set; }
28+
public string RoleClaimType { get; set; }
29+
30+
/// <summary>
31+
/// That would change the defined options of the current provider options object.
32+
/// </summary>
33+
/// <param name="options">The provider options model with the new options.</param>
34+
public void ChangeModel(LocalProviderOption? options)
35+
{
36+
if (options == null)
37+
{
38+
return;
39+
}
40+
else
41+
{
42+
if (!string.IsNullOrWhiteSpace(options.NameClaimType))
43+
{
44+
this.NameClaimType = options.NameClaimType;
45+
}
46+
47+
if (!string.IsNullOrWhiteSpace(options.RoleClaimType))
48+
{
49+
this.RoleClaimType = options.RoleClaimType;
50+
}
51+
52+
if (!string.IsNullOrWhiteSpace(options.AuthEndpoint))
53+
{
54+
this.AuthEndpoint = options.AuthEndpoint;
55+
}
56+
}
57+
}
58+
59+
public ProviderOptions GetProviderOptions() => new ProviderOptions(typeof(LocalAuthMeService).Name, this.NameClaimType, this.RoleClaimType);
60+
}
61+
}

src/KK.AspNetCore.EasyAuthAuthentication/Services/EasyAuthWithAuthMeService.cs renamed to src/KK.AspNetCore.EasyAuthAuthentication/Services/LocalAuthMeService.cs

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace KK.AspNetCore.EasyAuthAuthentication.Services
55
using System.Linq;
66
using System.Net;
77
using System.Net.Http;
8+
using System.Security.Claims;
89
using System.Threading.Tasks;
910
using KK.AspNetCore.EasyAuthAuthentication.Models;
1011
using Microsoft.AspNetCore.Authentication;
@@ -13,32 +14,30 @@ namespace KK.AspNetCore.EasyAuthAuthentication.Services
1314
using Newtonsoft.Json;
1415
using Newtonsoft.Json.Linq;
1516

16-
internal class EasyAuthWithAuthMeService
17+
internal class LocalAuthMeService
1718
{
18-
private EasyAuthWithAuthMeService(
19+
public LocalAuthMeService(
1920
ILogger logger,
2021
string httpSchema,
2122
string host,
2223
IRequestCookieCollection cookies,
23-
IHeaderDictionary headers,
24-
EasyAuthAuthenticationOptions options)
24+
IHeaderDictionary headers)
2525
{
2626
this.HttpSchema = httpSchema;
2727
this.Host = host;
2828
this.Cookies = cookies;
2929
this.Headers = headers;
30-
this.Options = options;
3130
this.Logger = logger;
3231
}
3332

33+
private readonly LocalProviderOption defaultOptions = new LocalProviderOption(".auth/me.json", ClaimTypes.Name, ClaimTypes.Role);
34+
3435
private string Host { get; }
3536

3637
private IRequestCookieCollection Cookies { get; }
3738

3839
private IHeaderDictionary Headers { get; }
3940

40-
private EasyAuthAuthenticationOptions Options { get; }
41-
4241
private ILogger Logger { get; }
4342

4443
private string HttpSchema { get; }
@@ -51,22 +50,15 @@ private EasyAuthWithAuthMeService(
5150
/// <param name="context">The http context with the missing user claim.</param>
5251
/// <param name="options">The <c>EasyAuthAuthenticationOptions</c> to use.</param>
5352
/// <returns>An <see cref="AuthenticateResult" />.</returns>
54-
public static async Task<AuthenticateResult> AuthUser(ILogger logger, HttpContext context, EasyAuthAuthenticationOptions options)
53+
public async Task<AuthenticateResult> AuthUser(HttpContext context, LocalProviderOption? options)
5554
{
55+
this.defaultOptions.ChangeModel(options);
5656
try
5757
{
58-
var authService = new EasyAuthWithAuthMeService(
59-
logger,
60-
context.Request.Scheme,
61-
context.Request.Host.ToString(),
62-
context.Request.Cookies,
63-
context.Request.Headers,
64-
options);
65-
66-
var ticket = await authService.CreateUserTicket();
67-
logger.LogInformation("Set identity to user context object.");
58+
var ticket = await this.CreateUserTicket();
59+
this.Logger.LogInformation("Set identity to user context object.");
6860
context.User = ticket.Principal;
69-
logger.LogInformation("identity build was a success, returning ticket");
61+
this.Logger.LogInformation("identity build was a success, returning ticket");
7062
return AuthenticateResult.Success(ticket);
7163
}
7264
catch (Exception ex)
@@ -84,7 +76,6 @@ private async Task<AuthenticationTicket> CreateUserTicket()
8476

8577
// build up identity from json...
8678
var ticket = this.BuildIdentityFromEasyAuthMeJson((JObject)payload[0]);
87-
8879
this.Logger.LogInformation("Set identity to user context object.");
8980
return ticket;
9081
}
@@ -98,7 +89,7 @@ private AuthenticationTicket BuildIdentityFromEasyAuthMeJson(JObject payload)
9889
return AuthenticationTicketBuilder.Build(
9990
JsonConvert.DeserializeObject<IEnumerable<AADClaimsModel>>(payload["user_claims"].ToString()),
10091
providerName,
101-
this.Options.ProviderOptions.First(d => d.ProviderName == typeof(EasyAuthWithAuthMeService).Name)
92+
this.defaultOptions.GetProviderOptions()
10293
);
10394
}
10495

@@ -108,6 +99,7 @@ private async Task<JArray> GetAuthMe(HttpClientHandler handler, HttpRequestMessa
10899
using (var client = new HttpClient(handler))
109100
{
110101
var response = await client.SendAsync(httpRequest);
102+
111103
if (!response.IsSuccessStatusCode)
112104
{
113105
this.Logger.LogDebug("auth endpoint was not successful. Status code: {0}, reason {1}", response.StatusCode, response.ReasonPhrase);
@@ -132,7 +124,7 @@ private async Task<JArray> GetAuthMe(HttpClientHandler handler, HttpRequestMessa
132124

133125
private HttpRequestMessage CreateAuthRequest(ref CookieContainer cookieContainer)
134126
{
135-
this.Logger.LogInformation($"identity not found, attempting to fetch from auth endpoint '/{this.Options.AuthEndpoint}'");
127+
this.Logger.LogInformation($"identity not found, attempting to fetch from auth endpoint '/{this.defaultOptions.AuthEndpoint}'");
136128

137129
var uriString = $"{this.HttpSchema}://{this.Host}";
138130

@@ -152,13 +144,13 @@ private HttpRequestMessage CreateAuthRequest(ref CookieContainer cookieContainer
152144

153145
// fetch value from endpoint
154146
string authMeEndpoint;
155-
if (this.Options.AuthEndpoint.StartsWith("http"))
147+
if (this.defaultOptions.AuthEndpoint.StartsWith("http"))
156148
{
157-
authMeEndpoint = this.Options.AuthEndpoint; // enable pulling from places like storage account private blob container
149+
authMeEndpoint = this.defaultOptions.AuthEndpoint; // enable pulling from places like storage account private blob container
158150
}
159151
else
160152
{
161-
authMeEndpoint = $"{uriString}/{this.Options.AuthEndpoint}"; // localhost relative path, e.g. wwwroot/.auth/me.json
153+
authMeEndpoint = $"{uriString}/{this.defaultOptions.AuthEndpoint}"; // localhost relative path, e.g. wwwroot/.auth/me.json
162154
}
163155

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

test/KK.AspNetCore.EasyAuthAuthentication.Test/EasyAuthAuthenticationHandlerTest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ public async Task DontCallTheFallBackIfTheRequestUrlEqualsTheAuthEndPoint()
146146
var config = configBuilder.Build();
147147
var options = new EasyAuthAuthenticationOptions();
148148
options.AddProviderOptions(new ProviderOptions("TestProvider") { Enabled = false });
149+
options.LocalProviderOption = new LocalProviderOption(".auth/me", string.Empty, string.Empty);
149150

150151

151152
var services = new ServiceCollection().AddOptions()
@@ -159,7 +160,7 @@ public async Task DontCallTheFallBackIfTheRequestUrlEqualsTheAuthEndPoint()
159160
var schema = new AuthenticationScheme(EasyAuthAuthenticationDefaults.AuthenticationScheme, EasyAuthAuthenticationDefaults.DisplayName, typeof(EasyAuthAuthenticationHandler));
160161
var context = new DefaultHttpContext();
161162

162-
context.Request.Path = "/" + options.AuthEndpoint;
163+
context.Request.Path = "/" + options.LocalProviderOption.AuthEndpoint;
163164
// Act
164165
await handler.InitializeAsync(schema, context);
165166
var result = await handler.AuthenticateAsync();

0 commit comments

Comments
 (0)