Skip to content

Commit

Permalink
Allow suppress WWWAuthenticate header for Ajax requests.
Browse files Browse the repository at this point in the history
  • Loading branch information
msmolka committed Apr 9, 2019
1 parent 44485a5 commit 5c90147
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 46 deletions.
10 changes: 7 additions & 3 deletions CommonRuleSet.ruleset
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<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">
<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">
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
<Rule Id="CA1001" Action="Warning" />
<Rule Id="CA1009" Action="Warning" />
Expand All @@ -22,6 +22,7 @@
<Rule Id="CA1900" Action="Warning" />
<Rule Id="CA1901" Action="Warning" />
<Rule Id="CA2002" Action="Warning" />
<Rule Id="CA2006" Action="Warning" />
<Rule Id="CA2100" Action="Warning" />
<Rule Id="CA2101" Action="Warning" />
<Rule Id="CA2108" Action="Warning" />
Expand Down Expand Up @@ -66,15 +67,18 @@
</Rules>
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
<Rule Id="IDE0001" Action="None" />
<Rule Id="IDE0003" Action="None" />
<Rule Id="IDE0003" Action="None" />
</Rules>
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
<Rule Id="CA2007" Action="None" />
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1117" Action="None" />
<Rule Id="SA1118" Action="None" />
<Rule Id="SA1124" Action="None" />
<Rule Id="SA1127" Action="None" />
<Rule Id="SA1128" Action="None" />
<Rule Id="SA1413" Action="None" />
<Rule Id="SA1413" Action="None" />
<Rule Id="SA1615" Action="None" />
<Rule Id="SA1616" Action="None" />
<Rule Id="SA1649" Action="None" />
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ When you install the package, it should be added to your `.csproj`. Alternativel

```xml
<ItemGroup>
<PackageReference Include="ZNetCS.AspNetCore.Authentication.Basic" Version="3.0.0" />
<PackageReference Include="ZNetCS.AspNetCore.Authentication.Basic" Version="3.0.1" />
</ItemGroup>
```

