|
|
@ -46,47 +46,29 @@ public class OpenIddictValidationService |
|
|
// Note: this service is registered as a singleton service. As such, it cannot
|
|
|
// Note: this service is registered as a singleton service. As such, it cannot
|
|
|
// directly depend on scoped services like the validation provider. To work around
|
|
|
// directly depend on scoped services like the validation provider. To work around
|
|
|
// this limitation, a scope is manually created for each method to this service.
|
|
|
// this limitation, a scope is manually created for each method to this service.
|
|
|
var scope = _provider.CreateScope(); |
|
|
await using var scope = _provider.CreateAsyncScope(); |
|
|
|
|
|
|
|
|
// Note: a try/finally block is deliberately used here to ensure the service scope
|
|
|
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); |
|
|
// can be disposed of asynchronously if it implements IAsyncDisposable.
|
|
|
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); |
|
|
try |
|
|
var transaction = await factory.CreateTransactionAsync(); |
|
|
{ |
|
|
|
|
|
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); |
|
|
|
|
|
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); |
|
|
|
|
|
var transaction = await factory.CreateTransactionAsync(); |
|
|
|
|
|
|
|
|
|
|
|
var context = new ProcessAuthenticationContext(transaction) |
|
|
var context = new ProcessAuthenticationContext(transaction) |
|
|
{ |
|
|
{ |
|
|
AccessToken = token |
|
|
AccessToken = token |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0163(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Debug.Assert(context.AccessTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); |
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
return context.AccessTokenPrincipal; |
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0163(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
finally |
|
|
Debug.Assert(context.AccessTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); |
|
|
{ |
|
|
|
|
|
if (scope is IAsyncDisposable disposable) |
|
|
|
|
|
{ |
|
|
|
|
|
await disposable.DisposeAsync(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
else |
|
|
return context.AccessTokenPrincipal; |
|
|
{ |
|
|
|
|
|
scope.Dispose(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
@ -112,123 +94,105 @@ public class OpenIddictValidationService |
|
|
// Note: this service is registered as a singleton service. As such, it cannot
|
|
|
// Note: this service is registered as a singleton service. As such, it cannot
|
|
|
// directly depend on scoped services like the validation provider. To work around
|
|
|
// directly depend on scoped services like the validation provider. To work around
|
|
|
// this limitation, a scope is manually created for each method to this service.
|
|
|
// this limitation, a scope is manually created for each method to this service.
|
|
|
var scope = _provider.CreateScope(); |
|
|
await using var scope = _provider.CreateAsyncScope(); |
|
|
|
|
|
|
|
|
// Note: a try/finally block is deliberately used here to ensure the service scope
|
|
|
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); |
|
|
// can be disposed of asynchronously if it implements IAsyncDisposable.
|
|
|
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); |
|
|
try |
|
|
var transaction = await factory.CreateTransactionAsync(); |
|
|
{ |
|
|
|
|
|
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); |
|
|
|
|
|
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); |
|
|
|
|
|
var transaction = await factory.CreateTransactionAsync(); |
|
|
|
|
|
|
|
|
|
|
|
var request = new OpenIddictRequest(); |
|
|
var request = new OpenIddictRequest(); |
|
|
request = await PrepareConfigurationRequestAsync(); |
|
|
request = await PrepareConfigurationRequestAsync(); |
|
|
request = await ApplyConfigurationRequestAsync(); |
|
|
request = await ApplyConfigurationRequestAsync(); |
|
|
var response = await ExtractConfigurationResponseAsync(); |
|
|
var response = await ExtractConfigurationResponseAsync(); |
|
|
|
|
|
|
|
|
return await HandleConfigurationResponseAsync() ?? |
|
|
return await HandleConfigurationResponseAsync() ?? |
|
|
throw new InvalidOperationException(SR.GetResourceString(SR.ID0145)); |
|
|
throw new InvalidOperationException(SR.GetResourceString(SR.ID0145)); |
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictRequest> PrepareConfigurationRequestAsync() |
|
|
async ValueTask<OpenIddictRequest> PrepareConfigurationRequestAsync() |
|
|
|
|
|
{ |
|
|
|
|
|
var context = new PrepareConfigurationRequestContext(transaction) |
|
|
{ |
|
|
{ |
|
|
var context = new PrepareConfigurationRequestContext(transaction) |
|
|
RemoteUri = uri, |
|
|
{ |
|
|
Request = request |
|
|
RemoteUri = uri, |
|
|
}; |
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0148(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return context.Request; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictRequest> ApplyConfigurationRequestAsync() |
|
|
await dispatcher.DispatchAsync(context); |
|
|
{ |
|
|
|
|
|
var context = new ApplyConfigurationRequestContext(transaction) |
|
|
|
|
|
{ |
|
|
|
|
|
RemoteUri = uri, |
|
|
|
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0148(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
return context.Request; |
|
|
{ |
|
|
} |
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0149(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.RemoteUri, context.Request); |
|
|
async ValueTask<OpenIddictRequest> ApplyConfigurationRequestAsync() |
|
|
|
|
|
{ |
|
|
|
|
|
var context = new ApplyConfigurationRequestContext(transaction) |
|
|
|
|
|
{ |
|
|
|
|
|
RemoteUri = uri, |
|
|
|
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
return context.Request; |
|
|
await dispatcher.DispatchAsync(context); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictResponse> ExtractConfigurationResponseAsync() |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
var context = new ExtractConfigurationResponseContext(transaction) |
|
|
throw new ProtocolException( |
|
|
{ |
|
|
SR.FormatID0149(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
RemoteUri = uri, |
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
Request = request |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.RemoteUri, context.Request); |
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0150(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); |
|
|
return context.Request; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.RemoteUri, context.Response); |
|
|
async ValueTask<OpenIddictResponse> ExtractConfigurationResponseAsync() |
|
|
|
|
|
{ |
|
|
|
|
|
var context = new ExtractConfigurationResponseContext(transaction) |
|
|
|
|
|
{ |
|
|
|
|
|
RemoteUri = uri, |
|
|
|
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
return context.Response; |
|
|
await dispatcher.DispatchAsync(context); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictConfiguration> HandleConfigurationResponseAsync() |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
var context = new HandleConfigurationResponseContext(transaction) |
|
|
throw new ProtocolException( |
|
|
{ |
|
|
SR.FormatID0150(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
RemoteUri = uri, |
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
Request = request, |
|
|
|
|
|
Response = response |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0151(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return context.Configuration; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); |
|
|
|
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.RemoteUri, context.Response); |
|
|
|
|
|
|
|
|
|
|
|
return context.Response; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
finally |
|
|
async ValueTask<OpenIddictConfiguration> HandleConfigurationResponseAsync() |
|
|
{ |
|
|
{ |
|
|
if (scope is IAsyncDisposable disposable) |
|
|
var context = new HandleConfigurationResponseContext(transaction) |
|
|
{ |
|
|
{ |
|
|
await disposable.DisposeAsync(); |
|
|
RemoteUri = uri, |
|
|
} |
|
|
Request = request, |
|
|
|
|
|
Response = response |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
else |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
scope.Dispose(); |
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0151(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return context.Configuration; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -255,123 +219,105 @@ public class OpenIddictValidationService |
|
|
// Note: this service is registered as a singleton service. As such, it cannot
|
|
|
// Note: this service is registered as a singleton service. As such, it cannot
|
|
|
// directly depend on scoped services like the validation provider. To work around
|
|
|
// directly depend on scoped services like the validation provider. To work around
|
|
|
// this limitation, a scope is manually created for each method to this service.
|
|
|
// this limitation, a scope is manually created for each method to this service.
|
|
|
var scope = _provider.CreateScope(); |
|
|
await using var scope = _provider.CreateAsyncScope(); |
|
|
|
|
|
|
|
|
// Note: a try/finally block is deliberately used here to ensure the service scope
|
|
|
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); |
|
|
// can be disposed of asynchronously if it implements IAsyncDisposable.
|
|
|
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); |
|
|
try |
|
|
var transaction = await factory.CreateTransactionAsync(); |
|
|
{ |
|
|
|
|
|
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); |
|
|
|
|
|
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); |
|
|
|
|
|
var transaction = await factory.CreateTransactionAsync(); |
|
|
|
|
|
|
|
|
|
|
|
var request = new OpenIddictRequest(); |
|
|
var request = new OpenIddictRequest(); |
|
|
request = await PrepareJsonWebKeySetRequestAsync(); |
|
|
request = await PrepareJsonWebKeySetRequestAsync(); |
|
|
request = await ApplyJsonWebKeySetRequestAsync(); |
|
|
request = await ApplyJsonWebKeySetRequestAsync(); |
|
|
|
|
|
|
|
|
var response = await ExtractJsonWebKeySetResponseAsync(); |
|
|
var response = await ExtractJsonWebKeySetResponseAsync(); |
|
|
|
|
|
|
|
|
return await HandleJsonWebKeySetResponseAsync() ?? |
|
|
return await HandleJsonWebKeySetResponseAsync() ?? |
|
|
throw new InvalidOperationException(SR.GetResourceString(SR.ID0147)); |
|
|
throw new InvalidOperationException(SR.GetResourceString(SR.ID0147)); |
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictRequest> PrepareJsonWebKeySetRequestAsync() |
|
|
async ValueTask<OpenIddictRequest> PrepareJsonWebKeySetRequestAsync() |
|
|
|
|
|
{ |
|
|
|
|
|
var context = new PrepareJsonWebKeySetRequestContext(transaction) |
|
|
{ |
|
|
{ |
|
|
var context = new PrepareJsonWebKeySetRequestContext(transaction) |
|
|
RemoteUri = uri, |
|
|
{ |
|
|
Request = request |
|
|
RemoteUri = uri, |
|
|
}; |
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0152(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return context.Request; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictRequest> ApplyJsonWebKeySetRequestAsync() |
|
|
await dispatcher.DispatchAsync(context); |
|
|
{ |
|
|
|
|
|
var context = new ApplyJsonWebKeySetRequestContext(transaction) |
|
|
|
|
|
{ |
|
|
|
|
|
RemoteUri = uri, |
|
|
|
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0152(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
return context.Request; |
|
|
{ |
|
|
} |
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0153(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.RemoteUri, context.Request); |
|
|
async ValueTask<OpenIddictRequest> ApplyJsonWebKeySetRequestAsync() |
|
|
|
|
|
{ |
|
|
|
|
|
var context = new ApplyJsonWebKeySetRequestContext(transaction) |
|
|
|
|
|
{ |
|
|
|
|
|
RemoteUri = uri, |
|
|
|
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
return context.Request; |
|
|
await dispatcher.DispatchAsync(context); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictResponse> ExtractJsonWebKeySetResponseAsync() |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
var context = new ExtractJsonWebKeySetResponseContext(transaction) |
|
|
throw new ProtocolException( |
|
|
{ |
|
|
SR.FormatID0153(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
RemoteUri = uri, |
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
Request = request |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.RemoteUri, context.Request); |
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0154(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); |
|
|
return context.Request; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.RemoteUri, context.Response); |
|
|
async ValueTask<OpenIddictResponse> ExtractJsonWebKeySetResponseAsync() |
|
|
|
|
|
{ |
|
|
|
|
|
var context = new ExtractJsonWebKeySetResponseContext(transaction) |
|
|
|
|
|
{ |
|
|
|
|
|
RemoteUri = uri, |
|
|
|
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
return context.Response; |
|
|
await dispatcher.DispatchAsync(context); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async ValueTask<JsonWebKeySet> HandleJsonWebKeySetResponseAsync() |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
var context = new HandleJsonWebKeySetResponseContext(transaction) |
|
|
throw new ProtocolException( |
|
|
{ |
|
|
SR.FormatID0154(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
Request = request, |
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
Response = response |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0155(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return context.SecurityKeys; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); |
|
|
|
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.RemoteUri, context.Response); |
|
|
|
|
|
|
|
|
|
|
|
return context.Response; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
finally |
|
|
async ValueTask<JsonWebKeySet> HandleJsonWebKeySetResponseAsync() |
|
|
{ |
|
|
{ |
|
|
if (scope is IAsyncDisposable disposable) |
|
|
var context = new HandleJsonWebKeySetResponseContext(transaction) |
|
|
{ |
|
|
{ |
|
|
await disposable.DisposeAsync(); |
|
|
Request = request, |
|
|
} |
|
|
Response = response |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
else |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
scope.Dispose(); |
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0155(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return context.SecurityKeys; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -413,133 +359,115 @@ public class OpenIddictValidationService |
|
|
// Note: this service is registered as a singleton service. As such, it cannot
|
|
|
// Note: this service is registered as a singleton service. As such, it cannot
|
|
|
// directly depend on scoped services like the validation provider. To work around
|
|
|
// directly depend on scoped services like the validation provider. To work around
|
|
|
// this limitation, a scope is manually created for each method to this service.
|
|
|
// this limitation, a scope is manually created for each method to this service.
|
|
|
var scope = _provider.CreateScope(); |
|
|
await using var scope = _provider.CreateAsyncScope(); |
|
|
|
|
|
|
|
|
// Note: a try/finally block is deliberately used here to ensure the service scope
|
|
|
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); |
|
|
// can be disposed of asynchronously if it implements IAsyncDisposable.
|
|
|
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); |
|
|
try |
|
|
var transaction = await factory.CreateTransactionAsync(); |
|
|
{ |
|
|
|
|
|
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); |
|
|
|
|
|
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); |
|
|
|
|
|
var transaction = await factory.CreateTransactionAsync(); |
|
|
|
|
|
|
|
|
|
|
|
request = await PrepareIntrospectionRequestAsync(); |
|
|
request = await PrepareIntrospectionRequestAsync(); |
|
|
request = await ApplyIntrospectionRequestAsync(); |
|
|
request = await ApplyIntrospectionRequestAsync(); |
|
|
|
|
|
|
|
|
var response = await ExtractIntrospectionResponseAsync(); |
|
|
var response = await ExtractIntrospectionResponseAsync(); |
|
|
|
|
|
|
|
|
return await HandleIntrospectionResponseAsync(); |
|
|
return await HandleIntrospectionResponseAsync(); |
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictRequest> PrepareIntrospectionRequestAsync() |
|
|
async ValueTask<OpenIddictRequest> PrepareIntrospectionRequestAsync() |
|
|
|
|
|
{ |
|
|
|
|
|
var context = new PrepareIntrospectionRequestContext(transaction) |
|
|
{ |
|
|
{ |
|
|
var context = new PrepareIntrospectionRequestContext(transaction) |
|
|
CancellationToken = cancellationToken, |
|
|
{ |
|
|
ClientAuthenticationMethod = method, |
|
|
CancellationToken = cancellationToken, |
|
|
RemoteUri = uri, |
|
|
ClientAuthenticationMethod = method, |
|
|
Configuration = configuration, |
|
|
RemoteUri = uri, |
|
|
Request = request |
|
|
Configuration = configuration, |
|
|
}; |
|
|
Request = request |
|
|
|
|
|
}; |
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0158(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return context.Request; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictRequest> ApplyIntrospectionRequestAsync() |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
var context = new ApplyIntrospectionRequestContext(transaction) |
|
|
throw new ProtocolException( |
|
|
{ |
|
|
SR.FormatID0158(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
CancellationToken = cancellationToken, |
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
RemoteUri = uri, |
|
|
|
|
|
Configuration = configuration, |
|
|
|
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0159(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); |
|
|
|
|
|
|
|
|
|
|
|
return context.Request; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictResponse> ExtractIntrospectionResponseAsync() |
|
|
return context.Request; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async ValueTask<OpenIddictRequest> ApplyIntrospectionRequestAsync() |
|
|
|
|
|
{ |
|
|
|
|
|
var context = new ApplyIntrospectionRequestContext(transaction) |
|
|
{ |
|
|
{ |
|
|
var context = new ExtractIntrospectionResponseContext(transaction) |
|
|
CancellationToken = cancellationToken, |
|
|
{ |
|
|
RemoteUri = uri, |
|
|
CancellationToken = cancellationToken, |
|
|
Configuration = configuration, |
|
|
RemoteUri = uri, |
|
|
Request = request |
|
|
Configuration = configuration, |
|
|
}; |
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
throw new ProtocolException( |
|
|
throw new ProtocolException( |
|
|
SR.FormatID0160(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
SR.FormatID0159(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); |
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); |
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); |
|
|
return context.Request; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return context.Response; |
|
|
async ValueTask<OpenIddictResponse> ExtractIntrospectionResponseAsync() |
|
|
} |
|
|
{ |
|
|
|
|
|
var context = new ExtractIntrospectionResponseContext(transaction) |
|
|
|
|
|
{ |
|
|
|
|
|
CancellationToken = cancellationToken, |
|
|
|
|
|
RemoteUri = uri, |
|
|
|
|
|
Configuration = configuration, |
|
|
|
|
|
Request = request |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
async ValueTask<(OpenIddictResponse, ClaimsPrincipal)> HandleIntrospectionResponseAsync() |
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
var context = new HandleIntrospectionResponseContext(transaction) |
|
|
throw new ProtocolException( |
|
|
{ |
|
|
SR.FormatID0160(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
CancellationToken = cancellationToken, |
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
RemoteUri = uri, |
|
|
|
|
|
Configuration = configuration, |
|
|
|
|
|
Request = request, |
|
|
|
|
|
Response = response |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0161(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); |
|
|
|
|
|
|
|
|
|
|
|
return (context.Response, context.Principal); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); |
|
|
|
|
|
|
|
|
|
|
|
context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); |
|
|
|
|
|
|
|
|
|
|
|
return context.Response; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
finally |
|
|
async ValueTask<(OpenIddictResponse, ClaimsPrincipal)> HandleIntrospectionResponseAsync() |
|
|
{ |
|
|
{ |
|
|
if (scope is IAsyncDisposable disposable) |
|
|
var context = new HandleIntrospectionResponseContext(transaction) |
|
|
{ |
|
|
{ |
|
|
await disposable.DisposeAsync(); |
|
|
CancellationToken = cancellationToken, |
|
|
} |
|
|
RemoteUri = uri, |
|
|
|
|
|
Configuration = configuration, |
|
|
|
|
|
Request = request, |
|
|
|
|
|
Response = response |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
else |
|
|
await dispatcher.DispatchAsync(context); |
|
|
|
|
|
|
|
|
|
|
|
if (context.IsRejected) |
|
|
{ |
|
|
{ |
|
|
scope.Dispose(); |
|
|
throw new ProtocolException( |
|
|
|
|
|
SR.FormatID0161(context.Error, context.ErrorDescription, context.ErrorUri), |
|
|
|
|
|
context.Error, context.ErrorDescription, context.ErrorUri); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); |
|
|
|
|
|
|
|
|
|
|
|
return (context.Response, context.Principal); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|