0

我正在用 asp.net core 2.0、AspNet.Security.OpenIdConnect.Server 和 AspNet.Security.OAuth.Extensions 编写一个测试应用程序。我遇到了访问令牌自省的问题。当我从 /connect/token 获取令牌并将其发送到我的资源服务器时,我的服务器中出现以下错误:

fail: AspNet.Security.OpenIdConnect.Server.OpenIdConnectServerHandler[0]
      The introspection request was rejected with the following error: invalid_request ; (null)
info: AspNet.Security.OpenIdConnect.Server.OpenIdConnectServerHandler[0]
      The introspection response was successfully returned: {
        "error": "invalid_request"
      }

在我的资源服务器中:

fail: AspNet.Security.OAuth.Introspection.OAuthIntrospectionHandler[0]
      An error occurred while validating an access token: the remote server returned a BadRequest response with the following payload: Date: Sat, 21 Oct 2017 17:11:50 GMT
      Server: Kestrel
       {"error":"invalid_request"}.
info: AspNet.Security.OAuth.Introspection.OAuthIntrospectionHandler[7]
      Bearer was not authenticated. Failure message: Authentication failed because the authorization server rejected the access token.

这是我的资源服务器 (WebApi) 的 Startup 类中的 ConfigureServices 方法:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication().AddOAuthIntrospection(
        options =>
        {
            options.Authority = new Uri("http://localhost:64855/");
            options.Audiences.Add("resource_server");
            options.ClientId = "client_id";
            options.ClientSecret = "client_secret";
            options.RequireHttpsMetadata = false;
        });
    services.AddMvc();
}

这是我在资源服务器中受 AuthorizeAttribute 控制器保护:

[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = OAuthIntrospectionDefaults.AuthenticationScheme)]
public class ValuesController : Controller
{
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] {"value1", "value2"};
    }
}

这是身份验证服务器中的启动类:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(
                options =>
                {
                    options.DefaultScheme = OAuthValidationDefaults.AuthenticationScheme;
                })
            .AddOAuthValidation(
                options =>
                {
                    options.Audiences.Add("resource_server");
                });

        services.AddAuthentication().AddOpenIdConnectServer(options =>
        {
            options.TokenEndpointPath = "/connect/token";
            options.IntrospectionEndpointPath = "/connect/introspect";
            options.AllowInsecureHttp = true;
            options.ApplicationCanDisplayErrors = true;
            options.Provider.OnValidateTokenRequest = context =>
            {
                if (!context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType())
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
                        description: "Only grant_type=password and refresh_token " +
                                     "requests are accepted by this server.");

                    return Task.CompletedTask;
                }

                if (string.Equals(context.ClientId, "client_id", StringComparison.Ordinal) &&
                    string.Equals(context.ClientSecret, "client_secret", StringComparison.Ordinal))
                {
                    context.Validate();
                }

                return Task.CompletedTask;
            };

            options.Provider.OnHandleTokenRequest = context =>
            {
                if (context.Request.IsPasswordGrantType())
                {
                    if (!string.Equals(context.Request.Username, "Bob", StringComparison.Ordinal) ||
                        !string.Equals(context.Request.Password, "P@ssw0rd", StringComparison.Ordinal))
                    {
                        context.Reject(
                            error: OpenIdConnectConstants.Errors.InvalidGrant,
                            description: "Invalid user credentials.");

                        return Task.CompletedTask;
                    }

                    var identity = new ClaimsIdentity(context.Scheme.Name,
                        OpenIdConnectConstants.Claims.Name,
                        OpenIdConnectConstants.Claims.Role);

                    identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "[unique id]");

                    identity.AddClaim("urn:customclaim", "value",
                        OpenIdConnectConstants.Destinations.AccessToken,
                        OpenIdConnectConstants.Destinations.IdentityToken);

                    var ticket = new AuthenticationTicket(
                        new ClaimsPrincipal(identity),
                        new AuthenticationProperties(),
                        context.Scheme.Name);

                    ticket.SetScopes(
                        OpenIdConnectConstants.Scopes.Profile,
                        OpenIdConnectConstants.Scopes.OfflineAccess);

                    context.Validate(ticket);
                }

                return Task.CompletedTask;
            };
        });

        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();
        app.UseAuthentication();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

在我看来,我在配置服务器和客户端时遗漏了一些东西,但我不明白在哪里。或者,也许我只是做错了什么。也许,我应该自己实现自省方法……不知道(我已经尝试覆盖 OpenIdServerConnectProvider 中的方法,但最终什么也没发生。

请告诉我可能是什么问题或我做错了什么。谢谢。

UPD:在所有修复之后,感谢 Pinpoint,这是我的工作解决方案: https ://github.com/mstya/Introspection.Sample 我希望它对某人有所帮助。

4

1 回答 1

1

或者,也许我只是做错了什么。也许,我应该自己实现自省方法……不知道(我已经尝试覆盖 OpenIdServerConnectProvider 中的方法,但最终什么也没发生。

您忘记执行该ValidateIntrospectionRequest事件。就像ValidateTokenRequest,您必须验证客户端凭据并context.Validate()在它们有效时调用。

于 2017-10-22T00:26:00.097 回答