Created
October 12, 2011 00:41
-
-
Save howarddierking/1279891 to your computer and use it in GitHub Desktop.
Web API Operation Handler for initiating a server-driven OAuth2 workflow with Facebook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class OAuthFacebookOpHandler : HttpOperationHandler<HttpRequestMessage, HttpRequestMessage> { | |
readonly Uri _facebookBaseAuthUri = new Uri("https://www.facebook.com/dialog/oauth"); | |
readonly AuthorizeAttribute _authorizationAttribute; | |
readonly string _facebookAppId; | |
public OAuthFacebookOpHandler() : base("response") { } | |
public OAuthFacebookOpHandler(AuthorizeAttribute authorizeAttribute, string appId) : this() { | |
_authorizationAttribute = authorizeAttribute; | |
_facebookAppId = appId; | |
} | |
protected override HttpRequestMessage OnHandle(HttpRequestMessage input) { | |
var identity = GetIdentity(); | |
if (identity == null) | |
{ | |
var challengeMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized); | |
challengeMessage.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("oauth", "location=\"" + BuildFacebookAuthUri(input) + "\"")); | |
throw new HttpResponseException(challengeMessage); | |
} | |
var principle = new GenericPrincipal(identity, new string[0]); | |
//set the thread context | |
Thread.CurrentPrincipal = principle; | |
if(!AuthorizeCore(principle)) | |
throw new HttpResponseException(HttpStatusCode.Forbidden); | |
return input; | |
} | |
// ripped from MVC AuthorizeAttribute (http://aspnet.codeplex.com/SourceControl/changeset/view/70574#266447) | |
// kept the logic but removed dependency on HttpContextBase and use local attribute field (since we're obviously no longer in the AuthorizeAttribute class | |
// calling local copy (and creating local vars for users/roles | |
// also removed virtual since it doesn't matter for this sample - may be worthwhile considering if we want a base class for something like AuthorizationOperationHandler | |
protected bool AuthorizeCore(IPrincipal principal) | |
{ | |
if (!principal.Identity.IsAuthenticated) | |
return false; | |
var usersSplit = SplitString(_authorizationAttribute.Users); | |
if (usersSplit.Length > 0 && !usersSplit.Contains(principal.Identity.Name, StringComparer.OrdinalIgnoreCase)) | |
return false; | |
var rolesSplit = SplitString(_authorizationAttribute.Roles); | |
return rolesSplit.Length <= 0 || rolesSplit.Any(principal.IsInRole); | |
} | |
// ripped from MVC AuthorizeAttribute (http://aspnet.codeplex.com/SourceControl/changeset/view/70574#266447) | |
static string[] SplitString(string original) { | |
if (String.IsNullOrEmpty(original)) { | |
return new string[0]; | |
} | |
var split = from piece in original.Split(',') | |
let trimmed = piece.Trim() | |
where !String.IsNullOrEmpty(trimmed) | |
select trimmed; | |
return split.ToArray(); | |
} | |
Uri BuildFacebookAuthUri(HttpRequestMessage request) { | |
var builder = new UriBuilder(_facebookBaseAuthUri) | |
{ | |
Query = string.Format("client_id={0}&redirect_uri={1}&response_type=code", | |
_facebookAppId, | |
new Uri(request.RequestUri, "authtoken")) | |
}; | |
return builder.Uri; | |
} | |
static IIdentity GetIdentity() { | |
var ticketCookie = HttpContext.Current.Request.Cookies["ticket"]; | |
if (ticketCookie == null) | |
return null; | |
var val = ticketCookie.Value; | |
var ticket = FormsAuthentication.Decrypt(val); | |
var ident = new FormsIdentity(ticket); | |
return ident; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment