我已经开始创建自己拥有的软件体系结构:
根据https://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/的文章,我已经成功进行了Google身份验证。
WebApp ==重定向到==> Auth_API ==挑战==> Google ==> API接收externalAccessToken,在本地注册用户并返回 localAccessToken
现在,当我想使用承载授权(使用本地访问令牌)时,一切正常。 但是我也想使用(cookie?)ClaimsIdentity登录到ASP MVC应用程序。
我当时正在考虑改用JWT,但是我不确定应该走哪条路...
代码位:
Auth_API-获取本地访问令牌
/// <summary>
/// Returns local access token for already registered users
/// </summary>
/// <param name="provider"></param>
/// <param name="externalAccessToken"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpGet]
[Route("ObtainLocalAccessToken")]
public async Task<IHttpActionResult> ObtainLocalAccessToken(string provider, string externalAccessToken)
{
if (string.IsNullOrWhiteSpace(provider) || string.IsNullOrWhiteSpace(externalAccessToken))
{
return BadRequest("Provider or external access token is not sent");
}
var verifiedAccessToken = await VerifyExternalAccessToken(provider, externalAccessToken);
if (verifiedAccessToken == null)
{
return BadRequest("Invalid Provider or External Access Token");
}
IdentityUser user = await _repo.FindAsync(new UserLoginInfo(provider, verifiedAccessToken.user_id));
bool hasRegistered = user != null;
if (!hasRegistered)
{
return BadRequest("External user is not registered");
}
//generate access token response
var accessTokenResponse = GenerateLocalAccessTokenResponse(user.UserName);
return Ok(accessTokenResponse);
}
生成本地访问令牌算法
private JObject GenerateLocalAccessTokenResponse(string userName)
{
var tokenExpiration = TimeSpan.FromDays(1);
ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
identity.AddClaim(new Claim("role", "user"));
var props = new AuthenticationProperties()
{
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.Add(tokenExpiration),
};
var ticket = new AuthenticationTicket(identity, props);
var accessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
JObject tokenResponse = new JObject(
new JProperty("userName", userName),
new JProperty("access_token", accessToken),
new JProperty("token_type", "bearer"),
new JProperty("expires_in", tokenExpiration.TotalSeconds.ToString()),
new JProperty(".issued", ticket.Properties.IssuedUtc.ToString()),
new JProperty(".expires", ticket.Properties.ExpiresUtc.ToString())
);
return tokenResponse;
}
Web应用程序-登录操作的一部分:
if (hasLocalAccount)
{
var client = new RestClient(baseApiUrl);
var externalLoginUrl = "Account/ObtainLocalAccessToken";
var externalLoginRequest = new RestRequest(externalLoginUrl, Method.GET);
externalLoginRequest.AddQueryParameter("provider", provider);
externalLoginRequest.AddQueryParameter("externalAccessToken", externalAccessToken);
var externalLoginResponse = client.Execute(externalLoginRequest);
if (externalLoginResponse.IsSuccessful)
{
JObject response = JObject.Parse(externalLoginResponse.Content);
string localAccessToken = response["access_token"].Value<string>();
string localTokenExpiresIn = response["expires_in"].Value<string>();
// WHAT TO DO WHERE TO SIGN IN A USER ???
//AuthenticationTicket ticket = Startup.OAuthBearerOptions.AccessTokenFormat.Unprotect(localAccessToken); <== this returns NULL
return RedirectToAction("Index", "Home");
}
}