2016-01-21 13 views
6

Sto cercando di implementare swagger nella mia API Web Asp.Net e sto avendo un problema.SwashBuckle/Swagger - Flusso password proprietario risorsa OAuth

sto usando il flusso proprietario della risorsa password e sto avendo per aggiungere un lavoro in giro per fare questo, che è coperto nella seguente domanda Stack Overflow: -

Swagger/Swashbuckle: OAuth2 with Resource Owner Password Credentials Grant

Ho tutto funzionante, il token Bearer viene aggiunto tramite javascript all'intestazione della richiesta nella finestra corrente del browser, ma le chiamate api ai metodi del controller che richiedono l'autorizzazione sono ancora restituite "401 - Autorizzazione non riuscita".

Ecco il JavaScript che ottiene il portatore token e aggiunge l'intestazione: -

$('#input_apiKey').change(function() { 
    var key = $('#input_apiKey')[0].value; 
    var credentials = key.split(':'); //username:password expected 
    $.ajax({ 
     url: "http://localhost:42291/token", 
     type: "post", 
     contenttype: 'x-www-form-urlencoded', 
     data: "grant_type=password&username=" + credentials[0] + "&password=" + credentials[1], 
     success: function (response) { 
      var bearerToken = 'Bearer ' + response.access_token; 

      window.swaggerUi.api.clientAuthorizations.add('Authorization', new window.SwaggerClient.ApiKeyAuthorization('Authorization', bearerToken, 'header')); 
      window.swaggerUi.api.clientAuthorizations.remove('api_key'); 

      alert("Login Succesfull!"); 
     }, 
     error: function (xhr, ajaxoptions, thrownerror) { 
      alert("Login failed!"); 
     } 
    }); 
}); 

Il Curl nella risposta in Swagger è: -

ricciolo -X GET --header " Accept: application/json "--header " Autorizzazione: portatore NqlSG-WyTx2zkYE8xFklGyZWlQDZdsCKZBHruEXvX47N7PAzw4-jZ4eH5D0yFzQTXj13RwKFFt1rUZt2fzWj1vR5UR87wdlKC3YvsTojYV4-3DsWwY7qYRfiKPuM0j09c3X5lnrtlBVJ1rBRUH0TLjfw_yGxgoLBwOJl9xyC1YWNoPOe2nzL4lMOHodAnMem0IBMJmUo3Rt575tnWAbBsQXWhlImDIxCZ XvkZdJtlXfIfBSUdY9gfRWL0ZjKbf7m2-yLzH0gpMAMuKaADmJlIudJc0d4SP1Nn2Kh2HuVH8CX4QgZuu4egl9N6rY2smorP2vBSC4_dC4CpmYYzOTu2wUnUhHDY2Q6NWl377ijDKwZLcW9jtD-2tBiEGmFuRV0mVGnh0zc4w9Ao9jPCdtrbSyGitgloBW-UG2bfyao3eE" "http://localhost:42291/api/v1/claims"

smusso vedo nulla di sbagliato in questo a tutti.

Ho quindi utilizzato Postman per chiamare la stessa chiamata URL esatto, utilizzando lo stesso token di accesso che è stato generato nella chiamata javascript ...

Indovinate un po '... funziona benissimo.

EDIT

Ho provato a rimuovere l'attributo di autorizzazione da parte del controllore, in modo che posso controllare la richiesta in quanto colpisce il metodo di controllo.

cercando nelle intestazioni della richiesta, la proprietà di autorizzazione è nulla.

Non sono sicuro del motivo. la CURL suggerisce che sia stata inserita nella richiesta.

EDIT 2

Ive ha incluso le mie definizioni di sicurezza: -

"securityDefinitions": { 
     "oauth2": { 
      "type": "oauth2", 
      "description": "OAuth2 Password Grant", 
      "flow": "password", 
      "tokenUrl": "http://localhost:42291/token", 
      "scopes": {} 
     } 
    } 

EDIT 3 il ricciolo visualizzato nella Swagger interfaccia utente per questa chiamata API, quando esposta attraverso cURL direttamente al la riga di comando funziona senza problemi.

Ora sono completamente confuso.

+1

