44383

Retrieving additional profile information from Facebook during external login/register with ASP.NET

There appears to be a lot of documentation on how to get additional information from a Facebook profile using ASP.NET Identity and an MVC client, but I can't seem to find anything on how to access the additional info claims from a Web API controller.

My Startup.Auth.cs ConfigAuth method contains this, which seems to work alright if I breakpoint on JObject wholeUser = context.User

String XmlSchemaString = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims"; var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions() { AppId = "*", AppSecret = "*", Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider() { OnAuthenticated = (context) => { JObject wholeUser = context.User; context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "Facebook")); context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:email", context.Email, XmlSchemaString, "Facebook")); return Task.FromResult(0); } } }; facebookOptions.Scope.Add("email"); app.UseFacebookAuthentication(facebookOptions);

Once authenticated, wholeUser will have all the information I need like birthdate, etc. but once out of this scope, I don't know how to get to it.

I need to get this information in AccountController.RegisterExternal, but I can't seem to configure it correctly. A lot of the MVC doco around uses this in the ExternalLoginCallback method:

ClaimsIdentity claimsIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);

But AuthenticationManager can't be found in Web API, so if I change it to just Authentication, it returns null unless I change the parameter to be DefaultAuthenticationTypes.ExternalBearer. This is as close as I get, but the returned ClaimsIdentity object doesn't have any of the additional claims - just the username and ID.

So overall, it's as though I'm getting the information from Facebook properly and cramming into context.Identity, but then I have no idea how to access it from the controller. N.B: the context object in ConfigAuth is of type Microsoft.Owin.Security.Facebook.FacebookAuthenticatedContext

Answer1:

I'm not sure if you need the same thing that I did, but take a look at http://aliu.ro/easy-mvc4-facebook-authentication-example/

There is a small sample project that does the Facebook Auth, retrieves the access token and makes a call using some .NET SDK that I found in NuGet

Answer2:

I have used the following code here;

var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions { AppId = "*", AppSecret = "**", Provider = new FacebookAuthenticationProvider() { OnAuthenticated = (context) => { context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, ClaimValueTypes.String, "Facebook")); return Task.FromResult(0); } }, }; facebookOptions.Scope.Add("email"); app.UseFacebookAuthentication(facebookOptions);

Now in the RegisterExternal method, the claim is available to me. I just can't figure out how to persist it in the Identity so that it can be used in other Controller calls. If i add the claim to the identity then it seems to break the User.Identity object on other calls;

ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

And the FromIdentity method;

public static ExternalLoginData FromIdentity(ClaimsIdentity identity) { if (identity == null) { return null; } string userEmail = string.Empty; string userFacebookAccessToken = string.Empty; Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier); Claim facebookToken = identity.Claims.First(x => x.Type.Contains("access_token")); Claim emailDetails = identity.FindFirst(ClaimTypes.Email); if (facebookToken != null) userFacebookAccessToken = facebookToken.Value; if (emailDetails != null) userEmail = emailDetails.Value; //string userEmail = identity.Claims.First(x => x.Type.Contains("emailaddress")).Value; if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer) || String.IsNullOrEmpty(providerKeyClaim.Value)) { return null; } if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer) { return null; } return new ExternalLoginData { LoginProvider = providerKeyClaim.Issuer, ProviderKey = providerKeyClaim.Value, UserName = identity.FindFirstValue(ClaimTypes.Name), Email = userEmail, FacebookAccessToken = userFacebookAccessToken }; } }

Recommend

  • How to use InboundClaimTypeMap for claim mapping?
  • Find theta notation of the following while loop
  • How do I inject dependency in owin startup class
  • Unable to access a WebApi from a MVC Web app where both are secured by Azure AD B2C
  • What is the default consistency level in spring-data-cassandra?
  • SNIReadSync executing between 120-500 ms for a simple query. What do I look for?
  • Missing type map configuration or unsupported mapping after auto code generation on the client
  • What's the point of nonfinal singleton objects in scala?
  • How should I start to implement RESTful web service?
  • How do I correctly parse a URI query string into a name-value collection in C#?
  • Can't connect Entity Framework to local SQL Server Express
  • Dynamically set LESS variables from user settings
  • Relative paths. baseUrl and paths not working on ionic2 - angular2
  • PHP CURL timing out but CLI CURL works
  • With Hadoop, can I create a tasktracker on a machine that isn't running a datanode?
  • All Classes Conforming to Protocol Inherit Default Implementation
  • Using variable in a value field in jMeter
  • Adding a button at the bottom of a table view
  • Deleting and Updating values from a cusrsor adapter
  • Is possible to count alias result on mysql
  • Importing jscolor library in angular 2
  • To display the title for the current loaction in map in iphone
  • Properly structure and highlight a GtkPopoverMenu using PyGObject
  • php design question - will a Helper help here?
  • KeystoneJS: Relationships in Admin UI not updating
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • JTable with a ScrollPane misbehaving
  • Angular 2 constructor injection vs direct access
  • Java static initializers and reflection
  • Android Google Maps API OnLocationChanged only called once
  • Turn off referential integrity in Derby? is it possible?
  • Authorize attributes not working in MVC 4
  • Busy indicator not showing up in wpf window [duplicate]
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?
  • Python/Django TangoWithDjango Models and Databases
  • Net Present Value in Excel for Grouped Recurring CF