SwashBuckle / Swagger - OAuth资源所有者密码流

时间:2016-01-21 16:35:58

标签: asp.net-web-api2 swagger-ui swagger-2.0 swashbuckle

我试图在我的Asp.Net Web API中实现招摇,并且我遇到了问题。

我使用密码资源所有者流程,并且我必须添加一个解决方法才能执行此操作,这在以下堆栈溢出问题中有所涉及: -

Swagger/Swashbuckle: OAuth2 with Resource Owner Password Credentials Grant

我已经完成了所有工作,通过javascript将Bearer令牌添加到当前浏览器窗口中的请求标头,但是api调用需要授权的控制器方法仍然返回" 401 - 授权失败& #34;

以下是获取持票人令牌并添加标题的JavaScript: -

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

Swagger响应中的卷曲是: -

  

curl -X GET --header"接受:application / json" --header   "授权:持票人   NqlSG-WyTx2zkYE8xFklGyZWlQDZdsCKZBHruEXvX47N7PAzw4-jZ4eH5D0yFzQTXj13RwKFFt1rUZt2fzWj1vR5UR87wdlKC3YvsTojYV4-3DsWwY7qYRfiKPuM0j09c3X5lnrtlBVJ1rBRUH0TLjfw_yGxgoLBwOJl9xyC1YWNoPOe2nzL4lMOHodAnMem0IBMJmUo3Rt575tnWAbBsQXWhlImDIxCZXvkZdJtlXfIfBSUdY9gfRWL0ZjKbf7m2-yLzH0gpMAMuKaADmJlIudJc0d4SP1Nn2Kh2HuVH8CX4QgZuu4egl9N6rY2smorP2vBSC4_dC4CpmYYzOTu2wUnUhHDY2Q6NWl377ijDKwZLcW9jtD-2tBiEGmFuRV0mVGnh0zc4w9Ao9jPCdtrbSyGitgloBW-UG2bfyao3eE"   " http://localhost:42291/api/v1/claims"

我根本看不出任何问题。

然后我使用Postman来调用完全相同的URL调用,使用javascript调用中生成的相同访问令牌...

猜猜......它运作正常。

修改

我尝试从控制器中删除授​​权属性,这样我就可以检查请求是否符合控制器方法。

查看请求标头,Authorization属性为null。

不确定为什么会这样。 CURL建议将其放入请求中。

编辑2

我已加入我的安全定义: -

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

编辑3 在通过命令行直接通过cURL公开时,此api调用的Swagger UI中显示的cURL可以正常工作。

现在我完全糊涂了。

2 个答案:

答案 0 :(得分:8)

我设法纠正了这个问题。这是一种简单的类型不匹配,给我带来了几天的悲伤。

在onComplete.JS中,我需要创建一个与swagger规范中显示的键匹配的键。

如果您检查上面的代码片段,您会看到我创建了一个密钥并将其命名为#34;授权"。但这与命名的安全性定义不匹配" oauth2"。

工作代码: -

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

为了进一步解释这一点,您需要创建IOperationFilter的实现,以便swagger可以确定api的哪些方法需要Authorizaion。正确配置后,您应该在swagger规范中看到针对每个api调用的安全性定义: -

enter image description here

我的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);
        }
    }

答案 1 :(得分:2)

授权机制期望每个操作都分配了security。如果不存在,则不会发送标头。如果您认为已正确分配

,请分享您的spec文件