Skip to content

Commit a07fe7e

Browse files
authored
Merge pull request #5 from mihirdilip/5.0.0
5.0.0
2 parents a877f5d + 077509e commit a07fe7e

17 files changed

+406
-56
lines changed

README.md

+10-6
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ public class Startup
5252
services.AddControllers();
5353

5454
//// By default, authentication is not challenged for every request which is ASP.NET Core's default intended behaviour.
55-
//// So to challenge authentication for every requests please use below option instead of above services.AddControllers().
56-
//services.AddControllers(options =>
55+
//// So to challenge authentication for every requests please use below FallbackPolicy option.
56+
//services.AddAuthorization(options =>
5757
//{
58-
// options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()));
58+
// options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
5959
//});
6060
}
6161

@@ -153,6 +153,10 @@ Default value is false.
153153
When set to true, it will NOT return WWW-Authenticate response header when challenging un-authenticated requests.
154154
When set to false, it will return WWW-Authenticate response header when challenging un-authenticated requests.
155155

156+
#### IgnoreAuthenticationIfAllowAnonymous
157+
Default value is false.
158+
If set to true, it checks if AllowAnonymous filter on controller action or metadata on the endpoint which, if found, it does not try to authenticate the request.
159+
156160
#### Events
157161
The object provided by the application to process events raised by the basic authentication middleware.
158162
The application may implement the interface fully, or it may create an instance of BasicEvents and assign delegates only to the events it wants to process.
@@ -187,9 +191,9 @@ Please note that, by default, with ASP.NET Core, all the requests are not challe
187191
However, if you want all the requests to challenge authentication by default, depending on what you are using, you can add the below options line to *ConfigureServices* method on *Startup* class.
188192

