2015-03-31 12 views
36

Ho seguito this article per implementare un server di autorizzazione OAuth. Tuttavia quando uso postale uomo per ottenere un gettone, ottengo un errore nella risposta:Ottenere "errore": "unsupported_grant_type" quando si cerca di ottenere una JWT chiamando un OWIN OAuth protetto Web Api tramite Postman

"errore": "unsupported_grant_type"

ho letto da qualche parte che i dati in Postman deve essere inviato utilizzando Content-type:application/x-www-form-urlencoded. Ho predisposto le impostazioni necessarie in Postman:

enter image description here

eppure le mie intestazioni sono come questo:

enter image description here

Ecco il mio codice

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(); 
    } 
} 

Nella classe CustomJWTFormat sopra solo il punto di interruzione nel costruttore viene colpito. Nella classe CustomOauth, il punto di interruzione nel metodo GrantResourceOwnerCredentials non viene mai colpito. Gli altri lo fanno.

La classe di avvio:

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) 
       } 
      }); 
    } 
} 

Devo configurare Content-type:application/x-www-form-urlencoded da qualche altra parte nel codice web api? Cosa potrebbe esserci di sbagliato? Per favore aiuto.

+0

Non voglio passare la password del nome utente piuttosto, voglio verificare utilizzando provider esterni come la chiave utente di Twitter e il segreto del consumatore, come posso farlo? – Neo

+0

Grazie per questo, anche se la tua domanda e la risposta definitiva non erano in realtà ciò che stavo cercando, uno snippet inline sembra averlo risolto per me. Stavo lottando con il punto di token di autenticazione OPTIONS protetto dall'ID client/segreto. Mi hai salvato! –

risposta

65

La risposta è un po 'tardi - ma nel caso qualcuno ha il problema in futuro ...

Dalla schermata qui sopra - sembra che si sta aggiungendo i dati URL (nome utente, password, grant_type) per l'intestazione e non l'elemento del corpo.

Facendo clic sulla scheda del corpo, e quindi selezionare "x-www-form-urlencoded" pulsante di scelta, ci dovrebbe essere un elenco di valori-chiave di sotto di quella in cui è possibile inserire i dati di richiesta

+1

Come posso effettuare la stessa richiesta dalla chiamata di servizio angolare? –

1

tenta di aggiungere questo nel payload

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

Con Postman, selezionare la scheda corpo e scegliere l'opzione prima e digitare quanto segue:

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

Questo ha funzionato bene per me, grazie! – CodeOrElse

+0

per i body che includono caratteri speciali come 'p @ ssword', dovresti sostituire" @ "con"% 40 "? –

+0

ha funzionato meravigliosamente per me. Molte grazie. – Nagesh

11
  1. Annotare l'URL: localhost:55828/token (non localhost:55828/API/token)
  2. Annotare i dati della richiesta. Non è in formato JSON, ma solo dati semplici senza virgolette. [email protected]&password=Test123$&grant_type=password
  3. Annotare il tipo di contenuto.Content-Type: 'application/x-www-form-urlencoded' (non Content-Type: 'application/json')
  4. Quando si utilizza JavaScript per fare richiesta di posta, è possibile utilizzare seguente:

    $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) {//... 
    

vedere gli screenshot qui sotto da Postman:

Postman Request

Postman Request Header

+1

Sto inviando la stessa richiesta come descritto sopra, ottenendo ancora invalid_grant. Si prega di suggerire una soluzione. – sadhana

+0

Ottima risposta! Passi aiutati. – OverMars

-2

Usa grant_type = {La tua password} enter image description here

Problemi correlati