Utilizzare Fiddler (http: //www.telerik.com/fiddler) per verificare la differenza tra le due chiamate (swagger e postman). Anche per un test vorrei aggiungere add ('Autorizzazione' ... per aggiungere ('someUniqueKey' ... – Dunken

+0

Hai davvero bisogno di 'securityDefinitions'? Non l'ho fatto ... anche se ho bisogno di una versione precedente. – Dunken

+0

Penso questa negazione dell'autorizzazione sta fallendo in precedenza nella pipeline, sembra che non sia l'unica persona ad avere questo problema. Penso che potrebbe essere qualcosa a che fare con la richiesta OPTION pre-flight essere dirottata da IIS. Man this sucks! – Derek

risposta

7

Sono riuscito a correggere il problema. Era un semplice errore di tipo che mi ha causato giorni di dolore.

Nel onComplete.JS, avevo bisogno di creare una chiave che corrisponda alla chiave presentata nella specifica swagger.

Se si esaminano i frammenti di codice sopra, vedrete che ho creato una chiave e l'ho chiamata "Autorizzazione". Ma ciò non corrisponde alla definizione di sicurezza denominata "oauth2".

Il codice di lavoro: -

$('#input_apiKey').change(function() { 
    var key = $('#input_apiKey')[0].value; 
    var credentials = key.split(':'); 
    $.ajax({ 
     url: "http://localhost:42291/token", 
     type: "post", 
     contenttype: 'x-www-form-urlencoded', 
     data: "grant_type=password&username=" + credentials[0] + "&password=" + credentials[1], 
     success: function (response) { 

      var bearerToken = "Bearer " + response.access_token; 

      window.swaggerUi.api.clientAuthorizations.remove('api_key'); 

      var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("Authorization", bearerToken, "header"); 

      window.swaggerUi.api.clientAuthorizations.add('oauth2', apiKeyAuth); 

      alert("Login Succesfull!"); 

     }, 
     error: function (xhr, ajaxoptions, thrownerror) { 
      alert("Login failed!"); 
     } 
    }); 
}); 

Giusto per spiegare questo un po 'più, è necessario creare un'implementazione di IOperationFilter in modo che spavalderia può determinare quali metodi dell'API richiedono Authorizaion. Una volta configurato correttamente, si dovrebbe vedere una definizione di sicurezza contro ogni chiamata API nella specifica spavalderia: -

enter image description here

mia implementazione di IOperationFilter: -

public class AssignOAuth2SecurityRequirements : IOperationFilter 
    { 
     /// <summary> 
     /// Apply Security Measures. 
     /// </summary> 
     /// <param name="operation"></param> 
     /// <param name="schemaRegistry"></param> 
     /// <param name="apiDescription"></param> 
     /// <exception cref="NotImplementedException"></exception> 
     public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) 
     { 
      // Determine if the operation has the Authorize attribute 
      var authorizeAttributes = apiDescription.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>(); 

      if (!authorizeAttributes.Any()) 
       return; 

      // Initialize the operation.security property 
      if (operation.security == null) 
       operation.security = new List<IDictionary<string, IEnumerable<string>>>(); 

      // Add the appropriate security definition to the operation 
      var oAuthRequirements = new Dictionary<string, IEnumerable<string>> 
      { 
       { "oauth2", Enumerable.Empty<string>() } 
      }; 

      operation.security.Add(oAuthRequirements); 
     } 
    } 
+0

Ho avuto un problema diverso, tuttavia, questo mi ha indirizzato nella giusta direzione: "oauth2", Enumerable.Empty (); Devi avere un nome diverso per ogni tipo di sovvenzione e devono avere una voce nell'implementazione di IOperationFilter – twoleggedhorse

+0

@Derek - Ho provato a seguire le tue istruzioni ma non sono stato in grado di risolvere il mio problema, puoi leggere la mia domanda https: // stackoverflow.com/questions/47976035/swagger-ui-oauth-password-flow-retrieve-and-add-token-to-authorized-requests –

2

Il meccanismo di autorizzazione prevede che a ciascuna operazione sia assegnato un security. Se non presente, l'intestazione non verrà inviata.Si prega di condividere il file spec se si pensa che sia assegnato correttamente

+0

Ehi, ho aggiunto le mie definizioni di sicurezza alla domanda, puoi vedere qualche problema con esso? fehguy – Derek

+0

Ive ha verificato il mio swagger json, il tag auth2 è collegato a quei metodi che prevedono l'autorizzazione, in modo che tutto sembra corretto. Quando guardo la richiesta in Fiddler, non c'è l'intestazione auth. – Derek

Problemi correlati