2015-11-17 16 views
9

Używam IdentityServer3 do zabezpieczenia interfejsu Web API z przyznaniem poświadczeń klienta. Dla dokumentacji Im przy użyciu Swashbuckle, ale nie można dowiedzieć się, jak włączyć Oauth2 w SwaggerConfig dla przepływu poświadczeń klienta (aplikacji). Każda pomoc będzie doceniona!Włącz przepływ danych uwierzytelniających klienta Oauth2 w Swashbuckle

+0

Czy znalazłeś rozwiązanie tego problemu? –

+0

Przykro mi to mówić nie. Zdecydowaliśmy się nie używać w produkcji zbójcy, który rozwiązał to dla nas. – mstrand

Odpowiedz

7

Udało mi się to zadziałać. Większość odpowiedzi można znaleźć here.

Było kilka części musiałem zmienić, aby uzyskać client_credential grant do pracy. Pierwsza część jest w EnableSwagger i EnableSwaggerUi wzywa:

config.EnableSwagger(c => 
    { 
    c.SingleApiVersion("v1", "sample api"); 
    c.OAuth2("oauth2") 
    .Description("client credentials grant flow") 
    .Flow("application") 
    .Scopes(scopes => scopes.Add("sampleapi", "try out the sample api")) 
    .TokenUrl("http://authuri/token"); 
    c.OperationFilter<AssignOAuth2SecurityRequirements>(); 
    }).EnableSwaggerUi(c => 
    { 
    c.EnableOAuth2Support("sampleapi", "samplerealm", "Swagger UI"); 
    }); 

Ważną zmianą tutaj jest .Flow("application") użyłem również .TokenUrl połączenia zamiast .AuthorizationUrl To tylko zależy od konkretnego systemu zezwoleń jest skonfigurowany.

użyłem również nieco inny AssignOAuth2SecurityRequirements klasę

public class AssignOAuth2SecurityRequirements : IOperationFilter 
{ 
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) 
    { 
     var authorized = apiDescription.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>(); 
     if (!authorized.Any()) return; 

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

     var oAuthRequirements = new Dictionary<string, IEnumerable<string>> 
     { 
      {"oauth2", Enumerable.Empty<string>()} 
     }; 

     operation.security.Add(oAuthRequirements); 
    } 
} 

To powinno być wystarczające, aby dostać przełącznik uwierzytelniania pokazać. Innym problemem było dla mnie ustawienie domyślnego okna dialogowego uwierzytelniania, więc użytkownik musi tylko wybrać zakres, a następnie kliknąć autoryzuj. W moim przypadku nie działało to ze względu na sposób, w jaki mam ustawioną autoryzację. Musiałem ponownie zapisać okno dialogowe w skrypcie swagger-oauth.js i wprowadzić je do SwaggerUI.

+0

Czy jest jakiś sposób, aby umożliwić konsumentowi dokumentu Swagger dostarczenie identyfikatora id_klienta lub id_klienta i klucza_prywatnego? – Zoop

+0

Zdecydowanie tak właśnie uwierzytelniasz. Po prostu utwórz żądanie formularza POST formularza logowania za pomocą "grant_type: client_credentials", "id_klienta: " i "secret_key: " i opublikuj go w adresie tokena. Następnie należy podklasować OAuthAuthorizationServerProvider do obsługi logowania. –

+0

Powinienem być bardziej konkretny ... Miałem na myśli poprzez formularz, który wyskoczył. – Zoop

2

miałem nieco więcej kłopotów z dostaniem to wszystko działa, ale po dużo wytrwałości znalazłem rozwiązanie, które działa bez konieczności wstrzykiwać żadnych JavaScript w SwaggerUI. UWAGA: Część moich trudności mogła być spowodowana użyciem serwera IdentityServer3, który jest świetnym produktem, po prostu nie wiedział o problemie z konfiguracją.

Większość moich zmian jest podobna do opisanych powyżej odpowiedzi rachunków, ale mój filtr operacji jest inny. W moim kontroler wszystkie metody mają tagu Autoryzuj bez ról tak:

[Authorize] 
// Not this 
[Authorize(Roles = "Read")] // This doesn't work for me. 

