我正在尝试使用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"
});
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
它正在经历:
OnMatchEndpoint
OnValidateClientAuthentication
就这样。我希望它接下来可以调用
OnValidateTokenRequest
和OnGrantAuthorizationCode
,但事实并非如此。我不知道为什么。请求中的
xxxx
不是占位符,我这样尝试过。也许中间件自己进行一些检查并因此拒绝请求?我尝试了redirect_uri
和http
的变体,没有任何协议(protocol),没有结尾的斜杠...它也可以与自定义
grant_type
一起正常工作。因此,如果我太绝望了,我想我可以用它来模拟authorization_code
,但是我宁愿不必那样做。TL; DR
使用
OAuthAuthorizationServerProvider
时,我的{"error":"invalid_grant"}
在OnValidateClientAuthentication
之后返回grant_type=authorization_code
。谢谢你的帮助!
编辑
正如RajeshKannan指出的那样,我在配置中犯了一个错误。我没有提供
AuthorizationCodeProvider
实例。但是,这并不能完全解决问题,因为在我的情况下,该代码不是由AuthorizationCodeProvider
发出的,我不能反序列化它。我忙于解决方法。 最佳答案
这就是我的工作。我对该解决方案并不完全满意,但是它可以正常工作,并且应该帮助其他人解决他们的问题。
因此,问题在于我没有设置AuthorizationCodeProvider
属性。收到带有grant_type=authorization_code
的请求时,该代码提供者必须验证该代码。该框架假定该代码是由该代码提供者发出的,但这不是我的情况。我是从另一台服务器上获得的,必须将代码发送回去进行验证。
在标准情况下,您也是发出代码的人,RajeshKannan提供的链接描述了您必须执行的所有操作。
这是您必须设置属性的地方:
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString(Paths.TokenPath),
Provider = new SampleAuthProvider(),
AuthorizationCodeProvider = new MyAuthorizationCodeProvider ()
}
以及
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);
}
}
}
}