Swagger启用客户端oAuth凭据

时间:2016-10-03 12:50:29

标签: c# oauth swagger

我试图将Swagger(通过Swashbuckle)设置到我的webApi上。我已经明白了它成功地展示了我的方法,并且开放方法运行良好。

我的Api上的大多数方法都使用oAuth2进行身份验证,使用client_credentials授权类型。我尝试设置Swagger UI,以便用户可以将其凭据输入文本框,然后让它使用。

这是我到目前为止所做的:

Swashbuckle配置

public static class SwashbuckleConfig
{
    public static void Configure(HttpConfiguration config)
    {
        config.EnableSwagger(c =>
            {
                c.SingleApiVersion("v1", "Configuration Api Config");
                c.OAuth2("oauth2")
                    .Description("OAuth2")
                    .Flow("application")
                    .TokenUrl("http://localhost:55236/oauth/token")
                    .Scopes(scopes =>
                    {
                        scopes.Add("write", "Write Access to protected resources");
                    });

                c.OperationFilter<AssignOAuth2SecurityRequirements>();
            })
            .EnableSwaggerUi(c =>
            {
                c.EnableOAuth2Support("Test", "21", "Test.Documentation");
                c.InjectJavaScript(Assembly.GetAssembly(typeof(SwashbuckleConfig)), 
                          "InternalAPI.Swagger.client-credentials.js");

            });
    }

    public class AssignOAuth2SecurityRequirements : IOperationFilter
    {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, 
                      ApiDescription apiDescription)
        {
            //All methods are secured by default, 
            //unless explicitly specifying an AllowAnonymous attribute.
            var anonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>();
            if (anonymous.Any()) return;

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

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

            operation.security.Add(requirements);
        }
    }
}

客户credentials.js

(function () {
    $(function () {
        var basicAuthUi =
            '<div class="input">' +
                '<label text="Client Id" /><input placeholder="clientId" id="input_clientId" name="Client Id" type="text" size="25">' +
                '<label text="Client Secret" /><input placeholder="secret" id="input_secret" name="Client Secret" type="password" size="25">' +
                '</div>';

        $(basicAuthUi).insertBefore('div.info_title');
        $("#input_apiKey").hide();

        $('#input_clientId').change(addAuthorization);
        $('#input_secret').change(addAuthorization);
    });

    function addAuthorization() {
        var username = $('#input_clientId').val();
        var password = $('#input_secret').val();

        if (username && username.trim() !== "" && password && password.trim() !== "") {

            //What do I need to do here??
            //var basicAuth = new SwaggerClient.oauth2AUthorisation(username, password);
            //window.swaggerUi.api.clientAuthorizations.add("oauth2", basicAuth);

            console.log("Authorization added: ClientId = " 
               + username + ", Secret = " + password);
        }
    }
})();

我尝试修改的客户端示例来自here。显然这是基本身份验证,但我需要修改它以适应oAuth。

在调用Api方法之前,我需要做什么才能生成令牌?

1 个答案:

答案 0 :(得分:0)

首先我想说你不能使用来自客户端的客户端凭证流; 但是我今天也违反了这条规则:)。一直到用户输入它应该没问题(我希望您使用TLS)。

通常你会在这里实现隐式类型,你可以在这里查看如何(我个人没试过):https://danielwertheim.se/use-identityserver-in-swaggerui-to-consume-a-secured-asp-net-webapi/

所以你需要删除这个安全定义: c.OperationFilter(); 剩下的就可以了。

然后添加此代码:

  function addApiKeyAuthorization() {

            var clientId = $('#input_clientid')[0].value;
            var clientSecret = $('#input_clientsecret')[0].value;

            if (clientId == '' || clientSecret == "")
                return;

            var token = getToken(clientId, clientSecret, 'a defined scope');

            var authKeyHeader = new SwaggerClient.ApiKeyAuthorization("Authorization", "Bearer " + token.access_token, "header");
            console.log("authKeyHeader", authKeyHeader);
            window.swaggerUi.api.clientAuthorizations.add("Authorization", authKeyHeader);

            //handle token expiration here
        }

        function getToken(clientId, clientSecret, scope) {

            var authorizationUrl = '<url to token service>/connect/token';
            var authorizationParams = "grant_type=client_credentials&scope=" + scope;
            var basicAuth = window.btoa(clientId + ":" + clientSecret)
            var token = "";

            $.ajax({
                type: 'POST',
                url: authorizationUrl,
                contenttype: 'x-www-form-urlencoded',
                headers: {
                    'Authorization': 'basic ' + basicAuth
                },
                data: authorizationParams,
                success: function (data) {
                    token = data;
                },
                error: function (data) {
                    // don't worry about it, swagger will respond that something went wrong : )
                },
                async: false
            });

            return token;
            //example response format: {access_token: "86f2bc88dcd1e6919ef0dadbde726c52", expires_in: 3600, token_type: "Bearer"}
        }

        $('#explore').on('click', addApiKeyAuthorization);

我希望这会有所帮助。玩得开心:))