如何通过 DotNetOpenAuth 使用 OAuth2 访问令牌授权对 ServiceStack 资源的访问? [英] How do I authorize access to ServiceStack resources using OAuth2 access tokens via DotNetOpenAuth?

查看:33
本文介绍了如何通过 DotNetOpenAuth 使用 OAuth2 访问令牌授权对 ServiceStack 资源的访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用 DotNetOpenAuth 创建了一个 OAuth2 授权服务器,它工作正常 - 我正在使用资源所有者密码流,并成功地将用户凭据交换为访问令牌.

我现在想使用该访问令牌从 ServiceStack API 中的安全端点检索数据,但我不知道该怎么做.我已经检查了 ServiceStack 中包含的 Facebook、Google 等提供商,但不清楚我是否应该遵循相同的模式.

我想要达到的(我认为!)是

  1. OAuth 客户端(我的应用)要求资源所有者(Catherine Smith")提供凭据
  2. 客户端授权服务器提交请求,收到一个访问令牌
  3. 客户端资源服务器请求一个安全的资源 (GET/users/csmith/photos)
    • 访问令牌包含在 HTTP 标头中,例如授权:Bearer 1234abcd...
  4. 资源服务器解密访问令牌以验证资源所有者的身份
  5. 资源服务器检查资源所有者是否有权访问所请求的资源
  6. 资源服务器资源返回给客户端

步骤 1 和 2 正在运行,但我不知道如何将 DotNetOpenAuth 资源服务器代码与 ServiceStack 授权框架集成.

有什么地方可以说明我如何实现这一目标吗?我在

public class RequireScopeAttribute : Attribute, IHasRequestFilter {public void RequireScope(IHttpRequest req, IHttpResponse res, object requestDto){//这段代码在服务之前执行//如果用户缺少所需的范围,则关闭请求}...}

然后按照您的概述装饰您的 DTO 或服务:

使用ServiceStack.ServiceInterface;使用 SpotAuth.Common.ServiceModel;命名空间 SpotAuth.ResourceServer.Services {[RequireScope("你好")]公共类HelloService:服务{公共对象任何(你好请求){return new HelloResponse { Result = "Hello, " + request.Name };}}}

您的 RequireScope 自定义过滤器几乎与 ServiceStack 的 RequiredRoleAttribute 实现相同.,因此将其用作编码的起点.

或者,您可以将范围映射到权限.然后相应地装饰你的 DTO 或服务(详见 SS wiki)例如:

[验证][RequiredPermission("你好")]公共类HelloService:服务{公共对象任何(你好请求){return new HelloResponse { Result = "Hello, " + request.Name };}}

通常ServiceStack调用IAuthSession中的bool HasPermission(string permission)方法.此方法检查 IAuthSession 中的 List Permissions 列表是否包含所需的权限,因此,在自定义 IAuthSession 中,您可以覆盖 HasPermission 并将您的 OAuth2 范围检查在那里.

I've created an OAuth2 authorization server using DotNetOpenAuth, which is working fine - I'm using the resource owner password flow, and successfully exchanging user credentials for an access token.

I now want to use that access token to retrieve data from secure endpoints in a ServiceStack API, and I can't work out how to do so. I've examined the Facebook, Google, etc. providers included with ServiceStack but it's not clear whether I should be following the same pattern or not.

What I'm trying to achieve (I think!) is

  1. OAuth client (my app) asks resource owner ('Catherine Smith') for credentials
  2. Client submits request to authorization server, receives an access token
  3. Client requests a secure resource from the resource server (GET /users/csmith/photos)
    • The access token is included in an HTTP header, e.g. Authorization: Bearer 1234abcd...
  4. The resource server decrypts the access token to verify the identity of the resource owner
  5. The resource server checks that the resource owner has access to the requested resource
  6. The resource server returns the resource to the client

Steps 1 and 2 are working, but I can't work out how to integrate the DotNetOpenAuth resource server code with the ServiceStack authorization framework.

Is there an example somewhere of how I would achieve this? I've found a similar StackOverflow post at How to build secured api using ServiceStack as resource server with OAuth2.0? but it isn't a complete solution and doesn't seem to use the ServiceStack authorization provider model.

EDIT: A little more detail. There's two different web apps in play here. One is the authentication/authorisation server - this doesn't host any customer data (i.e. no data API), but exposes the /oauth/token method that will accept a username/password and return an OAuth2 access token and refresh token, and also provides token-refresh capability. This is built on ASP.NET MVC because it's almost identical to the AuthorizationServer sample included with DotNetOpenAuth. This might be replaced later, but for now it's ASP.NET MVC.

For the actual data API, I'm using ServiceStack because I find it much better than WebAPI or MVC for exposing ReSTful data services.

So in the following example:

the Client is a desktop application running on a user's local machine, the Auth server is ASP.NET MVC + DotNetOpenAuth, and the Resource server is ServiceStack

The particular snippet of DotNetOpenAuth code that's required is:

// scopes is the specific OAuth2 scope associated with the current API call.
var scopes = new string[] { "some_scope", "some_other_scope" }

var analyzer = new StandardAccessTokenAnalyzer(authServerPublicKey, resourceServerPrivateKey);
var resourceServer = new DotNetOpenAuth.OAuth2.ResourceServer(analyzer);
var wrappedRequest = System.Web.HttpRequestWrapper(HttpContext.Current.Request);
var principal = resourceServer.GetPrincipal(wrappedRequest, scopes);

if (principal != null) {
    // We've verified that the OAuth2 access token grants this principal
    // access to the requested scope.
}

So, assuming I'm on the right track, what I need to do is to run that code somewhere in the ServiceStack request pipeline, to verify that the Authorization header in the API request represents a valid principal who has granted access to the requested scope.

I'm starting to think the most logical place to implement this is in a custom attribute that I use to decorate my ServiceStack service implementations:

using ServiceStack.ServiceInterface;
using SpotAuth.Common.ServiceModel;

namespace SpotAuth.ResourceServer.Services {
    [RequireScope("hello")]
    public class HelloService : Service {
        public object Any(Hello request) {
            return new HelloResponse { Result = "Hello, " + request.Name };
        }
    }
}

This approach would also allow specifying the scope(s) required for each service method. However, that seems to run rather contrary to the 'pluggable' principle behind OAuth2, and to the extensibility hooks built in to ServiceStack's AuthProvider model.

In other words - I'm worried I'm banging in a nail with a shoe because I can't find a hammer...

解决方案

Update On further reflection, your initial thought, to create a RequiredScope attribute would be a cleaner way to go. Adding it to the ServiceStack pipeline is as easy as adding the IHasRequestFilter interface, implementing a custom request filter, as documented here: https://github.com/ServiceStack/ServiceStack/wiki/Filter-attributes

public class RequireScopeAttribute : Attribute, IHasRequestFilter {
  public void RequireScope(IHttpRequest req, IHttpResponse res, object requestDto)
  {
      //This code is executed before the service
      //Close the request if user lacks required scope
  }

  ...
}

Then decorate your DTO's or Services as you've outlined:

using ServiceStack.ServiceInterface;
using SpotAuth.Common.ServiceModel;

namespace SpotAuth.ResourceServer.Services {
    [RequireScope("hello")]
    public class HelloService : Service {
        public object Any(Hello request) {
            return new HelloResponse { Result = "Hello, " + request.Name };
        }
    }
}   

Your RequireScope custom filter would be almost identical to ServiceStack's RequiredRoleAttribute implementation., so use it as a starting point to code from.

Alternately, you could map scope to permission. Then decorate your DTO or service accordingly (see SS wiki for details) for example:

[Authenticate]
[RequiredPermission("Hello")]
    public class HelloService : Service {
        public object Any(Hello request) {
            return new HelloResponse { Result = "Hello, " + request.Name };
        }
    }

Normally ServiceStack calls the method bool HasPermission(string permission) in IAuthSession. This method checks if the list List Permissions in IAuthSession contains the required permission, so, in a custom IAuthSession you could override HasPermission and put your OAuth2 scopes checking there.

这篇关于如何通过 DotNetOpenAuth 使用 OAuth2 访问令牌授权对 ServiceStack 资源的访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