ASP.NET Web API 2: Logging in with an External Provider through a Mobile App (iOS)

I searched a lot and could not find the perfect solution to this problem. I know that there is a proposed solution ( WebApi ASP.NET Identity Facebook login ), however, some elements of the solution (in my opinion) are seriously hacked (for example, registering a user with a regular account and then adding an external login, rather than registering them with an external login).

I would like to be able to register and authenticate against the ASP.NET Web API 2 application after you have already used the Facebook SDK login in the iOS mobile application, that is, I have already authenticated using Facebook using their SDKs, and Now you want to easily register / authenticate using the ASP.NET Web API. I do not want to use a process in which I have to use web calls (/ api / Account / ExternalLogin), since this is not very convenient for a regular mobile application.

I tried to learn about OWIN, but the .NET platform is complex and I am struggling to solve this problem.

+8
ios facebook asp.net-web-api owin asp.net-web-api2
source share
1 answer

I needed to do this today for my Ionic app. The web API account controller has its own opinion on how to do this, and the best way to figure it out is with a rather interesting 3-page blog post by Dominic Bayer. https://leastprivilege.com/2013/11/26/dissecting-the-web-api-individual-accounts-templatepart-3-external-accounts/ .

The way I worked on this was to forget the stream out of the box, but instead use accessToken from my own Facebook login and then call the following server code: 1) call the Facebook API to check the access token, 2) from this Facebook call, get the email and ID, 3) either get the user, or create one (and log in), which is already a code that is in the account controller in other places, 4) create a local JWT authority for subsequent calls Web API

public class ProviderAndAccessToken { public string Token { get; set; } public string Provider { get; set; } } [AllowAnonymous] [HttpPost] [Route("JwtFromProviderAccessToken")] public async Task<IHttpActionResult> JwtFromProviderAccessToken(ProviderAndAccessToken model) { string id = null; string userName = null; if (model.Provider == "Facebook") { var fbclient = new Facebook.FacebookClient(model.Token); dynamic fb = fbclient.Get("/me?locale=en_US&fields=name,email"); id = fb.id; userName = fb.email; } //TODO: Google, LinkedIn ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(model.Provider, id)); bool hasRegistered = user != null; string accessToken = null; var identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType); var props = new AuthenticationProperties() { IssuedUtc = DateTime.UtcNow, ExpiresUtc = DateTime.UtcNow.Add(Startup.OAuthOptions.AccessTokenExpireTimeSpan), }; if (hasRegistered) { ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager, OAuthDefaults.AuthenticationType); ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager, CookieAuthenticationDefaults.AuthenticationType); AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName); Authentication.SignIn(properties, oAuthIdentity, cookieIdentity); identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName)); identity.AddClaim(new Claim("role", "user")); } else { user = new ApplicationUser() { UserName = userName, Email = userName }; IdentityResult result = await UserManager.CreateAsync(user); if (!result.Succeeded) { return GetErrorResult(result); } result = await UserManager.AddLoginAsync(user.Id, new UserLoginInfo(model.Provider, id)); if (!result.Succeeded) { return GetErrorResult(result); } identity.AddClaim(new Claim(ClaimTypes.Name, userName)); } identity.AddClaim(new Claim("role", "user")); var ticket = new AuthenticationTicket(identity, props); accessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket); return Ok(accessToken); } 

The code I use in Ionic basically does this in order to get the access token from Facebook and then call the web API to use the local authority JWT to use as the media token.

 Facebook.login(['public_profile', 'email']).then((result) => { return this.http.post("<URL>/api/Account/JwtFromProviderAccessToken", { provider: "Facebook", token: result.authResponse.accessToken }) .map((res: Response) => res.json()) .catch(this.handleError) .subscribe((res: Response) => { // use the result as the Bearer token }); })... 

It seems pretty safe, but understand that I am not a security expert, so this code comes with no guarantee, and please let me know if you see anything blatant and I will update the code.

0
source share

All Articles