Я начал создавать программную архитектуру, в которой у меня есть:
- Auth_API - в качестве сервера аутентификации
- Resource_API - в качестве API ресурса (защищен Auth_API)
- WebApplication (mvc) - приложение внешнего интерфейса (защищено Auth_API).
Основано на статье https://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/. Я успешно провел проверку подлинности Google.
WebApp== перенаправляет на ==> Auth_API == challenge ==> Google ==> API получает externalAccessToken, регистрирует пользователя локально и возвращает localAccessToken
Теперь все в порядке, когда я хочу использоватьавторизация на предъявителя (с использованием локального токена доступа).Но я также хочу войти в приложение ASP MVC с помощью (cookie?) ClaimsIdentity.
Я думал о переходе на 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;
}
Веб-приложение - частьдействия входа в систему:
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");
}
}