Skip to content

Commit 5c90147

Browse files
committed
Allow suppress WWWAuthenticate header for Ajax requests.
1 parent 44485a5 commit 5c90147

File tree

10 files changed

+95
-46
lines changed

10 files changed

+95
-46
lines changed

CommonRuleSet.ruleset

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<RuleSet Name="Common Rules" Description="These rules focus on the most critical problems in your code, including potential security holes, application crashes, and other important logic and design errors. You should include this rule set in any custom rule set you create for your projects." ToolsVersion="14.0">
2+
<RuleSet Name="Common Rules" Description="These rules focus on the most critical problems in your code, including potential security holes, application crashes, and other important logic and design errors. You should include this rule set in any custom rule set you create for your projects." ToolsVersion="16.0">
33
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
44
<Rule Id="CA1001" Action="Warning" />
55
<Rule Id="CA1009" Action="Warning" />
@@ -22,6 +22,7 @@
2222
<Rule Id="CA1900" Action="Warning" />
2323
<Rule Id="CA1901" Action="Warning" />
2424
<Rule Id="CA2002" Action="Warning" />
25+
<Rule Id="CA2006" Action="Warning" />
2526
<Rule Id="CA2100" Action="Warning" />
2627
<Rule Id="CA2101" Action="Warning" />
2728
<Rule Id="CA2108" Action="Warning" />
@@ -66,15 +67,18 @@
6667
</Rules>
6768
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
6869
<Rule Id="IDE0001" Action="None" />
69-
<Rule Id="IDE0003" Action="None" />
70+
<Rule Id="IDE0003" Action="None" />
71+
</Rules>
72+
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
73+
<Rule Id="CA2007" Action="None" />
7074
</Rules>
7175
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
7276
<Rule Id="SA1117" Action="None" />
7377
<Rule Id="SA1118" Action="None" />
7478
<Rule Id="SA1124" Action="None" />
7579
<Rule Id="SA1127" Action="None" />
7680
<Rule Id="SA1128" Action="None" />
77-
<Rule Id="SA1413" Action="None" />
81+
<Rule Id="SA1413" Action="None" />
7882
<Rule Id="SA1615" Action="None" />
7983
<Rule Id="SA1616" Action="None" />
8084
<Rule Id="SA1649" Action="None" />

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ When you install the package, it should be added to your `.csproj`. Alternativel
2323

2424
```xml
2525
<ItemGroup>
26-
<PackageReference Include="ZNetCS.AspNetCore.Authentication.Basic" Version="3.0.0" />
26+
<PackageReference Include="ZNetCS.AspNetCore.Authentication.Basic" Version="3.0.1" />
2727
</ItemGroup>
2828
```
2929

