Owin.Security.OAuth上的Authorization_code授权流:返回invalid_grant

dgn*_*dgn 6 asp.net oauth-2.0 owin owin.security

我正在尝试使用authorization_code授权流程设置我的身份验证.我以前曾经使用它grant_type=password,所以我知道这些东西应该如何工作.但是在使用时grant_type=authorization_code,我无法让它返回任何其他东西invalid_grant

这是我的设置:

app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString("/auth/token"),
    AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(5),
    Provider = new SampleAuthProvider()
});

app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
    AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
    AuthenticationType = "Bearer"
});
Run Code Online (Sandbox Code Playgroud)

SampleAuthProvider是以下类:https://gist.github.com/anonymous/8a0079b705423b406c00

基本上,它只是记录每一步并验证它.我试过了这个请求:

POST http://localhost:12345/auth/token
grant_type=authorization_code&code=xxxxxx&client_id=xxxxx&redirect_uri=https://xxxx.com/
Content-Type: application/x-www-form-urlencoded
Run Code Online (Sandbox Code Playgroud)

它正在经历:

  • OnMatchEndpoint
  • OnValidateClientAuthentication

就这样.我希望它能打电话OnValidateTokenRequest,OnGrantAuthorizationCode接下来,但事实并非如此.我不知道为什么.

xxxx请求中的's不是占位符,我是这样尝试的.也许中间件会自行进行一些检查并因此拒绝请求?我尝试了redirect_uriwith的变种http,没有任何协议,没有尾随斜线...

它也适用于自定义grant_type.因此,如果我太绝望了,我想我可以用它来模拟authorization_code,但我宁愿不必那样做.

TL; DR

使用后我的OAuthAuthorizationServerProvider回报.{"error":"invalid_grant"}OnValidateClientAuthenticationgrant_type=authorization_code

  • 它为什么停在那里?
  • 我怎么能让整个该死的东西工作?

谢谢你的帮助!


编辑

正如RajeshKannan所指出的,我在配置上犯了一个错误.我没有提供AuthorizationCodeProvider实例.但是,这并没有完全解决问题,因为在我的情况下,代码不是由代码发出的AuthorizationCodeProvider,我不能只是反序列化它.我接受了工作的解决方法.

dgn*_*dgn 10

这就是我的工作.我对这个解决方案并不完全满意,但它有效,应该帮助其他人解决问题.


所以,问题是我没有设置AuthorizationCodeProvider属性.grant_type=authorization_code收到请求后,代码必须由该代码提供程序验证.该框架假定代码是由该代码提供者发布的,但这不是我的情况.我从另一台服务器获取它,并且必须将代码发送回它以进行验证.

在标准情况下,您也是发布代码的人,RajeshKannan提供的链接描述了您必须做的一切.

您必须在此处设置属性:

app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString(Paths.TokenPath),
    Provider = new SampleAuthProvider(),
    AuthorizationCodeProvider = new MyAuthorizationCodeProvider ()
}
Run Code Online (Sandbox Code Playgroud)

MyAuthorizationCodeProvider班级的宣言:

internal class MyAuthorizationCodeProvider : AuthenticationTokenProvider
{
    public override async Task ReceiveAsync(
        AuthenticationTokenReceiveContext context)
    {
        object form;
        // Definitely doesn't feel right
        context.OwinContext.Environment.TryGetValue(
                "Microsoft.Owin.Form#collection", out form); 
        var redirectUris = (form as FormCollection).GetValues("redirect_uri");
        var clientIds = (form as FormCollection).GetValues("client_id");
        if (redirectUris != null && clientIds != null)
        {
            // Queries the external server to validate the token
            string username = await MySsoService.GetUserName(context.Token,
                                                             redirectUris[0]);
            if (!string.IsNullOrEmpty(username))
            {
                var identity = new ClaimsIdentity(new List<Claim>()
                {
                    // I need the username in  GrantAuthorizationCode
                    new Claim(ClaimTypes.NameIdentifier, username) 
                }, DefaultAuthenticationTypes.ExternalBearer);

                var authProps = new AuthenticationProperties();

                // Required. The request is rejected if it's not provided
                authProps.Dictionary.Add("client_id", clientIds[0]); 

                // Required, must be in the future
                authProps.ExpiresUtc = DateTimeOffset.Now.AddMinutes(1); 

                var ticket = new AuthenticationTicket(identity, authProps);
                context.SetTicket(ticket);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Geb*_*ebb 5

我有同样的错误。我缺少的东西:

  • OAuthAuthorizationServerOptions.AuthorizationCodeProvider根据文档指定。
  • 向令牌端点发出请求时指定client_id与 GET 参数相同的参数,就像您收到authorization_code.
  • 重写OAuthAuthorizationServerProvider.ValidateClientAuthentication并在此方法中调用context.TryGetFormCredentials。这会将属性设置为GET 参数context.ClientId中的值。必须设置client_id该属性,否则会出现错误。另外,打电话。invalid_grantcontext.Validated()

完成上述所有操作后,我终于可以在令牌端点将 交换authorization_code为 an 。access_token