存储 OAuth 配置文件信息

我发现 Web API 模板已损坏 - 默认实现依赖于最后一步中的 cookie,你可能不希望在 Rest API 中使用它。如果没有 cookie,RegisterExternal 中的 GetExternalLoginInfoAsync 将始终返回 null。我完全删除了 RegisterExternal,而是在 GetExternalLogin 中创建最终用户帐户 - 从 OAuth 提供程序返回时调用(在本例中为 Google):

[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
[AllowAnonymous]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
{
      if (error != null)
      {
            return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
      }

      if (!User.Identity.IsAuthenticated)
      {
            return new ChallengeResult(provider, this);
      }

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

      if (externalLogin == null)
      {
            return InternalServerError();
      }

      if (externalLogin.LoginProvider != provider)
      {
            Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            return new ChallengeResult(provider, this);
      }

      ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
                externalLogin.ProviderKey));

      bool hasRegistered = user != null;

      if (hasRegistered)
      {
            Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
                
            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);
      }
      else
      {
            var accessToken = Authentication.User.Claims.Where(c => c.Type.Equals("urn:google:accesstoken")).Select(c => c.Value).FirstOrDefault();
            Uri apiRequestUri = new Uri("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + accessToken);

            RegisterExternalBindingModel model = new RegisterExternalBindingModel();

            using (var webClient = new System.Net.WebClient())
            {
                  var json = webClient.DownloadString(apiRequestUri);
                  dynamic jsonResult = JsonConvert.DeserializeObject(json);
                  model.Email = jsonResult.email;
                  model.Picture = jsonResult.picture;
                  model.Family_name = jsonResult.family_name;
                  model.Given_name = jsonResult.given_name;
            }

            var appUser = new ApplicationUser
            {
                  UserName = model.Email,
                  Email = model.Email,
                  ImageUrl = model.Picture,
                  FirstName = model.Given_name,
                  Surname = model.Family_name,
                  DateCreated = DateTime.Now
            };

            var loginInfo = await Authentication.GetExternalLoginInfoAsync();

            IdentityResult result = await UserManager.CreateAsync(appUser);
            if (!result.Succeeded)
            {
                  return GetErrorResult(result);
            }

            result = await UserManager.AddLoginAsync(appUser.Id, loginInfo.Login);
            if (!result.Succeeded)
            {
                  return GetErrorResult(result);
            }

            ClaimsIdentity oAuthIdentity = await appUser.GenerateUserIdentityAsync(UserManager,
                   OAuthDefaults.AuthenticationType);
            ClaimsIdentity cookieIdentity = await appUser.GenerateUserIdentityAsync(UserManager,
                    CookieAuthenticationDefaults.AuthenticationType);

            AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(appUser.UserName);
            Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
      }

      return Ok();
}

这消除了客户端应用程序在收到外部访问令牌后执行不必要的 POST 请求的需要。