Skip to content

Commit 6611a6d

Browse files
committed
Upgrade for ASP Core 2.0
1 parent 7703a38 commit 6611a6d

14 files changed

+280
-367
lines changed

README.md

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,59 +19,62 @@ When you install the package, it should be added to your `.csproj`. Alternativel
1919

2020
```xml
2121
<ItemGroup>
22-
<PackageReference Include="ZNetCS.AspNetCore.Authentication.Basic" Version="1.0.0" />
22+
<PackageReference Include="ZNetCS.AspNetCore.Authentication.Basic" Version="2.0.0" />
2323
</ItemGroup>
2424
```
2525

26-
In order to use the basic authentication middleware, you must configure the services in the `Configure` call of `Startup`. Because basic
26+
In order to use the basic authentication middleware, you must configure the services in the `Configure` and `ConfigureServices` call of `Startup`. Because basic
2727
authentication is manual process handled on each request, there is need to validate credentials manually (see below).
2828

2929
```csharp
30-
using ZNetCS.AspNetCore.Authentication.Basic.DependencyInjection;
30+
using ZNetCS.AspNetCore.Authentication.Basic;
31+
using ZNetCS.AspNetCore.Authentication.Basic.Events;
3132
```
3233

3334
```
3435
...
3536
```
3637

3738
```csharp
38-
3939
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
4040
{
41-
var options = new BasicAuthenticationOptions
42-
{
43-
Realm = "My Application",
44-
Events = new BasicAuthenticationEvents
45-
{
46-
OnValidatePrincipal = context =>
41+
42+
// default authentication initilaization
43+
app.UseAuthentication();
44+
45+
// other middleware e.g. MVC etc
46+
}
47+
48+
public void ConfigureServices(IServiceCollection services)
49+
{
50+
services
51+
.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
52+
.AddBasicAuthentication(
53+
options =>
4754
{
48-
// here validation comes
49-
if ((context.UserName == "userName") && (context.Password == "password"))
55+
options.Realm = "My Application";
56+
options.Events = new BasicAuthenticationEvents
5057
{
51-
var claims = new List<Claim>
58+
OnValidatePrincipal = context =>
5259
{
53-
new Claim(ClaimTypes.Name, context.UserName, context.Options.ClaimsIssuer)
54-
};
55-
56-
var ticket = new AuthenticationTicket(
57-
new ClaimsPrincipal(
58-
new ClaimsIdentity(claims, context.Options.AuthenticationScheme)),
59-
new AuthenticationProperties(),
60-
context.Options.AuthenticationScheme);
61-
62-
// return success result with ticket
63-
return Task.FromResult(AuthenticateResult.Success(ticket));
64-
}
65-
66-
// return failed result
67-
return Task.FromResult(AuthenticateResult.Fail("Authentication failed."));
68-
}
69-
}
70-
};
71-
72-
app.UseBasicAuthentication(options);
73-
74-
// other middleware e.g. MVC etc
60+
if ((context.UserName == "userName") && (context.Password == "password"))
61+
{
62+
var claims = new List<Claim>
63+
{
64+
new Claim(ClaimTypes.Name, context.UserName, context.Options.ClaimsIssuer)
65+
};
66+
67+
var ticket = new AuthenticationTicket(
68+
new ClaimsPrincipal(new ClaimsIdentity(claims, BasicAuthenticationDefaults.AuthenticationScheme)),
69+
new Microsoft.AspNetCore.Authentication.AuthenticationProperties(),
70+
BasicAuthenticationDefaults.AuthenticationScheme);
71+
72+
return Task.FromResult(AuthenticateResult.Success(ticket));
73+
}
74+
75+
return Task.FromResult(AuthenticateResult.Fail("Authentication failed."));
76+
};
77+
});
7578
}
7679
```
7780

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// --------------------------------------------------------------------------------------------------------------------
2+
// <copyright file="BasicAuthenticationExtensions.cs" company="Marcin Smółka zNET Computer Solutions">
3+
// Copyright (c) Marcin Smółka zNET Computer Solutions. All rights reserved.
4+
// </copyright>
5+
// <summary>
6+
// The basic authentication extensions.
7+
// </summary>
8+
// --------------------------------------------------------------------------------------------------------------------
9+
10+
namespace ZNetCS.AspNetCore.Authentication.Basic
11+
{
12+
#region Usings
13+
14+
using System;
15+
16+
using Microsoft.AspNetCore.Authentication;
17+
18+
#endregion
19+
20+
/// <summary>
21+
/// The basic authentication extensions.
22+
/// </summary>
23+
public static class BasicAuthenticationExtensions
24+
{
25+
#region Public Methods
26+
27+
/// <summary>
28+
/// Adds basic authentication.
29+
/// </summary>
30+
/// <param name="builder">
31+
/// The authentication builder.
32+
/// </param>
33+
public static AuthenticationBuilder AddBasicAuthentication(this AuthenticationBuilder builder)
34+
{
35+
return builder.AddBasicAuthentication(BasicAuthenticationDefaults.AuthenticationScheme);
36+
}
37+
38+
/// <summary>
39+
/// Adds basic authentication.
40+
/// </summary>
41+
/// <param name="builder">
42+
/// The authentication builder.
43+
/// </param>
44+
/// <param name="authenticationScheme">
45+
/// The authentication scheme.
46+
/// </param>
47+
public static AuthenticationBuilder AddBasicAuthentication(this AuthenticationBuilder builder, string authenticationScheme)
48+
{
49+
return builder.AddBasicAuthentication(authenticationScheme, null);
50+
}
51+
52+
/// <summary>
53+
/// Adds basic authentication.
54+
/// </summary>
55+
/// <param name="builder">
56+
/// The authentication builder.
57+
/// </param>
58+
/// <param name="configureOptions">
59+
/// The configure options.
60+
/// </param>
61+
public static AuthenticationBuilder AddBasicAuthentication(this AuthenticationBuilder builder, Action<BasicAuthenticationOptions> configureOptions)
62+
{
63+
return builder.AddBasicAuthentication(BasicAuthenticationDefaults.AuthenticationScheme, configureOptions);
64+
}
65+
66+
/// <summary>
67+
/// Adds basic authentication.
68+
/// </summary>
69+
/// <param name="builder">
70+
/// The builder.
71+
/// </param>
72+
/// <param name="authenticationScheme">
73+
/// The authentication scheme.
74+
/// </param>
75+
/// <param name="configureOptions">
76+
/// The configure options.
77+
/// </param>
78+
public static AuthenticationBuilder AddBasicAuthentication(
79+
this AuthenticationBuilder builder,
80+
string authenticationScheme,
81+
Action<BasicAuthenticationOptions> configureOptions)
82+
{
83+
return builder.AddScheme<BasicAuthenticationOptions, BasicAuthenticationHandler>(authenticationScheme, configureOptions);
84+
}
85+
86+
#endregion
87+
}
88+
}

