从ASP.NET WebAPI 2中的标头和/或查询字符串中检索承载标记

时间:2016-02-14 09:54:54

标签: asp.net-web-api signalr asp.net-identity signalr-hub

背景

我有一个ASP.NET WebAPI项目。我使用Bearer Tokens对我的用户进行身份验证。我的一些控制器操作标有[Authorized]过滤器。在客户端,客户端通过调用http://foo.bar/Token获取其令牌,然后将该令牌作为Authorization标头添加到其请求中。

到目前为止没有问题,我的Startup.Auth.cs课程中的所有设置都能正常运行:

OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    // In production mode set AllowInsecureHttp = false
    AllowInsecureHttp = true                
};

// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);

现在我已经为我的项目添加了一些SignalR Hub,并且我也希望对集线器中的用户进行身份验证。还有一些其他问题涉及客户端如何向SignalR连接添加承载令牌。总结:

我尝试了什么:

所以我创建了这个类来从查询字符串中检索我的访问令牌。

public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider
{
    public override Task RequestToken(OAuthRequestTokenContext context)
    {
        var value = context.Request.Query.Get("access_token");

        if (!string.IsNullOrEmpty(value))
        {
            context.Token = value;
        }

        return Task.FromResult<object>(null);
    }
}

然后在客户端,我这样做是为了传递我的访问令牌:

var connection = $.hubConnection();
var hub = connection.createHubProxy('fooHub');
connection.qs = { 'access_token': myAccessToken};
// Init connection

这是一个想法,但当我想在QueryStringOAuthBearerProvider课程中注册我的Startup.Auth.cs时会出现问题。

以下是我更改Startup.Auth.cs类的方法:

OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    // In production mode set AllowInsecureHttp = false
    AllowInsecureHttp = true                
};

// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);

// Enable the application to retrieve tokens from query string to authenticate users
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
    Provider = new QueryStringOAuthBearerProvider()
});

所以我想我现在可以使用:

  1. 默认承载令牌,位于我的WebAPI请求的标头中。
  2. 我的SignalR Hubs的查询字符串中的自定义访问令牌。
  3. 结果:

    当我连接到我的集线器时,我可以从查询字符串中检索访问令牌,并对用户进行身份验证。但是当我尝试调用WebAPI控制器操作时,我得System.InvalidOperationExceptionSequence contains more than one element。我认为这是因为我通过承载令牌注册了两种方式来验证我的用户,而OWIN并不喜欢这样。

    问题:

    如何使用这两种方法获取持票人令牌?

    • WebApi调用的默认行为(授权标头)
    • QueryStringOAuthBearerProvider(查询字符串)用于SignalR Hub。

    请注意,我不想将访问令牌作为查询字符串传递给我的WebApi操作,但仅限于SignalR Hub。

2 个答案:

答案 0 :(得分:7)

在盲目搜索答案的同时,我遇到了一个 post ,与我的问题有些相似,并在评论中名为 mahmoud 的评论说:

  

我发现了问题。而不是使用app.UseOAuthBearerTokens(OAuthOptions)申请app.UseOAuthAuthorizationServer(OAuthOptions)

它适用于我的情况,现在我可以使用这两种方法来获取持有者令牌。这是我修改过的Startup.Auth.cs类:

OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    // In production mode set AllowInsecureHttp = false
    AllowInsecureHttp = true                
};

// Enable the application to use bearer tokens to authenticate users

//app.UseOAuthBearerTokens(OAuthOptions);   // Commented this line.

app.UseOAuthAuthorizationServer(OAuthOptions); // Added this line

// Enable the application to retrieve tokens from query string to authenticate users
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
    Provider = new QueryStringOAuthBearerProvider()
});

答案 1 :(得分:0)

我使用了逻辑,但在QueryStringOAuthBearerProvider类中做了一些更新,然后我得到了正确的结果..

defineCommand(NEW_SESSION, post("/session"));