Skip to content

Instantly share code, notes, and snippets.

@howarddierking
Created October 12, 2011 00:41
Show Gist options
  • Save howarddierking/1279891 to your computer and use it in GitHub Desktop.
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
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