Веб-API с OAUTH с использованием Swagger/Swashbuckle

Я пытаюсь заставить мой проект веб-API использовать красивую документацию Swagger и т.д. (http://swagger.io/)

Я использую Swashbuckle для .NET, установленную из NuGet, и использую версию 4.0.1

Я был в состоянии установить и использовать Swagger. На данный момент все кажется нормальным. Единственное препятствие, которое у меня есть, это отключение ключа API и возможность использовать OAuth, как в примере с PetStore (http://petstore.swagger.wordnik.com/#!/pet/addPet)

Я перепробовал все, что мог найти в Интернете. Позвольте мне перечислить их ниже:

Во-первых, вот мой Startup.cs

public void Configuration(IAppBuilder app)
{
    var config = new HttpConfiguration();

    WebApiConfig.Register(config);

    Swashbuckle.Bootstrapper.Init(config);
}

Теперь мой SwaggerConfig.cs:

public static void Register()
{
    Swashbuckle.Bootstrapper.Init(GlobalConfiguration.Configuration);

    SwaggerSpecConfig.Customize(c =>
    {
        c.IgnoreObsoleteActions();

        c.IncludeXmlComments(GetXmlCommentsPath());

        c.ApiInfo(new Info
        {
            Title = "Work you",
            Description = "testing some stuffs",
            Contact = "[email protected]"
        });

        c.Authorization("oauth2", new Authorization
        {
            Type = "oauth2",
            Scopes = new List<Scope>
                {
                    new Scope { ScopeId = "products.read", Description = "View products" },
                    new Scope { ScopeId = "products.manage", Description = "Manage products" }
                },
            GrantTypes = new GrantTypes
            {
                ImplicitGrant = new ImplicitGrant
                {
                    LoginEndpoint = new LoginEndpoint
                    {
                        Url = "https://www.mysecure.website.com"
                    },
                    TokenName = "access_token"
                }
            }
        });
    });


    SwaggerUiConfig.Customize(c =>
    {
        c.EnableOAuth2Support("client_id", "test-realm", "app Name");

        var thisAssembly = typeof(SwaggerConfig).Assembly;

        c.SupportHeaderParams = true;
        c.DocExpansion = DocExpansion.List;
        c.SupportedSubmitMethods = new[] { HttpMethod.Get, HttpMethod.Post, HttpMethod.Put, HttpMethod.Head };
        c.EnableDiscoveryUrlSelector();

    });

}

У меня есть папка SwaggerExtensions, там у меня есть файлы, которые должны быть запрошены. Например:

Files for SwaggerExt

У меня есть классы, украшенные:

[ScopeAuthorize("this.scope")]

Тем не менее, опция OAuth никогда не отображается для меня на странице чванства. Я также не вижу, где я могу вводить пользовательские заголовки.

Я вижу, что заголовок и описание документации, адрес электронной почты и т.д. Читаются из файла SwaggerConfig.cs, поэтому я знаю, что он по крайней мере читается.

Я не могу понять это. :(

Есть идеи?

Ответы

Ответ 1

Я получил свое решение. Это мощно, просто не на 100% прямо настроить.

Вот шаги, которые я сделал:

Установите пакет NuGet, я использовал PM> Install-Package Swashbuckle -Version 4.1.0, но ссылка находится в https://www.nuget.org/packages/Swashbuckle/, и я бы рекомендовал получить последнюю версию, но я знать 4.1.0. EDIT Я просто обновился до 5.X, и он сломал его. 4.1.0 работает, но последний этого не делал. Я еще не исследовал, почему еще.

Как только вы установите это, вы почти закончите.

Установка создаст файл SwaggerConfig.cs. Это код, который я использовал (скопирован из мастера github)

public class SwaggerConfig
    {
        public static void Register()
        {
            Swashbuckle.Bootstrapper.Init(GlobalConfiguration.Configuration);

            SwaggerSpecConfig.Customize(c =>
            {
                c.IgnoreObsoleteActions();

                //c.SupportMultipleApiVersions(
                //    new[] { "1.0", "2.0" },
                //    ResolveVersionSupportByRouteConstraint);

                //c.PolymorphicType<Animal>(ac => ac
                //    .DiscriminateBy(a => a.Type)
                //    .SubType<Kitten>());

                c.OperationFilter<AddStandardResponseCodes>();
                c.OperationFilter<AddAuthResponseCodes>();
                c.OperationFilter<AddOAuth2Scopes>();

                //c.IncludeXmlComments(GetXmlCommentsPath());

                c.ApiInfo(new Info
                {
                    Title = "Swashbuckle Dummy",
                    Description = "For testing and experimenting with Swashbuckle features",
                    Contact = "[email protected]"
                });

                c.Authorization("oauth2", new Authorization
                {
                    Type = "oauth2",
                    Scopes = new List<Scope>
                        {
                            new Scope { ScopeId = "test1", Description = "test1" },
                            new Scope { ScopeId = "test2", Description = "test2" }
                        },
                    GrantTypes = new GrantTypes
                    {
                        ImplicitGrant = new ImplicitGrant
                        {
                            LoginEndpoint = new LoginEndpoint
                            {
                                Url = "https://your.Oauth.server/Authorize"
                            },
                            TokenName = "access_token"
                        }
                    }
                });
            });

            SwaggerUiConfig.Customize(c =>
            {
                var thisAssembly = typeof(SwaggerConfig).Assembly;

                c.SupportHeaderParams = true;
                c.DocExpansion = DocExpansion.List;
                c.SupportedSubmitMethods = new[] { HttpMethod.Get, HttpMethod.Post, HttpMethod.Put, HttpMethod.Head };
                //c.InjectJavaScript(typeof(SwaggerConfig).Assembly, "WebApplication4.SwaggerExtensions.onComplete.js");
                //c.EnableDiscoveryUrlSelector();
                //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
                //c.InjectStylesheet(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");

                c.EnableOAuth2Support("client_id", "realm", "Swagger UI");
            });
            // NOTE: If you want to customize the generated swagger or UI, use SwaggerSpecConfig and/or SwaggerUiConfig here ...
        }
        private static string GetXmlCommentsPath()
        {
            return String.Format(@"{0}\XmlComments.xml", AppDomain.CurrentDomain.BaseDirectory);
        }

Теперь мы сказали Swagger, что хотим использовать OAuth, и именно так мы хотим его использовать. Совершено, верно? Нет.

Вам нужно добавить эту папку и файлы в ваше решение: https://github.com/domaindrivendev/Swashbuckle/tree/master/Swashbuckle.Dummy.Core/SwaggerExtensions

(вам нужны только файлы .cs)

Убедитесь, что ваши пространства имен правы...

Затем вам нужно украсить свой класс в WebAPI, например:

[ScopeAuthorize("test1")]

Теперь, когда вы запустите его и перейдите на страницу разворота, вы увидите, что каждая операция, в которой есть это объявление, будет иметь переключатель OAuth в верхнем правом углу. Когда вы нажимаете на нее, вы можете использовать Неявный поток грантов и получить токен, который будет добавлен к вашему запросу.

Это будет работать только с неявным грантом от того, что я нашел. Кажется, они пытались получить AuthorizationCode Grant, но файлы js, которые они построили, поддерживают только неявные из того, что я вижу.

Надеюсь, это поможет кому-то. Это мощный инструмент, и я надеюсь, что мы увидим, что другие сайты используют что-то вроде этого.

Спасибо и удачи!

Ответ 2

Я думаю, что большинство из того, что у вас было изначально, было в порядке. Я использую Swashbuckle 5.2.1 и хорошо работает. Я только что написал сообщение в блоге (http://knowyourtoolset.com/2015/08/secure-web-apis-with-swagger-swashbuckle-and-oauth2-part-2/), которое объясняет это в деталях, но суть добавляет класс OperationFilter (es) которые определяют, какой из ваших методов API получит на них кнопку переключения OAuth21. Существуют определения (примеры) в папке SwaggerExtensions из GitHub, как указано выше, но на самом деле все, что вам нужно, по крайней мере, для одного класса, который реализует IOperationFilter и его метод Apply. У меня есть образец класса ниже. Имя класса действительно не имеет значения (и где оно), вам просто нужно включить его (и любые другие, если у вас есть) в SwaggerConfig, где указаны OperationFilter (ы).

 public class AssignOAuth2SecurityRequirements : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
        var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
        if (allowsAnonymous)
            return; // must be an anonymous method


        //var scopes = apiDescription.ActionDescriptor.GetFilterPipeline()
        //    .Select(filterInfo => filterInfo.Instance)
        //    .OfType<AllowAnonymousAttribute>()
        //    .SelectMany(attr => attr.Roles.Split(','))
        //    .Distinct();

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

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

        operation.security.Add(oAuthRequirements);
    }
}

Ответ 3

По умолчанию, swagger-ui не отображает интеграцию OAuth2.

Чтобы включить его, вам необходимо выполнить следующие действия:

  • Убедитесь, что <script src='lib/swagger-oauth.js' type='text/javascript'></script> включен в список скриптов в верхней части index.html. Он должен быть там по умолчанию.
  • В объявлении SwaggerUi в нижней части index.html раскомментируйте следующий фрагмент кода (он там и прокомментирован по умолчанию):

        /*
        initOAuth({
          clientId: "your-client-id",
          realm: "your-realms",
          appName: "your-app-name"
        });
        */
    

Вероятно, вы захотите изменить clientId, realm и appName своими собственными настройками.