Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Use [Authorize] Attribute with Token
WTF:
===
- AuthorizeAttribute checks roles of HttpContext.User.
- TokenAuthenticationHandler sets IPrincipal of HttpContext.
- Cookie, HTTP header, query are evaluated by TokenAuthenticationHandler.
- TokenAuthenticationHandler fetches IPrincipal from PrincipalFromTokenCallback.
- Accessing /api/Account/LogOn with a token in query, HTTP header (or Cookie) creates a cookie.
Setup
=====
E.g. in Global.asax:
protected void Application_Start()
{
...
GlobalConfiguration.Configuration.MessageHandlers.Add(
new TokenAuthenticationHandler(SimpleCloudConfigurationManagerSettingsPrincipalProvider.GetPrincipal)
);
...
}
Usage
=====
E.g. in views/Home/Index.cshtml:
<a href="/api/Account/LogOn?apikey=">/api/Account/LogOn?token=</a>
<a href="/api/Account/LogOff">/api/Account/LogOff</a>
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web.Http;
using EventStoreService.Main;
namespace EventStoreService.Controllers
{
public class AccountController : ApiController
{
// GET: api/Account
//public IEnumerable<string> Get()
//{
// return new string[] { "value1", "value2" };
//}
// GET: api/Account/5
public HttpResponseMessage Get(string id)
{
var resp = new HttpResponseMessage();
switch (id) {
case "LogOn": {
if (!RequestContext.Principal.Identity.IsAuthenticated) { throw new UnauthorizedAccessException(); }
var token = HttpRequestMesssageToken.GetToken(Request);
if (string.IsNullOrEmpty(token)) { throw new UnauthorizedAccessException(); }
var cookie = new CookieHeaderValue(HttpRequestMesssageToken.CookieName, token) {
Expires = DateTimeOffset.Now.AddDays(1000),
//Domain = Request.RequestUri.Host, // beware of port number for development environment
Path = "/",
};
resp.Headers.AddCookies(new[] { cookie });
resp.Content = new StringContent("Logged in");
}
break;
case "LogOff": {
var cookie = Request.Headers.GetCookies(HttpRequestMesssageToken.CookieName);
if (cookie != null) {
var newCookie = new CookieHeaderValue(HttpRequestMesssageToken.CookieName, "_loggedout") {
Expires = DateTimeOffset.Now.AddDays(-1),
//Domain = Request.RequestUri.Host,
Path = "/",
};
resp.Headers.AddCookies(new[] { newCookie });
}
resp.Content = new StringContent("Logged out");
}
break;
default: throw new HttpResponseException(HttpStatusCode.NotFound);
}
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return resp;
}
// POST: api/Account
//public void Post([FromBody]string value)
//{
//}
//// PUT: api/Account/5
//public void Put(int id, [FromBody]string value)
//{
//}
//// DELETE: api/Account/5
//public void Delete(int id)
//{
//}
}
}
using System.Linq;
using System.Net.Http;
using System.Web;
namespace EventStoreService.Main
{
public static class HttpRequestMesssageToken
{
public const string QueryKey = "token";
public const string CookieName = "token";
public const string HeaderName = "X-Token";
public static string GetToken(HttpRequestMessage request)
{
string token = "";
if (string.IsNullOrEmpty(token)) {
token = HttpUtility.ParseQueryString(request.RequestUri.Query)[QueryKey];
}
if (string.IsNullOrEmpty(token)) {
token = request.Headers.Contains("X-Token") ? request.Headers.GetValues(HeaderName).FirstOrDefault() : null;
}
if (string.IsNullOrEmpty(token)) {
var cookie = request.Headers.GetCookies(CookieName).FirstOrDefault();
if (cookie != null) {
token = cookie["token"].Value;
}
}
return token;
}
}
}
using System;
using System.Security.Principal;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
namespace EventStoreService.Main
{
public static class SimpleCloudConfigurationManagerSettingsPrincipalProvider
{
public static IPrincipal GetPrincipal(string token)
{
IPrincipal principal = null;
if (!RoleEnvironment.IsAvailable) { throw new Exception("Not running in RoleEnvironment. Wrong startup project?"); }
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
if (principal == null) {
if (token == CloudConfigurationManager.GetSetting("ClientToken")) {
var identity = new GenericIdentity("Client");
principal = new GenericPrincipal(identity, new[] { "Client" });
}
}
if (principal == null) {
if (token == CloudConfigurationManager.GetSetting("AdminToken")) {
var identity = new GenericIdentity("Admin");
principal = new GenericPrincipal(identity, new[] { "Admin" });
}
}
return principal;
}
}
}
using System.Net.Http;
using System.Security.Principal;
using System.Web;
namespace EventStoreService.Main
{
public class TokenAuthenticationHandler : DelegatingHandler
{
public delegate IPrincipal PrincipalFromToken(string token);
private readonly PrincipalFromToken PrincipalFromTokenCallback;
public TokenAuthenticationHandler(PrincipalFromToken callback)
{
PrincipalFromTokenCallback = callback;
}
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var token = HttpRequestMesssageToken.GetToken(request);
var principal = PrincipalFromTokenCallback(token);
if (principal == null) {
return base.SendAsync(request, cancellationToken);
}
var context = request.Properties["MS_HttpContext"] as HttpContextWrapper;
if (context != null) {
context.User = principal;
}
return base.SendAsync(request, cancellationToken);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.