src/ZNetCS.AspNetCore.Authentication.Basic/BasicAuthenticationHandler.cs

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ namespace ZNetCS.AspNetCore.Authentication.Basic
1414
using System;
1515
using System.Linq;
1616
using System.Text;
17+
using System.Text.Encodings.Web;
1718
using System.Threading.Tasks;
1819

1920
using Microsoft.AspNetCore.Authentication;
2021
using Microsoft.AspNetCore.Http;
21-
using Microsoft.AspNetCore.Http.Features.Authentication;
2222
using Microsoft.Extensions.Logging;
23+
using Microsoft.Extensions.Options;
2324
using Microsoft.Net.Http.Headers;
2425

2526
using ZNetCS.AspNetCore.Authentication.Basic.Events;
@@ -41,14 +42,45 @@ namespace ZNetCS.AspNetCore.Authentication.Basic
4142
/// </remarks>
4243
public class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOptions>
4344
{
45+
#region Constants
46+
4447
/// <summary>
4548
/// The scheme name is "Basic".
4649
/// </summary>
47-
private const string Scheme = "Basic";
50+
private const string Basic = "Basic";
51+
52+
#endregion
53+
54+
#region Constructors and Destructors
55+
56+
/// <summary>
57+
/// Initializes a new instance of the <see cref="BasicAuthenticationHandler"/> class.
58+
/// </summary>
59+
/// <param name="options">
60+
/// The options.
61+
/// </param>
62+
/// <param name="logger">
63+
/// The logger.
64+
/// </param>
65+
/// <param name="encoder">
66+
/// The encoder.
67+
/// </param>
68+
/// <param name="clock">
69+
/// The clock.
70+
/// </param>
71+
public BasicAuthenticationHandler(IOptionsMonitor<BasicAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(
72+
options,
73+
logger,
74+
encoder,
75+
clock)
76+
{
77+
}
78+
79+
#endregion
4880

4981
#region Methods
5082

51-
/// <inheritdoc />
83+
/// <inheritdoc/>
5284
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
5385
{
5486
// RFC 7230 section 3.2.2
@@ -58,19 +90,19 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
5890
if ((authorizationHeaderValues == null) || (authorizationHeaderValues.Length == 0))
5991
{
6092
this.Logger.LogDebug("'Authorization' header is not present in the request.");
61-
return AuthenticateResult.Skip();
93+
return AuthenticateResult.NoResult();
6294
}
6395

64-
var basicAuthorizationHeader = authorizationHeaderValues.FirstOrDefault(s => s.StartsWith(Scheme + ' ', StringComparison.OrdinalIgnoreCase));
96+
string basicAuthorizationHeader = authorizationHeaderValues.FirstOrDefault(s => s.StartsWith(Basic + ' ', StringComparison.OrdinalIgnoreCase));
6597

6698
// Authorization header is not 'Basic' so there is nothing to do by this middleware
6799
if (string.IsNullOrEmpty(basicAuthorizationHeader))
68100
{
69101
this.Logger.LogDebug("'Authorization' header is not in 'Basic' scheme in the request.");
70-
return AuthenticateResult.Skip();
102+
return AuthenticateResult.NoResult();
71103
}
72104

73-
var credentials = basicAuthorizationHeader.Replace($"{Scheme} ", string.Empty).Trim();
105+
string credentials = basicAuthorizationHeader.Replace($"{Basic} ", string.Empty).Trim();
74106

75107
if (string.IsNullOrEmpty(credentials))
76108
{
@@ -95,35 +127,21 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
95127
return AuthenticateResult.Fail("The credentials delimiter is not present in 'Basic' scheme.");
96128
}
97129

98-
var userName = decodedCredentials.Substring(0, delimiterIndex);
99-
var password = decodedCredentials.Substring(delimiterIndex + 1);
130+
string userName = decodedCredentials.Substring(0, delimiterIndex);
131+
string password = decodedCredentials.Substring(delimiterIndex + 1);
100132

101-
var context = new ValidatePrincipalContext(this.Context, this.Options, userName, password);
133+
var context = new ValidatePrincipalContext(this.Context, this.Scheme, this.Options, userName, password);
102134
return await this.Options.Events.ValidatePrincipal(context);
103135
}
104136

105-
/// <inheritdoc />
106-
protected override Task HandleSignInAsync(SignInContext context)
107-
{
108-
// Basic authentication have to be resolved on every request.
109-
throw new NotSupportedException();
110-
}
111-
112-
/// <inheritdoc />
113-
protected override Task HandleSignOutAsync(SignOutContext context)
114-
{
115-
// Basic authentication have to be resolved on every request.
116-
throw new NotSupportedException();
117-
}
118-
119-
/// <inheritdoc />
120-
protected override Task<bool> HandleUnauthorizedAsync(ChallengeContext context)
137+
/// <inheritdoc/>
138+
protected override Task HandleChallengeAsync(AuthenticationProperties context)
121139
{
122140
var realmHeader = new NameValueHeaderValue("realm", $"\"{this.Options.Realm}\"");
123141
this.Response.StatusCode = StatusCodes.Status401Unauthorized;
124-
this.Response.Headers.Append(HeaderNames.WWWAuthenticate, $"{Scheme} {realmHeader}");
142+
this.Response.Headers.Append(HeaderNames.WWWAuthenticate, $"{Basic} {realmHeader}");
125143

126-
return Task.FromResult(true);
144+
return Task.CompletedTask;
127145
}
128146

129147
#endregion

src/ZNetCS.AspNetCore.Authentication.Basic/BasicAuthenticationMiddleware.cs

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)