gpt4 book ai didi

c# WebAPI Owin jwt RefreshToken invalid_grant 收藏

转载 作者:太空宇宙 更新时间:2023-11-03 23:04:25 25 4
gpt4 key购买 nike

我被这种行为难住了。基本上,当请求刷新 token 时,WebAPI 会执行从数据中删除旧 refresh_token 的逻辑,我在调试器中没有看到任何错误。但是,API 返回一个 HTTP 400,错误为“invalid_grant”。

启动.cs

// OAuth Server configuration
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = false,
TokenEndpointPath = new PathString("/oauth2/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(1),
AccessTokenFormat = new AccessTokenJwtFormat(issuer),
RefreshTokenProvider = new SimpleRefreshTokenProvider(),
RefreshTokenFormat = new RefreshTokenJwtFormat(issuer),
Provider = new CustomOAuthProvider()
};

// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);

SimpleRefreshTokenProvider.cs

public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{

public async Task CreateAsync(AuthenticationTokenCreateContext context)
{
var clientid = context.Ticket.Properties.Dictionary["as:client_id"];

if (string.IsNullOrEmpty(clientid))
{
return;
}

var refreshTokenId = Guid.NewGuid().ToString("n");
var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime");

var _repo = ClientDbProvider.GetInstance();
var token = new RefreshToken()
{
Id = ClientHelper.GetHash(refreshTokenId),
ClientId = clientid,
Subject = context.Ticket.Identity.Name,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
};

context.Ticket.Properties.IssuedUtc = new DateTimeOffset(token.IssuedUtc);
context.Ticket.Properties.ExpiresUtc = new DateTimeOffset(token.ExpiresUtc);
context.Ticket.Properties.Dictionary.Add("refreshTokenId", refreshTokenId);
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.Role, "refreshToken"));
token.ProtectedTicket = context.SerializeTicket();
var result = await _repo.AddRefreshToken(token);
if (result)
{
context.SetToken(token.ProtectedTicket);
}

return;
}

public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{

var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

var _repo = ClientDbProvider.GetInstance();
string hashedTokenId = ClientHelper.GetHash(context.Token);
var refreshToken = await _repo.FindRefreshToken(hashedTokenId);

if (refreshToken != null)
{
//Get protectedTicket from refreshToken class
context.DeserializeTicket(refreshToken.ProtectedTicket);
var result = await _repo.RemoveRefreshToken(hashedTokenId);
}
}

public void Create(AuthenticationTokenCreateContext context)
{
throw new NotImplementedException();
}

public void Receive(AuthenticationTokenReceiveContext context)
{
throw new NotImplementedException();
}
}

RefreshTokenJwtFormat.cs

public class RefreshTokenJwtFormat : ISecureDataFormat<AuthenticationTicket>
{
private const string AudiencePropertyKey = "audience";

private readonly string _issuer = string.Empty;

public RefreshTokenJwtFormat(string issuer)
{
_issuer = issuer;
audStore = new AudiencesStore();
}

public string Protect(AuthenticationTicket data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}

string audienceId = data.Properties.Dictionary.ContainsKey(AudiencePropertyKey) ? data.Properties.Dictionary[AudiencePropertyKey] : null;

if (string.IsNullOrWhiteSpace(audienceId)) throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience");

var audience = GetAudience(audienceId);
string symmetricKeyAsBase64 = audience.Base64Secret;

var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var signingCredentials = new SigningCredentials(
new InMemorySymmetricSecurityKey(keyByteArray),
SecurityAlgorithms.HmacSha256Signature,
SecurityAlgorithms.Sha256Digest);

var issued = data.Properties.IssuedUtc;
var expires = data.Properties.ExpiresUtc;
var payload = new JwtPayload(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime);
if (data.Properties.Dictionary.ContainsKey("refreshTokenId"))
{
payload.Add("refreshTokenId", data.Properties.Dictionary["refreshTokenId"]);
}

var header = new JwtHeader(signingCredentials);
var token = new JwtSecurityToken(header, payload);

var handler = new JwtSecurityTokenHandler();

var jwt = handler.WriteToken(token);

return jwt;
}

public AuthenticationTicket Unprotect(string protectedText)
{
var handler = new JwtSecurityTokenHandler();
SecurityToken securityToken = handler.ReadToken(protectedText);
var audienceId = ((JwtSecurityToken)securityToken).Claims.First(x => x.Type == "aud").Value;
var audience = GetAudience(audienceId);

string symmetricKeyAsBase64 = audience.Base64Secret;
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var securityKey = new InMemorySymmetricSecurityKey(keyByteArray);

var validationParameters = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = securityKey,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
ValidateAudience = true,
ValidAudience = audienceId,
ValidateIssuer = true,
ValidIssuer = _issuer
};

SecurityToken validatedToken;
ClaimsPrincipal principal = null;
try
{
principal = handler.ValidateToken(protectedText, validationParameters, out validatedToken);
}
catch(Exception ex)
{
return null;
}

return new AuthenticationTicket(principal.Identities.First(), new AuthenticationProperties());
}

private Models.Audience GetAudience(string audienceId)
{
var findAudTask = Task.Run(() => audStore.FindAudienceAsync(audienceId));
findAudTask.Wait();
var audience = findAudTask.Result;
return audience;
}

private AudiencesStore audStore;
}

最佳答案

首先你需要在您的 CustomOAuthProvider 中实现 GrantRefreshToken(OAuthGrantRefreshTokenContext context)像

public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
{

// Change auth ticket for refresh token requests
var newIdentity = new ClaimsIdentity(context.Ticket.Identity);
//newIdentity.AddClaim(new Claim("newClaim", "newValue"));

var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties);
context.Validated(newTicket);

return Task.FromResult<object>(null);
}

其次,您需要在 RefreshTokenJwtFormat 中更改方法 Unprotect。

替换

return new AuthenticationTicket(principal.Identities.First(), new AuthenticationProperties());

return new AuthenticationTicket(principal.Identities.First(), new AuthenticationProperties
{
IssuedUtc = validatedToken.ValidFrom,
ExpiresUtc = validatedToken.ValidTo
});

关于c# WebAPI Owin jwt RefreshToken invalid_grant 收藏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41836210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com