2015-01-12 17 views
16

Ho seguito un tutorial per proteggere un'API Web con OAuth in C#.Restituzione dell'endpoint API "L'autorizzazione è stata rifiutata per questa richiesta." quando si invia token bearer

Sto eseguendo alcuni test e fino ad ora sono riuscito a ottenere correttamente il token di accesso da /token. Sto usando un'estensione di Chrome chiamata "Advanced REST Client" per testarlo.

{"access_token":"...","token_type":"bearer","expires_in":86399} 

Questo è quello che torno da /token. Tutto sembra a posto.

La mia prossima domanda è per il mio test di controllo API:

namespace API.Controllers 
{ 
    [Authorize] 
    [RoutePrefix("api/Social")] 
    public class SocialController : ApiController 
    { 
     .... 


     [HttpPost] 
     public IHttpActionResult Schedule(SocialPost post) 
     { 
      var test = HttpContext.Current.GetOwinContext().Authentication.User; 

      .... 
      return Ok(); 
     } 
    } 
} 

La richiesta è un POST e ha l'intestazione:

Authorization: Bearer XXXXXXXTOKEHEREXXXXXXX 

ottengo: Authorization has been denied for this request. restituito in JSON.

Ho provato a fare un GET e ottengo quello che mi aspetterei, che il metodo non è supportato dal momento che non l'ho implementato.

Ecco il mio Provider Authorization:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider 
{ 
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
    { 
     context.Validated(); 
    } 

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
    { 

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

     using (var repo = new AuthRepository()) 
     { 
      IdentityUser user = await repo.FindUser(context.UserName, context.Password); 

      if (user == null) 
      { 
       context.SetError("invalid_grant", "The user name or password is incorrect."); 
       return; 
      } 
     } 

     var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
     identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 
     identity.AddClaim(new Claim(ClaimTypes.Role, "User")); 

     context.Validated(identity); 

    } 
} 

Qualsiasi aiuto sarebbe grande. Non sono sicuro se sia la richiesta o il codice che è sbagliato.

edit: Ecco il mio Startup.cs

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     var config = new HttpConfiguration(); 
     WebApiConfig.Register(config); 
     app.UseWebApi(config); 
     ConfigureOAuth(app); 
    } 

    public void ConfigureOAuth(IAppBuilder app) 
    { 
     var oAuthServerOptions = new OAuthAuthorizationServerOptions() 
     { 
      AllowInsecureHttp = true, 
      TokenEndpointPath = new PathString("/token"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
      Provider = new SimpleAuthorizationServerProvider() 
     }; 

     // Token Generation 
     app.UseOAuthAuthorizationServer(oAuthServerOptions); 
     app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 

    } 
} 

risposta

27

questione è piuttosto semplice: Modifica ordine del OWIN gasdotto.

public void Configuration(IAppBuilder app) 
{ 
    ConfigureOAuth(app); 
    var config = new HttpConfiguration(); 
    WebApiConfig.Register(config); 
    app.UseWebApi(config); 
} 

Per OWIN l'ordine della pipeline della configurazione è molto importante. Nel tuo caso, provi a utilizzare il gestore API Web prima del gestore OAuth. Al suo interno, convalidate la vostra richiesta, avete trovato un'azione sicura e provate a convalidarla contro l'attuale Owin.Context.User. A questo punto questo utente non esiste perché è impostato dal token con OAuth Handler che ha chiamato in seguito.

+0

Come procederebbe se non si registra WebApi nella pipeline? Sto solo lavorando con il modello di API Web predefinito. Le richieste GET funzionano bene, le richieste POST mi danno 401. Mentre il token è lo stesso. – mwijnands

+1

Questo mi ha sorpreso! Grazie per aver dedicato del tempo per pubblicare questa risposta. – heymega

+0

Ho perso alcune ore dopo il refactoring cercando di trovare una ragione per questo problema. – Tomino

2

È necessario aggiungere un reclamo con questo schema:

http://schemas.microsoft.com/ws/2008/06/identity/claims/role 

cosa migliore da fare è quella di utilizzare il set predefinito di reclami:

identity.AddClaim(new Claim(ClaimTypes.Role, "User")); 

potete trovare ClaimTypes in System.Security.Claims.

Un'altra cosa che dovete considerare è ruoli filtro nel controller/Azione:

[Authorize(Roles="User")] 

È possibile trovare una semplice campione di applicazione, self-hosted Owin con un cliente jquery here.

+0

Ho aggiunto: 'identity.AddClaim (new Claim (ClaimTypes.Role," User "));' inutilmente. È importante che l'utente sia capitale? Ho aggiunto questo prima di vedere il tuo commento. Non penserei che sarebbe importante. Controllerò il tuo link. –

+0

Questa è una costante e può essere qualsiasi cosa. – LeftyX

+0

Ho provato a cambiare '[Autorizza]' per includere il ruolo nel mio controller, ma non riesco ancora a ottenere l'autorizzazione. Ho creato un nuovo utente nel ruolo "Utente" e ho ottenuto un nuovo token con successo. Aggiornato il mio codice sopra con la tua modifica suggerita. –

0

Sembra che la versione di "System.IdentityModel.Tokens.Jwt" che coesiste con gli altri assiemi Owin non sia corretta.

Se si utilizza la versione "Microsoft.Owin.Security.Jwt" versione 2.1.0, è necessario utilizzare l'assembly "System.IdentityModel.Tokens.Jwt" della versione 3.0.2.

Dalla console gestore di pacchetti, provare:

Update-Package System.IdentityModel.Tokens.Jwt -Version 3.0.2 
Problemi correlati