Expand Down Expand Up @@ -130,7 +130,7 @@ public void ConfigureServices(IServiceCollection services)
}
```

you can suppress the response WWW-Authenticate header (avoiding the browser to show a popup) for ajax requests by using a switch
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.

```c#
public void ConfigureServices(IServiceCollection services)
Expand All @@ -143,7 +143,7 @@ public void ConfigureServices(IServiceCollection services)
options =>
{
options.Realm = "My Application";
options.SupressResponseHeaderWWWAuthenticateForAjaxRequests = true;
options.AjaxRequestOptions.SuppressWwwAuthenticateHeader = true;
});
}
```
37 changes: 37 additions & 0 deletions src/ZNetCS.AspNetCore.Authentication.Basic/AjaxRequestOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AjaxRequestOptions.cs" company="Marcin Smółka zNET Computer Solutions">
// Copyright (c) Marcin Smółka zNET Computer Solutions. All rights reserved.
// </copyright>
// <summary>
// The ajax request options.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ZNetCS.AspNetCore.Authentication.Basic
{
/// <summary>
/// The ajax request options.
/// </summary>
public class AjaxRequestOptions
{
#region Public Properties

/// <summary>
/// Gets or sets the ajax request header name.
/// </summary>
public string HeaderName { get; set; } = BasicAuthenticationDefaults.AjaxRequestHeaderName;

/// <summary>
/// Gets or sets the ajax request header value.
/// </summary>
public string HeaderValue { get; set; } = BasicAuthenticationDefaults.AjaxRequestHeaderValue;

/// <summary>
/// Gets or sets a value indicating whether suppress sending the WWWAuthenticate response header when a request has the
/// header (X-Requested-With,XMLHttpRequest).
/// </summary>
public bool SuppressWwwAuthenticateHeader { get; set; } = false;

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ public static class BasicAuthenticationDefaults
{
#region Constants

/// <summary>
/// The ajax request header name.
/// </summary>
public const string AjaxRequestHeaderName = "X-Requested-With";

/// <summary>
/// The ajax request header value.
/// </summary>
public const string AjaxRequestHeaderValue = "XMLHttpRequest";

/// <summary>
/// The default value used for BasicAuthenticationOptions.AuthenticationScheme.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ZNetCS.AspNetCore.Authentication.Basic
// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
{
#region Usings

using System;

using Microsoft.AspNetCore.Authentication;

using ZNetCS.AspNetCore.Authentication.Basic;

#endregion

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace ZNetCS.AspNetCore.Authentication.Basic
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;

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

if (this.Options.SupressResponseHeaderWWWAuthenticateForAjaxRequests)
if ((this.Options.AjaxRequestOptions?.SuppressWwwAuthenticateHeader == true)
&& this.Request.Headers.TryGetValue(
this.Options.AjaxRequestOptions?.HeaderName ?? BasicAuthenticationDefaults.AjaxRequestHeaderName,
out StringValues value))
{
if (this.Request.Headers.TryGetValue(this.Options.AjaxRequestHeaderName, out var value))
if (value == (this.Options.AjaxRequestOptions?.HeaderValue ?? BasicAuthenticationDefaults.AjaxRequestHeaderValue))
{
if (value == this.Options.AjaxRequestHeaderValue)
{
return Task.CompletedTask;
}
return Task.CompletedTask;
}
}

var realmHeader = new NameValueHeaderValue("realm", $"\"{this.Options.Realm}\"");
this.Response.Headers.Append(HeaderNames.WWWAuthenticate, $"{Basic} {realmHeader}");
return Task.CompletedTask;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ namespace ZNetCS.AspNetCore.Authentication.Basic
/// </summary>
public class BasicAuthenticationOptions : AuthenticationSchemeOptions
{
public const string DefaultAjaxRequestHeaderName = "X-Requested-With";
public const string DefaultAjaxRequestHeaderValue = "XMLHttpRequest";

#region Constructors and Destructors

/// <summary>
Expand All @@ -36,14 +33,18 @@ public BasicAuthenticationOptions()
{
this.Realm = BasicAuthenticationDefaults.Realm;
this.Events = new BasicAuthenticationEvents();
AjaxRequestHeaderName = DefaultAjaxRequestHeaderName;
AjaxRequestHeaderValue = DefaultAjaxRequestHeaderValue;
this.AjaxRequestOptions = new AjaxRequestOptions();
}

#endregion

#region Public Properties

/// <summary>
/// Gets or sets the ajax request options.
/// </summary>
public AjaxRequestOptions AjaxRequestOptions { get; set; }

/// <summary>
/// Gets or sets basic authentication events. The Provider may be assigned to an instance of an object created
/// by the application at startup time. The handler calls methods on the provider which give the application
Expand Down Expand Up @@ -77,14 +78,6 @@ public BasicAuthenticationOptions()
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "OK")]
public string Realm { get; set; }

/// <summary>
/// If enabled, it suppress sending the WWWAuthenticate response header when a request has the header (X-Requested-With,XMLHttpRequest)
/// </summary>
public bool SupressResponseHeaderWWWAuthenticateForAjaxRequests { get; set; }

public string AjaxRequestHeaderName { get; set; }

public string AjaxRequestHeaderValue { get; set; }
#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
<PackageLicenseUrl>https://raw.githubusercontent.com/msmolka/ZNetCS.AspNetCore.Authentication.Basic/master/LICENSE</PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/msmolka/ZNetCS.AspNetCore.Authentication.Basic</RepositoryUrl>
<VersionPrefix>3.0.0</VersionPrefix>
<VersionPrefix>3.0.1</VersionPrefix>
<NoWarn>$(NoWarn);NU5125</NoWarn> <!-- remove once tools are truly ready for NuGet's new 'license' element -->
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
Expand All @@ -37,13 +38,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.0.0" />
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta004">
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.1-rc.114">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,20 +275,20 @@ public async Task UnauthorizedWrongHeaderTest()
}

/// <summary>
/// The unauthorized basic realm via ajax
/// The unauthorized basic realm via ajax.
/// </summary>
[TestMethod]
public async Task UnauthorizedMyRealmTestAjaxRequestSuppressed()
{
using (var server = new TestServer(WebHostBuilderHelper.CreateBuilder(o =>
{
o.Realm = "My realm";
o.SupressResponseHeaderWWWAuthenticateForAjaxRequests = true;
o.AjaxRequestOptions.SuppressWwwAuthenticateHeader = true;
})))
{
using (HttpClient client = server.CreateClient())
{
client.DefaultRequestHeaders.Add(Basic.BasicAuthenticationOptions.DefaultAjaxRequestHeaderName, Basic.BasicAuthenticationOptions.DefaultAjaxRequestHeaderValue);
client.DefaultRequestHeaders.Add(Basic.BasicAuthenticationDefaults.AjaxRequestHeaderName, Basic.BasicAuthenticationDefaults.AjaxRequestHeaderValue);

// Act
HttpResponseMessage response = await client.GetAsync("api/test");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.1" />
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.2.0" />
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta004">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
Expand Down

0 comments on commit 5c90147

Please sign in to comment.