@@ -130,7 +130,7 @@ public void ConfigureServices(IServiceCollection services)
130130
}
131131
```
132132

133-
you can suppress the response WWW-Authenticate header (avoiding the browser to show a popup) for ajax requests by using a switch
133+
As from version 3.0.1 You can suppress the response WWW-Authenticate header (avoiding the browser to show a popup) for ajax requests by using a switch.
134134

135135
```c#
136136
public void ConfigureServices(IServiceCollection services)
@@ -143,7 +143,7 @@ public void ConfigureServices(IServiceCollection services)
143143
options =>
144144
{
145145
options.Realm = "My Application";
146-
options.SupressResponseHeaderWWWAuthenticateForAjaxRequests = true;
146+
options.AjaxRequestOptions.SuppressWwwAuthenticateHeader = true;
147147
});
148148
}
149149
```
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// --------------------------------------------------------------------------------------------------------------------
2+
// <copyright file="AjaxRequestOptions.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 ajax request options.
7+
// </summary>
8+
// --------------------------------------------------------------------------------------------------------------------
9+
10+
namespace ZNetCS.AspNetCore.Authentication.Basic
11+
{
12+
/// <summary>
13+
/// The ajax request options.
14+
/// </summary>
15+
public class AjaxRequestOptions
16+
{
17+
#region Public Properties
18+
19+
/// <summary>
20+
/// Gets or sets the ajax request header name.
21+
/// </summary>
22+
public string HeaderName { get; set; } = BasicAuthenticationDefaults.AjaxRequestHeaderName;
23+
24+
/// <summary>
25+
/// Gets or sets the ajax request header value.
26+
/// </summary>
27+
public string HeaderValue { get; set; } = BasicAuthenticationDefaults.AjaxRequestHeaderValue;
28+
29+
/// <summary>
30+
/// Gets or sets a value indicating whether suppress sending the WWWAuthenticate response header when a request has the
31+
/// header (X-Requested-With,XMLHttpRequest).
32+
/// </summary>
33+
public bool SuppressWwwAuthenticateHeader { get; set; } = false;
34+
35+
#endregion
36+
}
37+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ public static class BasicAuthenticationDefaults
1616
{
1717
#region Constants
1818

19+
/// <summary>
20+
/// The ajax request header name.
21+
/// </summary>
22+
public const string AjaxRequestHeaderName = "X-Requested-With";
23+
24+
/// <summary>
25+
/// The ajax request header value.
26+
/// </summary>
27+
public const string AjaxRequestHeaderValue = "XMLHttpRequest";
28+
1929
/// <summary>
2030
/// The default value used for BasicAuthenticationOptions.AuthenticationScheme.
2131
/// </summary>

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@
77
// </summary>
88
// --------------------------------------------------------------------------------------------------------------------
99

10-
namespace ZNetCS.AspNetCore.Authentication.Basic
10+
// ReSharper disable once CheckNamespace
11+
namespace Microsoft.Extensions.DependencyInjection
1112
{
1213
#region Usings
1314

1415
using System;
1516

1617
using Microsoft.AspNetCore.Authentication;
1718

19+
using ZNetCS.AspNetCore.Authentication.Basic;
20+
1821
#endregion
1922

2023
/// <summary>

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace ZNetCS.AspNetCore.Authentication.Basic
2121
using Microsoft.AspNetCore.Http;
2222
using Microsoft.Extensions.Logging;
2323
using Microsoft.Extensions.Options;
24+
using Microsoft.Extensions.Primitives;
2425
using Microsoft.Net.Http.Headers;
2526

2627
using ZNetCS.AspNetCore.Authentication.Basic.Events;
@@ -162,20 +163,20 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
162163
/// <inheritdoc/>
163164
protected override Task HandleChallengeAsync(AuthenticationProperties context)
164165
{
165-
var realmHeader = new NameValueHeaderValue("realm", $"\"{this.Options.Realm}\"");
166166
this.Response.StatusCode = StatusCodes.Status401Unauthorized;
167167

168-
if (this.Options.SupressResponseHeaderWWWAuthenticateForAjaxRequests)
168+
if ((this.Options.AjaxRequestOptions?.SuppressWwwAuthenticateHeader == true)
169+
&& this.Request.Headers.TryGetValue(
170+
this.Options.AjaxRequestOptions?.HeaderName ?? BasicAuthenticationDefaults.AjaxRequestHeaderName,
171+
out StringValues value))
169172
{
170-
if (this.Request.Headers.TryGetValue(this.Options.AjaxRequestHeaderName, out var value))
173+
if (value == (this.Options.AjaxRequestOptions?.HeaderValue ?? BasicAuthenticationDefaults.AjaxRequestHeaderValue))
171174
{
172-
if (value == this.Options.AjaxRequestHeaderValue)
173-
{
174-
return Task.CompletedTask;
175-
}
175+
return Task.CompletedTask;
176176
}
177177
}
178178

179+
var realmHeader = new NameValueHeaderValue("realm", $"\"{this.Options.Realm}\"");
179180
this.Response.Headers.Append(HeaderNames.WWWAuthenticate, $"{Basic} {realmHeader}");
180181
return Task.CompletedTask;
181182
}

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

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ namespace ZNetCS.AspNetCore.Authentication.Basic
2424
/// </summary>
2525
public class BasicAuthenticationOptions : AuthenticationSchemeOptions
2626
{
27-
public const string DefaultAjaxRequestHeaderName = "X-Requested-With";
28-
public const string DefaultAjaxRequestHeaderValue = "XMLHttpRequest";
29-
3027
#region Constructors and Destructors
3128

3229
/// <summary>
@@ -36,14 +33,18 @@ public BasicAuthenticationOptions()
3633
{
3734
this.Realm = BasicAuthenticationDefaults.Realm;
3835
this.Events = new BasicAuthenticationEvents();
39-
AjaxRequestHeaderName = DefaultAjaxRequestHeaderName;
40-
AjaxRequestHeaderValue = DefaultAjaxRequestHeaderValue;
36+
this.AjaxRequestOptions = new AjaxRequestOptions();
4137
}
4238

4339
#endregion
4440

4541
#region Public Properties
4642

43+
/// <summary>
44+
/// Gets or sets the ajax request options.
45+
/// </summary>
46+
public AjaxRequestOptions AjaxRequestOptions { get; set; }
47+
4748
/// <summary>
4849
/// Gets or sets basic authentication events. The Provider may be assigned to an instance of an object created
4950
/// by the application at startup time. The handler calls methods on the provider which give the application
@@ -77,14 +78,6 @@ public BasicAuthenticationOptions()
7778
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "OK")]
7879
public string Realm { get; set; }
7980

80-
/// <summary>
81-
/// If enabled, it suppress sending the WWWAuthenticate response header when a request has the header (X-Requested-With,XMLHttpRequest)
82-
/// </summary>
83-
public bool SupressResponseHeaderWWWAuthenticateForAjaxRequests { get; set; }
84-
85-
public string AjaxRequestHeaderName { get; set; }
86-
87-
public string AjaxRequestHeaderValue { get; set; }
8881
#endregion
8982
}
9083
}

src/ZNetCS.AspNetCore.Authentication.Basic/ZNetCS.AspNetCore.Authentication.Basic.csproj

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
<PackageLicenseUrl>https://raw.githubusercontent.com/msmolka/ZNetCS.AspNetCore.Authentication.Basic/master/LICENSE</PackageLicenseUrl>
1414
<RepositoryType>git</RepositoryType>
1515
<RepositoryUrl>https://github.com/msmolka/ZNetCS.AspNetCore.Authentication.Basic</RepositoryUrl>
16-
<VersionPrefix>3.0.0</VersionPrefix>
16+
<VersionPrefix>3.0.1</VersionPrefix>
17+
<NoWarn>$(NoWarn);NU5125</NoWarn> <!-- remove once tools are truly ready for NuGet's new 'license' element -->
1718
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
1819
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
1920
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
@@ -37,13 +38,13 @@
3738
</PropertyGroup>
3839

3940
<ItemGroup>
40-
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.0.1" />
41-
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.0.1" />
42-
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.0.0" />
43-
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
44-
<PackageReference Include="Microsoft.Extensions.Options" Version="2.0.0" />
45-
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.0.1" />
46-
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta004">
41+
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
42+
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
43+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.0" />
44+
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
45+
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
46+
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.0" />
47+
<PackageReference Include="StyleCop.Analyzers" Version="1.1.1-rc.114">
4748
<PrivateAssets>All</PrivateAssets>
4849
</PackageReference>
4950
</ItemGroup>

test/ZNetCS.AspNetCore.Authentication.BasicTests/AuthorizationTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,20 @@ public async Task UnauthorizedWrongHeaderTest()
275275
}
276276

277277
/// <summary>
278-
/// The unauthorized basic realm via ajax
278+
/// The unauthorized basic realm via ajax.
279279
/// </summary>
280280
[TestMethod]
281281
public async Task UnauthorizedMyRealmTestAjaxRequestSuppressed()
282282
{
283283
using (var server = new TestServer(WebHostBuilderHelper.CreateBuilder(o =>
284284
{
285285
o.Realm = "My realm";
286-
o.SupressResponseHeaderWWWAuthenticateForAjaxRequests = true;
286+
o.AjaxRequestOptions.SuppressWwwAuthenticateHeader = true;
287287
})))
288288
{
289289
using (HttpClient client = server.CreateClient())
290290
{
291-
client.DefaultRequestHeaders.Add(Basic.BasicAuthenticationOptions.DefaultAjaxRequestHeaderName, Basic.BasicAuthenticationOptions.DefaultAjaxRequestHeaderValue);
291+
client.DefaultRequestHeaders.Add(Basic.BasicAuthenticationDefaults.AjaxRequestHeaderName, Basic.BasicAuthenticationDefaults.AjaxRequestHeaderValue);
292292

293293
// Act
294294
HttpResponseMessage response = await client.GetAsync("api/test");

test/ZNetCS.AspNetCore.Authentication.BasicTests/ZNetCS.AspNetCore.Authentication.BasicTests.csproj

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
</PropertyGroup>
2323

2424
<ItemGroup>
25-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
26-
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.1" />
27-
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.0.1" />
28-
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.2" />
29-
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
30-
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
31-
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
32-
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
25+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
26+
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.2.0" />
27+
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.0" />
28+
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
29+
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.2.0" />
30+
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.2.0" />
31+
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
32+
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
3333
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta004">
3434
<PrivateAssets>All</PrivateAssets>
3535
</PackageReference>

0 commit comments

Comments
 (0)