189193
```C#
190-
services.AddControllers(options =>
191-
{
192-
options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()));
194+
services.AddAuthorization(options =>
195+
{
196+
options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
193197
});
194198

195199
// OR

samples/SampleWebApi_2_0/SampleWebApi_2_0.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</ItemGroup>
1313

1414
<ItemGroup>
15-
<PackageReference Include="AspNetCore.Authentication.Basic" Version="3.1.1" />
15+
<PackageReference Include="AspNetCore.Authentication.Basic" Version="5.0.0" />
1616
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
1717
</ItemGroup>
1818

samples/SampleWebApi_2_2/SampleWebApi_2_2.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<PackageReference Include="AspNetCore.Authentication.Basic" Version="3.1.1" />
9+
<PackageReference Include="AspNetCore.Authentication.Basic" Version="5.0.0" />
1010
<PackageReference Include="Microsoft.AspNetCore.App" />
1111
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
1212
</ItemGroup>

samples/SampleWebApi_3_1/SampleWebApi_3_1.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Import Project="..\SampleWebApi.Shared\SampleWebApi.Shared.projitems" Label="Shared" />
88

99
<ItemGroup>
10-
<PackageReference Include="AspNetCore.Authentication.Basic" Version="3.1.1" />
10+
<PackageReference Include="AspNetCore.Authentication.Basic" Version="5.0.0" />
1111
</ItemGroup>
1212

1313
<!--<ItemGroup>

samples/SampleWebApi_3_1/Startup.cs

+14-5
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ public void ConfigureServices(IServiceCollection services)
4848
//// Optional option to suppress the browser login dialog for ajax calls.
4949
//options.SuppressWWWAuthenticateHeader = true;
5050

51+
//// Optional option to ignore authentication if AllowAnonumous metadata/filter attribute is added to an endpoint.
52+
//options.IgnoreAuthenticationIfAllowAnonymous = true;
53+
5154
//// Optional events to override the basic original logic with custom logic.
5255
//// Only use this if you know what you are doing at your own risk. Any of the events can be assigned.
5356
options.Events = new BasicEvents
@@ -149,13 +152,19 @@ public void ConfigureServices(IServiceCollection services)
149152

150153
services.AddControllers(options =>
151154
{
152-
// ALWAYS USE HTTPS (SSL) protocol in production when using Basic authentication.
155+
// ALWAYS USE HTTPS (SSL) protocol in production when using ApiKey authentication.
153156
//options.Filters.Add<RequireHttpsAttribute>();
154157

155-
// All the requests will need to be authorized.
156-
// Alternatively, add [Authorize] attribute to Controller or Action Method where necessary.
157-
options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()));
158158
}); //.AddXmlSerializerFormatters() // To enable XML along with JSON;
159+
160+
// All the requests will need to be authorized.
161+
// Alternatively, add [Authorize] attribute to Controller or Action Method where necessary.
162+
services.AddAuthorization(options =>
163+
{
164+
options.FallbackPolicy = new AuthorizationPolicyBuilder()
165+
.RequireAuthenticatedUser()
166+
.Build();
167+
});
159168
}
160169

161170
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -170,7 +179,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
170179

171180
app.UseHttpsRedirection();
172181
app.UseRouting();
173-
182+
174183
app.UseAuthentication(); // NOTE: DEFAULT TEMPLATE DOES NOT HAVE THIS, THIS LINE IS REQUIRED AND HAS TO BE ADDED!!!
175184

176185
app.UseAuthorization();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace SampleWebApi_5_0.Controllers
6+
{
7+
[Route("api/[controller]")]
8+
[ApiController]
9+
public class ValuesController : ControllerBase
10+
{
11+
// GET api/values
12+
[HttpGet]
13+
public ActionResult<IEnumerable<string>> Get()
14+
{
15+
return new string[] { "value1", "value2" };
16+
}
17+
18+
[HttpGet("claims")]
19+
public ActionResult<string> Claims()
20+
{
21+
var sb = new StringBuilder();
22+
foreach (var claim in User.Claims)
23+
{
24+
sb.AppendLine($"{claim.Type}: {claim.Value}");
25+
}
26+
return sb.ToString();
27+
}
28+
29+
[HttpGet("forbid")]
30+
public new IActionResult Forbid()
31+
{
32+
return base.Forbid();
33+
}
34+
}
35+
}

samples/SampleWebApi_5_0/Program.cs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Microsoft.AspNetCore.Hosting;
2+
using Microsoft.Extensions.Hosting;
3+
4+
namespace SampleWebApi_5_0
5+
{
6+
public class Program
7+
{
8+
public static void Main(string[] args)
9+
{
10+
CreateHostBuilder(args).Build().Run();
11+
}
12+
13+
public static IHostBuilder CreateHostBuilder(string[] args) =>
14+
Host.CreateDefaultBuilder(args)
15+
.ConfigureWebHostDefaults(webBuilder =>
16+
{
17+
webBuilder.UseStartup<Startup>();
18+
});
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"iisSettings": {
3+
"windowsAuthentication": false,
4+
"anonymousAuthentication": true,
5+
"iisExpress": {
6+
"applicationUrl": "http://localhost:3920",
7+
"sslPort": 44304
8+
}
9+
},
10+
"profiles": {
11+
"IIS Express": {
12+
"commandName": "IISExpress",
13+
"launchBrowser": true,
14+
"launchUrl": "api/values",
15+
"environmentVariables": {
16+
"ASPNETCORE_ENVIRONMENT": "Development"
17+
}
18+
}
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net5.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<Import Project="..\SampleWebApi.Shared\SampleWebApi.Shared.projitems" Label="Shared" />
8+
9+
<ItemGroup>
10+
<PackageReference Include="AspNetCore.Authentication.Basic" Version="5.0.0" />
11+
</ItemGroup>
12+
13+
<!--<ItemGroup>
14+
<ProjectReference Include="..\..\src\AspNetCore.Authentication.Basic\AspNetCore.Authentication.Basic.csproj" />
15+
</ItemGroup>-->
16+
17+
</Project>

samples/SampleWebApi_5_0/Startup.cs

+192
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
using AspNetCore.Authentication.Basic;
2+
using Microsoft.AspNetCore.Authorization;
3+
using Microsoft.AspNetCore.Builder;
4+
using Microsoft.AspNetCore.Hosting;
5+
using Microsoft.AspNetCore.Http;
6+
using Microsoft.AspNetCore.Mvc.Authorization;
7+
using Microsoft.Extensions.Configuration;
8+
using Microsoft.Extensions.DependencyInjection;
9+
using Microsoft.Extensions.Hosting;
10+
using SampleWebApi.Repositories;
11+
using SampleWebApi.Services;
12+
using System.Collections.Generic;
13+
using System.Security.Claims;
14+
using System.Threading.Tasks;
15+
16+
namespace SampleWebApi_5_0
17+
{
18+
public class Startup
19+
{
20+
public Startup(IConfiguration configuration)
21+
{
22+
Configuration = configuration;
23+
}
24+
25+
public IConfiguration Configuration { get; }
26+
27+
// This method gets called by the runtime. Use this method to add services to the container.
28+
public void ConfigureServices(IServiceCollection services)
29+
{
30+
// Add User repository to the dependency container.
31+
services.AddTransient<IUserRepository, InMemoryUserRepository>();
32+
33+
// Add the Basic scheme authentication here..
34+
// It requires Realm to be set in the options if SuppressWWWAuthenticateHeader is not set.
35+
// If an implementation of IBasicUserValidationService interface is registered in the dependency register as well as OnValidateCredentials delegete on options.Events is also set then this delegate will be used instead of an implementation of IBasicUserValidationService.
36+
services.AddAuthentication(BasicDefaults.AuthenticationScheme)
37+
38+
// The below AddBasic without type parameter will require OnValidateCredentials delegete on options.Events to be set unless an implementation of IBasicUserValidationService interface is registered in the dependency register.
39+
// Please note if both the delgate and validation server are set then the delegate will be used instead of BasicUserValidationService.
40+
//.AddBasic(options =>
41+
42+
// The below AddBasic with type parameter will add the BasicUserValidationService to the dependency register.
43+
// Please note if OnValidateCredentials delegete on options.Events is also set then this delegate will be used instead of BasicUserValidationService.
44+
.AddBasic<BasicUserValidationService>(options =>
45+
{
46+
options.Realm = "Sample Web API";
47+
48+
//// Optional option to suppress the browser login dialog for ajax calls.
49+
//options.SuppressWWWAuthenticateHeader = true;
50+
51+
//// Optional option to ignore authentication if AllowAnonumous metadata/filter attribute is added to an endpoint.
52+
//options.IgnoreAuthenticationIfAllowAnonymous = true;
53+
54+
//// Optional events to override the basic original logic with custom logic.
55+
//// Only use this if you know what you are doing at your own risk. Any of the events can be assigned.
56+
options.Events = new BasicEvents
57+
{
58+
59+
//// A delegate assigned to this property will be invoked just before validating credentials.
60+
//OnValidateCredentials = async (context) =>
61+
//{
62+
// // custom code to handle credentials, create principal and call Success method on context.
63+
// var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
64+
// var user = await userRepository.GetUserByUsername(context.Username);
65+
// var isValid = user != null && user.Password == context.Password;
66+
// if (isValid)
67+
// {
68+
// context.Response.Headers.Add("ValidationCustomHeader", "From OnValidateCredentials");
69+
// var claims = new[]
70+
// {
71+
// new Claim(ClaimTypes.NameIdentifier, context.Username, ClaimValueTypes.String, context.Options.ClaimsIssuer),
72+
// new Claim(ClaimTypes.Name, context.Username, ClaimValueTypes.String, context.Options.ClaimsIssuer),
73+
// new Claim("CustomClaimType", "Custom Claim Value - from OnValidateCredentials")
74+
// };
75+
// context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
76+
// context.Success();
77+
// }
78+
// else
79+
// {
80+
// context.NoResult();
81+
// }
82+
//},
83+
84+
//// A delegate assigned to this property will be invoked just before validating credentials.
85+
//// NOTE: Same as above delegate but slightly different implementation which will give same result.
86+
//OnValidateCredentials = async (context) =>
87+
//{
88+
// // custom code to handle credentials, create principal and call Success method on context.
89+
// var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
90+
// var user = await userRepository.GetUserByUsername(context.Username);
91+
// var isValid = user != null && user.Password == context.Password;
92+
// if (isValid)
93+
// {
94+
// context.Response.Headers.Add("ValidationCustomHeader", "From OnValidateCredentials");
95+
// var claims = new[]
96+
// {
97+
// new Claim("CustomClaimType", "Custom Claim Value - from OnValidateCredentials")
98+
// };
99+
// context.ValidationSucceeded(claims); // claims are optional
100+
// }
101+
// else
102+
// {
103+
// context.ValidationFailed();
104+
// }
105+
//},
106+
107+
//// A delegate assigned to this property will be invoked before a challenge is sent back to the caller when handling unauthorized response.
108+
//OnHandleChallenge = async (context) =>
109+
//{
110+
// // custom code to handle authentication challenge unauthorized response.
111+
// context.Response.StatusCode = StatusCodes.Status401Unauthorized;
112+
// context.Response.Headers.Add("ChallengeCustomHeader", "From OnHandleChallenge");
113+
// await context.Response.WriteAsync("{\"CustomBody\":\"From OnHandleChallenge\"}");
114+
// context.Handled(); // important! do not forget to call this method at the end.
115+
//},
116+
117+
//// A delegate assigned to this property will be invoked if Authorization fails and results in a Forbidden response.
118+
//OnHandleForbidden = async (context) =>
119+
//{
120+
// // custom code to handle forbidden response.
121+
// context.Response.StatusCode = StatusCodes.Status403Forbidden;
122+
// context.Response.Headers.Add("ForbidCustomHeader", "From OnHandleForbidden");
123+
// await context.Response.WriteAsync("{\"CustomBody\":\"From OnHandleForbidden\"}");
124+
// context.Handled(); // important! do not forget to call this method at the end.
125+
//},
126+
127+
//// A delegate assigned to this property will be invoked when the authentication succeeds. It will not be called if OnValidateCredentials delegate is assigned.
128+
//// It can be used for adding claims, headers, etc to the response.
129+
//OnAuthenticationSucceeded = (context) =>
130+
//{
131+
// //custom code to add extra bits to the success response.
132+
// context.Response.Headers.Add("SuccessCustomHeader", "From OnAuthenticationSucceeded");
133+
// var customClaims = new List<Claim>
134+
// {
135+
// new Claim("CustomClaimType", "Custom Claim Value - from OnAuthenticationSucceeded")
136+
// };
137+
// context.AddClaims(customClaims);
138+
// //or can add like this - context.Principal.AddIdentity(new ClaimsIdentity(customClaims));
139+
// return Task.CompletedTask;
140+
//},
141+
142+
//// A delegate assigned to this property will be invoked when the authentication fails.
143+
//OnAuthenticationFailed = (context) =>
144+
//{
145+
// // custom code to handle failed authentication.
146+
// context.Fail("Failed to authenticate");
147+
// return Task.CompletedTask;
148+
//}
149+
150+
};
151+
});
152+
153+
services.AddControllers(options =>
154+
{
155+
// ALWAYS USE HTTPS (SSL) protocol in production when using ApiKey authentication.
156+
//options.Filters.Add<RequireHttpsAttribute>();
157+
158+
}); //.AddXmlSerializerFormatters() // To enable XML along with JSON;
159+
160+
// All the requests will need to be authorized.
161+
// Alternatively, add [Authorize] attribute to Controller or Action Method where necessary.
162+
services.AddAuthorization(options =>
163+
{
164+
options.FallbackPolicy = new AuthorizationPolicyBuilder()
165+
.RequireAuthenticatedUser()
166+
.Build();
167+
});
168+
}
169+
170+
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
171+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
172+
{
173+
if (env.IsDevelopment())
174+
{
175+
app.UseDeveloperExceptionPage();
176+
}
177+
178+
// The below order of pipeline chain is important!
179+
180+
app.UseHttpsRedirection();
181+
app.UseRouting();
182+
183+
app.UseAuthentication(); // NOTE: DEFAULT TEMPLATE DOES NOT HAVE THIS, THIS LINE IS REQUIRED AND HAS TO BE ADDED!!!
184+
185+
app.UseAuthorization();
186+
app.UseEndpoints(endpoints =>
187+
{
188+
endpoints.MapControllers();
189+
});
190+
}
191+
}
192+
}

0 commit comments

Comments
 (0)