2016-01-21 20 views
6

Ich versuche, Swagger in meine Asp.Net-Web-API zu implementieren, und ich stolperte auf ein Problem.SwashBuckle/Swagger - OAuth-Ressourceneigner Kennwortfluss

Ich bin mit dem Passwort Ressourceneigentümer fließen, und ich habe eine Arbeit um hinzuzufügen, um dies zu tun, die in der folgenden Stack-Überlauf Frage bedeckt: -

Swagger/Swashbuckle: OAuth2 with Resource Owner Password Credentials Grant

Ich habe alles funktioniert, das Bearer-Token wird über JavaScript zum Anfrage-Header im aktuellen Browser-Fenster hinzugefügt, aber die API-Aufrufe an die Controller-Methoden, die eine Autorisierung erfordern, geben immer noch "401 - Authorization Failed" zurück. Hier

ist das JavaScript, das den Inhaber Token bekommt und fügt den Header: -

$('#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!"); 
     } 
    }); 
}); 

Die Curl in der Antwort in Swagger wird: -

curl -X GET --header " Accept: application/json "--header " Authorization: Inhaber NqlSG-WyTx2zkYE8xFklGyZWlQDZdsCKZBHruEXvX47N7PAzw4-jZ4eH5D0yFzQTXj13RwKFFt1rUZt2fzWj1vR5UR87wdlKC3YvsTojYV4-3DsWwY7qYRfiKPuM0j09c3X5lnrtlBVJ1rBRUH0TLjfw_yGxgoLBwOJl9xyC1YWNoPOe2nzL4lMOHodAnMem0IBMJmUo3Rt575tnWAbBsQXWhlImDIxCZ XvkZdJtlXfIfBSUdY9gfRWL0ZjKbf7m2-yLzH0gpMAMuKaADmJlIudJc0d4SP1Nn2Kh2HuVH8CX4QgZuu4egl9N6rY2smorP2vBSC4_dC4CpmYYzOTu2wUnUhHDY2Q6NWl377ijDKwZLcW9jtD-2tBiEGmFuRV0mVGnh0zc4w9Ao9jPCdtrbSyGitgloBW-UG2bfyao3eE“ "http://localhost:42291/api/v1/claims"

Ich kann überhaupt mit dieser etwas falsch sehen.

ich dann Postman verwendet habe, die genau die gleichen URL-Aufruf zu nennen, die gleichen Zugriffstoken verwenden, die in dem JavaScript-Aufruf erzeugt wurden ...

Ratet mal, was ... es funktioniert gut.

EDIT

Ich habe versucht, von der Steuerung die Genehmigung Attribut zu entfernen, so dass ich die Anfrage überprüfen kann, wie es die Controller-Methode trifft.

Wenn Sie in den Anforderungsheadern nachsehen, ist die Autorisierungseigenschaft null.

Nicht sicher, warum das ist. Die CURL schlägt vor, dass sie in die Anfrage aufgenommen wurde.

EDIT 2

Ive enthalten meine Sicherheitsdefinitionen: -

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

EDIT 3 Der Curl für diesen API-Aufruf in der Swagger Benutzeroberfläche angezeigt, wenn durch cURL direkt an der exponierte Befehlszeile funktioniert ohne Problem.

Jetzt bin ich völlig verwirrt.

+1

Bitte verwenden Sie Fiddler (http: //www.telerik.com/fiddler), um den Unterschied zwischen den beiden Aufrufen (Swagger und Postman) zu überprüfen. Auch für einen Test würde ich ändern hinzufügen ('Authorization' ... hinzufügen ('someUniqueKey' ... – Dunken

+0

Brauchen Sie wirklich 'securityDefinitions'? Ich habe nicht ... obwohl ich eine ältere Version brauche. – Dunken

+0

Ich denke Diese Autorisierungsverweigerung ist früher in der Pipeline gescheitert, es scheint, ich bin nicht die einzige Person, die dieses Problem hat. Ich denke, es könnte etwas mit der vor dem Flug OPTIONS Anfrage zu tun, die von IIS entführt werden. Man dies saugt! – Derek

Antwort

7

Ich habe es geschafft, das Problem zu beheben. Es war ein simples Typenkonflikt, das mich Tage der Trauer verursacht hat.

In der onComplete.JS musste ich einen Schlüssel erstellen, der mit dem in der Swagger-Spezifikation angegebenen Schlüssel übereinstimmt.

Wenn Sie meine Code-Schnipsel oben untersuchen, werden Sie sehen, dass ich einen Schlüssel erstellt habe und ihn "Autorisierung" genannt habe. Dies entspricht jedoch nicht der genannten Sicherheitsdefinition "oauth2".

Der Arbeitscode: -

$('#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!"); 
     } 
    }); 
}); 

Genau dies ein bisschen weiter zu erklären, müssen Sie eine Implementierung von IOperationFilter zu schaffen, damit Prahlerei bestimmen können, welche Methoden der api Authorizaion erfordern. Wenn Sie diese richtig konfiguriert haben, sollten Sie eine Sicherheitsdefinition gegen jeden API-Aufruf in der Prahlerei Spezifikation finden Sie unter: -

enter image description here

Meine Implementierung von 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

Ich hatte ein anderes Problem, aber dies wies mich in die richtige Richtung: "oauth2", Enumerable.Empty (); Sie müssen für jeden Grant-Typ einen anderen Namen haben und einen Eintrag in der Implementierung von IOperationFilter haben. – twoleggedhorse

+0

@Derek - Ich habe versucht, Ihren Anweisungen zu folgen, konnte aber mein Problem nicht lösen. Können Sie sich bitte meine Frage https: // ansehen stackoverflow.com/questions/47976035/swagger-ui-oauth-password-flow-retrieve-and-add-token-to-authorized-requests –

2

Der Autorisierungsmechanismus erwartet, dass jeder Operation eine security zugewiesen ist. Wenn nicht vorhanden, wird die Kopfzeile nicht gesendet.Bitte teilen Sie Ihre Spezifikationsdatei, wenn Sie denken, dass sie richtig zugewiesen ist

+0

Hey, ich habe meine Sicherheitsdefinitionen zur Frage hinzugefügt, können Sie irgendwelche Probleme damit sehen? fehguy – Derek

+0

Ive überprüft meine Swagger Json, das Auth2-Tag ist an die Methoden, die Autorisierung erwarten, so dass alle scheint richtig. Wenn ich die Anfrage in Fiddler ansehe, gibt es keinen Auth-Header. – Derek