Bez ról zdefiniowanych na Autoryzacja oznaczyć OperationFilter wygląda następująco:

public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) 
    { 
     // Correspond each "Authorize" role to an oauth2 scope, since I don't have any "Roles" defined, this didn't work 
     // and is in most of the Apply methods I found online. If you are like me and your [Authorize] tag doesn't contain 
     // any roles this will not work. 
     //var scopes = apiDescription.ActionDescriptor.GetFilterPipeline() 
     // .Select(filterInfo => filterInfo.Instance) 
     // .OfType<AuthorizeAttribute>() 
     // .SelectMany(attr => attr.Roles.Split(',')) 
     // .Distinct(); 

     var scopes = new List<string>() { "Read" }; // For me I just had one scope that is added to all all my methods, you might have to be more selective on how scopes are added. 

     if (scopes.Any()) 
     { 
      if (operation.security == null) 
       operation.security = new List<IDictionary<string, IEnumerable<string>>>(); 

      var oAuthRequirements = new Dictionary<string, IEnumerable<string>> 
      { 
       { "oauth2", scopes } 
      }; 

      operation.security.Add(oAuthRequirements); 
     } 
    } 

SwaggerConfig wygląda tak:

public static void Register() 
{ 
    var thisAssembly = typeof(SwaggerConfig).Assembly; 
    GlobalConfiguration.Configuration 
     .EnableSwagger(c => 
     { 
      c.SingleApiVersion("v1", "waPortal"); 
      c.OAuth2("oauth2") 
       .Description("OAuth2 Client Credentials Grant Flow") 
       .Flow("application") 
       .TokenUrl("http://security.RogueOne.com/core/connect/token") 
       .Scopes(scopes => 
       { 
        scopes.Add("Read", "Read access to protected resources"); 
       }); 
      c.IncludeXmlComments(GetXmlCommentsPath()); 
      c.UseFullTypeNameInSchemaIds(); 
      c.DescribeAllEnumsAsStrings(); 
      c.OperationFilter<AssignOAuth2SecurityRequirements>(); 
     }) 
     .EnableSwaggerUi(c => 
     { 
      c.EnableOAuth2Support(
       clientId: "swaggerUI", 
       clientSecret: "BigSecretWooH00", 
       realm: "swagger-realm", 
       appName: "Swagger UI" 
      ); 
     }); 
} 

Ostatnia część była najtrudniejsza, aby dowiedzieć się, co w końcu zrobił z pomocą narzędzi Chrome dla programistów, które wykazały mały czerwony X w sieci tag s howing się następujący komunikat o błędzie:

XMLHttpRequest cannot load http://security.RogueOne.com/core/connect/token. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:62561' is therefore not allowed access. 

Opisałem ten błąd tutaj Swagger UI not parsing reponse co było spowodowane IdentityServer3 właściwie nie dodając nagłówek reakcji „Access-Control-Allow-Origin: http://localhost:62561” Można wymusić IdentityServer3 wysłać ten nagłówek przez aktualizację twojego klienta:

new Client 
{ 
    ClientName = "SwaggerUI", 
    Enabled = true, 
    ClientId = "swaggerUI", 
    ClientSecrets = new List<Secret> 
    { 
     new Secret("PasswordGoesHere".Sha256()) 
    }, 
    Flow = Flows.ClientCredentials, 
    AllowClientCredentialsOnly = true, 
    AllowedScopes = new List<string> 
    { 
     "Read" 
    }, 

    Claims = new List<Claim> 
    { 
     new Claim("client_type", "headless"), 
     new Claim("client_owner", "Portal"), 
     new Claim("app_detail", "allow") 
    }, 
    PrefixClientClaims = false 
    // Add the AllowedCorOrigins to get the Access-Control-Allow-Origin header to be inserted for the following domains 
    ,AllowedCorsOrigins = new List<string> 
    { 
     "http://localhost:62561/" 
     ,"http://portaldev.RogueOne.com" 
     ,"https://portaldev.RogueOne.com" 
    } 
}  

The AllowedCorsOrigins był ostatnim elementem mojej układanki. Mam nadzieję, że to pomoże komuś, kto stoi w obliczu tego samego problemu.

Powiązane problemy