【问题标题】:API end point returning "Authorization has been denied for this request." when sending bearer tokenAPI 端点返回“此请求的授权已被拒绝。”发送不记名令牌时
【发布时间】:2015-03-10 19:27:03
【问题描述】:

我按照教程在 C# 中使用 OAuth 保护 Web API。

我正在做一些测试,到目前为止,我已经能够从/token 成功获取访问令牌。我正在使用一个名为“Advanced REST Client”的 Chrome 扩展来测试它。

{"access_token":"...","token_type":"bearer","expires_in":86399}

这是我从/token 得到的。一切看起来都不错。

我的下一个请求是我的测试 API 控制器:

namespace API.Controllers
{
    [Authorize]
    [RoutePrefix("api/Social")]
    public class SocialController : ApiController
    {
      ....


        [HttpPost]
        public IHttpActionResult Schedule(SocialPost post)
        {
            var test = HttpContext.Current.GetOwinContext().Authentication.User;

            ....
            return Ok();
        }
    }
}

请求是一个POST 并且有标题:

Authorization: Bearer XXXXXXXTOKEHEREXXXXXXX

我得到:Authorization has been denied for this request. 以 JSON 格式返回。

我也尝试过执行 GET,但我得到了我所期望的结果,即不支持该方法,因为我没有实现它。

这是我的授权提供者:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        using (var repo = new AuthRepository())
        {
            IdentityUser user = await repo.FindUser(context.UserName, context.Password);

            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }
        }

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
        identity.AddClaim(new Claim(ClaimTypes.Role, "User"));

        context.Validated(identity); 

    }
}

任何帮助都会很棒。我不确定是请求还是代码错误。

编辑: 这是我的Startup.cs

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        WebApiConfig.Register(config);
        app.UseWebApi(config);
        ConfigureOAuth(app);
    }

    public void ConfigureOAuth(IAppBuilder app)
    {
        var oAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider()
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }
}

【问题讨论】:

    标签: c# oauth asp.net-web-api2 owin


    【解决方案1】:

    问题很简单: 更改 OWIN 管道的顺序

    public void Configuration(IAppBuilder app)
    {
        ConfigureOAuth(app);
        var config = new HttpConfiguration();
        WebApiConfig.Register(config);
        app.UseWebApi(config);
    }
    

    对于你的配置的 OWIN 管道顺序相当重要。在您的情况下,您尝试在 OAuth 处理程序之前使用您的 Web API 处理程序。在其中,您验证您的请求,发现您采取了安全措施并尝试根据当前的Owin.Context.User 验证它。此时此用户不存在,因为它使用稍后调用的 OAuth Handler 的令牌设置。

    【讨论】:

    • 如果你没有在管道中注册 WebApi,你会怎么做?我只是在使用默认的 Web API 模板。 GET 请求工作正常,POST 请求给我 401。虽然令牌是相同的。
    • 这让我大吃一惊!感谢您抽出宝贵时间发布此答案。
    • 我在重构后浪费了几个小时试图找到这个问题的原因。
    • 天哪,我不会发布我浪费的时间试图弄清楚这一点,谢谢!
    【解决方案2】:

    看起来与其他 Owin 程序集共存的“System.IdentityModel.Tokens.Jwt”版本不正确。

    如果您使用的是“Microsoft.Owin.Security.Jwt”版本 2.1.0,则应该使用版本 3.0.2 的“System.IdentityModel.Tokens.Jwt”程序集。

    从包管理器控制台尝试:

    Update-Package System.IdentityModel.Tokens.Jwt -Version 3.0.2
    

    【讨论】:

      【解决方案3】:

      您必须使用此架构添加声明:

      http://schemas.microsoft.com/ws/2008/06/identity/claims/role
      

      最好的办法是使用预定义的声明集:

      identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
      

      您可以在System.Security.Claims 中找到ClaimTypes

      您必须考虑的另一件事是在控制器/操作中过滤角色:

      [Authorize(Roles="User")]
      

      您可以找到一个简单的示例应用程序,使用 jquery 客户端 here 自托管 owin。

      【讨论】:

      • 我添加了:identity.AddClaim(new Claim(ClaimTypes.Role, "User")); 无济于事。用户就是资本重要吗?我在看到你的评论之前添加了这个。我不认为那会很重要。我会看看你的链接。
      • 这是一个常数,可以是任何东西。
      • 我尝试更改 [Authorize] 以将角色包含在我的控制器中,但我仍然没有获得授权。我在角色“用户”中创建了一个新用户并成功获得了一个新令牌。用您建议的更改更新了我上面的代码。
      猜你喜欢
      • 2016-08-29
      • 2016-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-17
      • 2019-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多