Skip to content

Commit

Permalink
Merge pull request #8 from valeriob/avoid_WWW-Authenticate_header_for…
Browse files Browse the repository at this point in the history
…_ajax_requests

avoid returning WWW-Authenticate header if challenged by an ajax request
  • Loading branch information
msmolka authored Apr 9, 2019
2 parents 4f727e0 + c278d3f commit 44485a5
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 1 deletion.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,21 @@ 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

```c#
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<AuthenticationEvents>();

services
.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
.AddBasicAuthentication(
options =>
{
options.Realm = "My Application";
options.SupressResponseHeaderWWWAuthenticateForAjaxRequests = true;
});
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,19 @@ protected override Task HandleChallengeAsync(AuthenticationProperties context)
{
var realmHeader = new NameValueHeaderValue("realm", $"\"{this.Options.Realm}\"");
this.Response.StatusCode = StatusCodes.Status401Unauthorized;
this.Response.Headers.Append(HeaderNames.WWWAuthenticate, $"{Basic} {realmHeader}");

if (this.Options.SupressResponseHeaderWWWAuthenticateForAjaxRequests)
{
if (this.Request.Headers.TryGetValue(this.Options.AjaxRequestHeaderName, out var value))
{
if (value == this.Options.AjaxRequestHeaderValue)
{
return Task.CompletedTask;
}
}
}

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,6 +24,9 @@ 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 @@ -33,6 +36,8 @@ public BasicAuthenticationOptions()
{
this.Realm = BasicAuthenticationDefaults.Realm;
this.Events = new BasicAuthenticationEvents();
AjaxRequestHeaderName = DefaultAjaxRequestHeaderName;
AjaxRequestHeaderValue = DefaultAjaxRequestHeaderValue;
}

#endregion
Expand Down Expand Up @@ -72,6 +77,14 @@ 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 @@ -274,6 +274,34 @@ public async Task UnauthorizedWrongHeaderTest()
}
}

/// <summary>
/// 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;
})))
{
using (HttpClient client = server.CreateClient())
{
client.DefaultRequestHeaders.Add(Basic.BasicAuthenticationOptions.DefaultAjaxRequestHeaderName, Basic.BasicAuthenticationOptions.DefaultAjaxRequestHeaderValue);

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

// Assert
AuthenticationHeaderValue wwwAuth = response.Headers.WwwAuthenticate.SingleOrDefault();

Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode, "StatusCode != Unauthorized");
Assert.IsNull(wwwAuth, "No header should be sent back on ajax request");
}
}
}

#endregion
}
}

0 comments on commit 44485a5

Please sign in to comment.