ASP.NET Core使用基本身份验证的OAuth TokenEndpoint

3
我正在尝试使用ASP.Net Core 2.2进行OAuth身份验证。为了使用OAuth,我在Startup.cs的public void ConfigureServices(IServiceCollection services)方法中使用AddOAuth方法:
services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = "Provider";
})            
.AddCookie()
.AddOAuth("Provider", options =>
{
    options.ClientId = Configuration["Provider:ClientId"];
    options.ClientSecret = Configuration["Provider:ClientSecret"];
    options.CallbackPath = new PathString("/callback");

    options.AuthorizationEndpoint = "https://api.provider.net/auth/code";
    options.TokenEndpoint = "https://api.provider.net/auth/token";
});

问题在于当中间件尝试使用TokenEndpoint获取授权码时,我收到HTTP 401错误,因为提供程序在此端点处期望基本身份验证标头。我的问题是,如何告诉中间件向TokenEndpoint请求添加基本身份验证标头?

2
我认为这个问题与您的解决方案相似:https://stackoverflow.com/questions/52994176/jwtbearerhandler-with-authorization-header-for-discovery-endpoint/52999219。 - Kirk Larkin
1
这个问题今天仍然存在。这很奇怪,因为根据规范,授权服务器对client_id/client_credential身份验证的支持是可选的:https://tools.ietf.org/html/rfc6749#section-2.3 - Simon Bergot
1个回答

8

@Kirk Larkin感谢您发布这个链接,它对我提出解决方案有很大帮助!

我创建了一个DelegateHandler,如果请求发送到TokenEndpoint,则会添加基本身份验证头:

public class AuthorizingHandler : DelegatingHandler
{
    private readonly OAuthOptions _options;
    public AuthorizingHandler(HttpMessageHandler inner, OAuthOptions options)
        : base(inner)
    {
        _options = options;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if(request.RequestUri == new Uri(_options.TokenEndpoint))
        {
            string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(_options.ClientId + ":" + _options.ClientSecret));

            request.Headers.Add("Authorization", $"Basic {credentials}");
        }
        return base.SendAsync(request, cancellationToken);
    }
}

ConfigureService 方法中使用了此 DelegateHandler

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = "Provider";
    })            
    .AddCookie()
    .AddOAuth("Provider", options =>
    {
        options.ClientId = Configuration["Provider:ClientId"];
        options.ClientSecret = Configuration["Provider:ClientSecret"];
        options.CallbackPath = new PathString("/callback");

        options.AuthorizationEndpoint = "https://api.provider.net/auth/code";
        options.TokenEndpoint = "https://api.provider.net/auth/token";

        var innerHandler = new HttpClientHandler();
        options.BackchannelHttpHandler = new AuthorizingHandler(innerHandler, options);

        //...
    });

    // ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接