Используя токен обновления для получения нового токена доступа, я хочу обновить свой файл cookie на стороне клиента этим токеном доступа.
Мой клиент может войти в систему и вызвать мой REST API с помощью ajax, однако, когда истекает время первой авторизации, вызовы API больше не работают.
У меня есть веб-приложение .NET, которое использует собственный REST API. API является частью одного и того же проекта. У него нет собственной конфигурации запуска.
Поскольку файл cookie отправляется в заголовке каждого запроса, он должен иметь новый токен доступа без срока действия, чтобы я не получил «Пользователь не авторизован» для запроса.
Сейчас я могу получить новый токен, используя свой токен обновления, но значение cookie не изменилось, поэтому я считаю, что мне нужно обновить свой cookie, чтобы он отображал новый токен доступа, прежде чем клиент отправит какие-либо запросы.
Вот посмотрите на мой гибридный клиент:
using IdentityModel.Client;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Cts.HomeService.Web.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var identityServerSection = (IdentityServerSectionHandler)System.Configuration.ConfigurationManager.GetSection("identityserversection");
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
CookieManager = new Microsoft.Owin.Host.SystemWeb.SystemWebChunkingCookieManager()
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "localTestClient",
Authority = "http://localhost:5000",
RedirectUri = identityServerSection.Identity.RedirectUri,
Scope = "openid profile offline_access",
ResponseType = "code id_token",
RequireHttpsMetadata = false,
PostLogoutRedirectUri = identityServerSection.Identity.RedirectUri,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role",
},
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
var tokenClient = new TokenClient(
"http://localhost:5000/connect/token",
"localTestClient",
"");
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
n.Code, n.RedirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
// use the access token to retrieve claims from userinfo
var userInfoClient = new UserInfoClient(
"http://localhost:5000/connect/userinfo");
var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
// create new identity
var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(userInfoResponse.Claims);
id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
id.AddClaim(new Claim("id_token", tokenResponse.IdentityToken));
id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
n.AuthenticationTicket = new AuthenticationTicket(
new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
n.AuthenticationTicket.Properties);
},
RedirectToIdentityProvider = n =>
{
{
// so here I'll grab the access token
if (isAccessTokenExpired()) {
var cancellationToken = new CancellationToken();
var newAccessToken = context.GetNewAccessTokenAsync(refresh_token, null, cancellationToken);
// now what?
}
// if signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
}
return Task.FromResult(0);
}
}
}
});
}
}
}
Я много чего изучал, но ценность моего печенья всегда остается неизменной. Я подумал об удалении старого cookie и просто создании нового cookie вручную, но для этого нужно правильно его зашифровать, и он пахнет смешно, конечно, не идиоматическим способом сделать это.
Я чувствую, что должно быть что-то простое, что мне не хватает. Я ожидал бы простой метод «UpdateCookie (newToken)», и я пробовал SignIn () и SignOut (), но у меня это не сработало, казалось бы, вообще не взаимодействуя с cookie.