Skip to content

Instantly share code, notes, and snippets.

@jamescrowley
Created May 24, 2014 11:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamescrowley/ceb07f1a18f28936ca29 to your computer and use it in GitHub Desktop.
Save jamescrowley/ceb07f1a18f28936ca29 to your computer and use it in GitHub Desktop.
Owin Stateless auth
using System.Security.Claims;
using Microsoft.Owin;
namespace Owin.StatelessAuth
{
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class StatelessAuth : OwinMiddleware
{
private readonly ITokenValidator tokenValidator;
private readonly StatelessAuthOptions statelessAuthOptions;
private readonly ISet<string> ignorePaths;
public StatelessAuth(OwinMiddleware next, ITokenValidator tokenValidator, StatelessAuthOptions statelessAuthOptions)
: base(next)
{
this.tokenValidator = tokenValidator;
this.statelessAuthOptions = statelessAuthOptions;
this.ignorePaths = GetIgnorePaths(statelessAuthOptions);
}
private static ISet<string> GetIgnorePaths(StatelessAuthOptions options)
{
var ignorePaths = new HashSet<string>(options.IgnorePaths, StringComparer.OrdinalIgnoreCase);
if (!string.IsNullOrWhiteSpace(options.RedirectUri))
ignorePaths.Add(options.RedirectUri);
return ignorePaths;
}
public override Task Invoke(IOwinContext ctx)
{
var path = ctx.Request.Path;
if (statelessAuthOptions != null && ignorePaths.Contains(path.ToUriComponent()))
{
return Next.Invoke(ctx);
}
var claims = GetAuthorizationClaims(ctx);
if (claims == null)
{
return ReturnWithUnauthorized(ctx);
}
ctx.Authentication.User = claims;
return Next.Invoke(ctx);
}
private ClaimsPrincipal GetAuthorizationClaims(IOwinContext ctx)
{
var authorizationToken = ctx.Request.Headers["Authorization"];
if (string.IsNullOrWhiteSpace(authorizationToken))
{
return null;
}
return tokenValidator.ValidateToken(authorizationToken);
}
private Task ReturnWithUnauthorized(IOwinContext ctx)
{
ctx.Response.StatusCode = 401;
if (statelessAuthOptions != null && !string.IsNullOrWhiteSpace(statelessAuthOptions.WWWAuthenticateChallenge))
{
var wwwauthenticatechallenge = statelessAuthOptions.WWWAuthenticateChallenge;
ctx.Response.Headers.Add("WWW-Authenticate", new[] { wwwauthenticatechallenge });
}
else if (statelessAuthOptions != null && !string.IsNullOrEmpty(statelessAuthOptions.RedirectUri))
{
if (!ctx.Request.IsAjaxRequest() && ctx.Request.Accept.Contains("text/html"))
{
ctx.Response.Redirect(statelessAuthOptions.RedirectUri);
}
}
return Task.FromResult(0);
}
}
}
using Microsoft.Owin;
namespace Owin.StatelessAuth
{
public static class StatelessAuthExtensions
{
public static IAppBuilder UseStatelessAuth(this IAppBuilder app, ITokenValidator tokenValidator, StatelessAuthOptions options = null)
{
return app.Use<StatelessAuth>(tokenValidator, options);
}
public static bool IsAjaxRequest(this IOwinRequest request)
{
IReadableStringCollection query = request.Query;
if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))
{
return true;
}
IHeaderDictionary headers = request.Headers;
return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest"));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment