Конечная точка / токен никогда не достигается, поэтому ошибка не находится под моим контролем.
Фактически достигается /token
, а параметр grant_type
равен refresh_token
. Но логика отклонения по истечении срока действия маркера обновления не обрабатывается нами. Это какой-то «жесткий код» в исходном коде :
if (token == null)
{
context.Reject(
error: OpenIddictConstants.Errors.InvalidGrant,
description: context.Request.IsAuthorizationCodeGrantType() ?
"The specified authorization code is no longer valid." :
"The specified refresh token is no longer valid.");
return;
}
if (options.UseRollingTokens || context.Request.IsAuthorizationCodeGrantType())
{
if (!await TryRedeemTokenAsync(token))
{
context.Reject(
error: OpenIddictConstants.Errors.InvalidGrant,
description: context.Request.IsAuthorizationCodeGrantType() ?
"The specified authorization code is no longer valid." :
"The specified refresh token is no longer valid.");
return;
}
}
context.Reject
здесь происходит от сборки AspNet.Security.OpenIdConnect.Server
.
Подробнее см. исходный код на GitHub .
Я пытался использовать пользовательское промежуточное ПО для перехвата всех кодов состояния (что оно и делает), но результат возвращается до завершения выполнения моего пользовательского промежуточного ПО.
Я пытался, и я почти уверен, что мы можем использовать специальное промежуточное ПО для перехвата всех кодов состояния. Ключевым моментом является обнаружение кода состояния после вызова next()
:
app.Use(async(context , next )=>{
// passby all other end points
if(! context.Request.Path.StartsWithSegments("/connect/token")){
await next();
return;
}
// since we might want to detect the Response.Body, I add some stream here .
// if you only want to detect the status code , there's no need to use these streams
Stream originalStream = context.Response.Body;
var hijackedStream = new MemoryStream();
context.Response.Body = hijackedStream;
hijackedStream.Seek(0,SeekOrigin.Begin);
await next();
// if status code not 400 , pass by
if(context.Response.StatusCode != 400){
await CopyStreamToResponseBody(context,hijackedStream,originalStream);
return;
}
// read and custom the stream
hijackedStream.Seek(0,SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(hijackedStream))
{
var raw= sr.ReadToEnd();
if(raw.Contains("The specified refresh token is no longer valid.")){
// custom your own response
context.Response.StatusCode = 401;
// ...
//context.Response.Body = ... /
}else{
await CopyStreamToResponseBody(context,hijackedStream,originalStream);
}
}
});
// helper to make the copy easy
private async Task CopyStreamToResponseBody(HttpContext context,Stream newStream, Stream originalStream){
newStream.Seek(0,SeekOrigin.Begin);
await newStream.CopyToAsync(originalStream);
context.Response.ContentLength =originalStream.Length;
context.Response.Body = originalStream;
}