2015-03-31 105 views
36

我跟随this article实现OAuth授权服务器。然而,当我使用后的人得到一个道理,我的回应得到一个错误:当通过Postman调用OWIN OAuth安全Web API获取JWT时,获取“error”:“unsupported_grant_type”

“错误”:“unsupported_grant_type”

我读的地方,需要被张贴在邮差数据使用Content-type:application/x-www-form-urlencoded。我在邮差坦然所需的设置:

enter image description here

,但我的头是这样的:

enter image description here

这里是我的代码

public class CustomOAuthProvider : OAuthAuthorizationServerProvider 
{ 
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
    { 
     context.Validated(); 
     return Task.FromResult<object>(null); 
    } 

    public override Task MatchEndpoint(OAuthMatchEndpointContext context) 
    { 
     if (context.OwinContext.Request.Method == "OPTIONS" && context.IsTokenEndpoint) 
     { 
      context.OwinContext.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST" }); 
      context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "accept", "authorization", "content-type" }); 
      context.OwinContext.Response.StatusCode = 200; 
      context.RequestCompleted(); 
      return Task.FromResult<object>(null); 
     } 
     return base.MatchEndpoint(context);  
    } 

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
    { 
     string allowedOrigin = "*"; 

     context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin }); 
     context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Content-Type" }); 

     Models.TheUser user = new Models.TheUser(); 
     user.UserName = context.UserName; 
     user.FirstName = "Sample first name"; 
     user.LastName = "Dummy Last name"; 

     ClaimsIdentity identity = new ClaimsIdentity("JWT"); 

     identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 
     foreach (string claim in user.Claims) 
     { 
      identity.AddClaim(new Claim("Claim", claim));  
     } 

     var ticket = new AuthenticationTicket(identity, null); 
     context.Validated(ticket); 
    } 
} 

public class CustomJwtFormat : ISecureDataFormat<AuthenticationTicket> 
{ 
    private readonly string _issuer = string.Empty; 

    public CustomJwtFormat(string issuer) 
    { 
     _issuer = issuer; 
    } 

    public string Protect(AuthenticationTicket data) 
    { 
     string audienceId = ConfigurationManager.AppSettings["AudienceId"]; 
     string symmetricKeyAsBase64 = ConfigurationManager.AppSettings["AudienceSecret"]; 
     var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64); 
     var signingKey = new HmacSigningCredentials(keyByteArray); 
     var issued = data.Properties.IssuedUtc; 
     var expires = data.Properties.ExpiresUtc; 
     var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey); 
     var handler = new JwtSecurityTokenHandler(); 
     var jwt = handler.WriteToken(token); 
     return jwt; 
    } 

    public AuthenticationTicket Unprotect(string protectedText) 
    { 
     throw new NotImplementedException(); 
    } 
} 

在CustomJWTFormat类以上只有构造函数中的断点被击中。在CustomOauth类中,GrantResourceOwnerCredentials方法中的断点永远不会被击中。其他人做。

启动类:

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 

     HttpConfiguration config = new HttpConfiguration(); 
     WebApiConfig.Register(config); 

     ConfigureOAuthTokenGeneration(app); 
     ConfigureOAuthTokenConsumption(app); 

     app.UseWebApi(config); 
    } 

    private void ConfigureOAuthTokenGeneration(IAppBuilder app) 
    { 
     var OAuthServerOptions = new OAuthAuthorizationServerOptions() 
     { 
      //For Dev enviroment only (on production should be AllowInsecureHttp = false) 
      AllowInsecureHttp = true, 
      TokenEndpointPath = new PathString("/oauth/token"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
      Provider = new CustomOAuthProvider(), 
      AccessTokenFormat = new CustomJwtFormat(ConfigurationManager.AppSettings["Issuer"]) 
     }; 

     // OAuth 2.0 Bearer Access Token Generation 
     app.UseOAuthAuthorizationServer(OAuthServerOptions); 
    } 

    private void ConfigureOAuthTokenConsumption(IAppBuilder app) 
    { 
     string issuer = ConfigurationManager.AppSettings["Issuer"]; 
     string audienceId = ConfigurationManager.AppSettings["AudienceId"]; 
     byte[] audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]); 

     // Api controllers with an [Authorize] attribute will be validated with JWT 
     app.UseJwtBearerAuthentication(
      new JwtBearerAuthenticationOptions 
      { 
       AuthenticationMode = AuthenticationMode.Active, 
       AllowedAudiences = new[] { audienceId }, 
       IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[] 
       { 
        new SymmetricKeyIssuerSecurityTokenProvider(issuer, audienceSecret) 
       } 
      }); 
    } 
} 

我是否需要设立Content-type:application/x-www-form-urlencoded其他地方在web API代码?什么可能是错的?请帮忙。

+0

我不想传递用户名密码,我想验证使用exernal提供程序如twitter消费者密钥和消费者密钥,我该怎么做? – Neo 2017-05-25 17:29:49

+0

感谢你的提问,尽管你的问题和最终答案实际上并不是我想要的,但内联代码片段似乎已经为我解决了问题。我正在努力处理由客户端ID /秘密保护的OPTIONS身份验证令牌点。你救了我! – 2017-07-07 13:25:31

回答

65

的反应是有点晚了 - 但如果任何人有在未来的问题...

从上面的截图 - 看来你添加的网址数据(用户名,密码,grant_type)至标题而不是body元素。

点击体标签,然后选择“X WWW的形式,进行了urlencoded”单选按钮,应该有下面的键值列表,您可以输入请求数据

+1

我怎样才能使角度服务电话的请求相同? – 2016-10-12 13:13:57

1

尝试添加该在您的有效载荷

grant_type=password&username=pippo&password=pluto 
26

有了邮递员,选择车身标签,然后选择原始选项,并输入以下命令:

grant_type=password&username=yourusername&password=yourpassword 
+1

这对我很好,谢谢! – CodeOrElse 2017-09-01 11:56:54

+0

对于包含“p @ ssword”等特殊字符的人体,您是否需要用“%40”替换“@”? – 2017-11-16 03:30:11

+0

工作对我来说非常好。非常感谢。 – Nagesh 2018-02-01 12:27:03

11
  1. 请注意网址:localhost:55828/token(不是localhost:55828/API/token
  2. 请注意请求数据。它不是以json格式,它只是简单的数据没有双引号。 [email protected]&password=Test123$&grant_type=password
  3. 请注意内容类型。内容类型:“应用/的X WWW的形式,进行了urlencoded”(不是内容类型:“应用/ JSON”)
  4. 当您使用JavaScript来使POST请求,您可以使用下列内容:

    $http.post("localhost:55828/token", 
        "userName=" + encodeURIComponent(email) + 
        "&password=" + encodeURIComponent(password) + 
        "&grant_type=password", 
        {headers: { 'Content-Type': 'application/x-www-form-urlencoded' }} 
    ).success(function (data) {//... 
    

下方见截图从邮差:

Postman Request

Postman Request Header

+1

替换密码中的&我正在发送与上述相同的请求,但仍然收到invalid_grant。请提出解决方案。 – sadhana 2017-06-19 18:42:48

+0

很好的回答!步骤有帮助。 – OverMars 2018-01-20 23:08:07

-2

使用grant_type = {你的密码} enter image description here