我已经使用 DotNetOpenAuth 创建了一个 OAuth2 授权服务器,它工作正常 - 我正在使用资源所有者密码流,并成功地将用户凭据交换为访问令牌。
我现在想使用该访问令牌从 ServiceStack API 中的安全端点检索数据,但我不知道该怎么做。我检查了 ServiceStack 中包含的 Facebook、Google 等提供商,但不清楚我是否应该遵循相同的模式。
我想要实现的(我认为!)是
- OAuth客户端(我的应用程序)向资源所有者('Catherine Smith')询问凭据
- 客户端向授权服务器提交请求,接收访问令牌
- 客户端向资源服务器请求安全资源( )
GET /users/csmith/photos
- 访问令牌包含在HTTP 标头中,例如
Authorization: Bearer 1234abcd...
- 访问令牌包含在HTTP 标头中,例如
- 资源服务器解密访问令牌以验证资源所有者的身份
- 资源服务器检查资源所有者是否有权访问请求的资源
- 资源服务器将资源返回给客户端
第 1 步和第 2 步正在工作,但我不知道如何将 DotNetOpenAuth 资源服务器代码与 ServiceStack 授权框架集成。
有没有一个例子说明我将如何实现这一目标?我在How to buildsecure api using ServiceStack as resource server with OAuth2.0 中找到了类似的 StackOverflow 帖子?但它不是一个完整的解决方案,并且似乎没有使用 ServiceStack 授权提供者模型。
编辑:更详细一点。这里有两个不同的网络应用程序。一个是身份验证/授权服务器 - 它不托管任何客户数据(即没有数据 API),但公开了 /oauth/token 方法,该方法将接受用户名/密码并返回 OAuth2 访问令牌和刷新令牌,以及提供令牌刷新功能。这是基于 ASP.NET MVC 构建的,因为它与 DotNetOpenAuth 中包含的 AuthorizationServer 示例几乎相同。这可能会在以后被替换,但现在它是 ASP.NET MVC。
对于实际的数据 API,我使用的是 ServiceStack,因为我发现它比 WebAPI 或 MVC 在公开 ReSTful 数据服务方面要好得多。
所以在下面的例子中:
Client是运行在用户本地机器上的桌面应用程序,Auth服务器是 ASP.NET MVC + DotNetOpenAuth,Resource 服务器是 ServiceStack
所需的特定 DotNetOpenAuth 代码片段是:
// 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.
}
因此,假设我走在正确的轨道上,我需要做的是在 ServiceStack 请求管道中的某处运行该代码,以验证 API 请求中的 Authorization 标头是否代表已授予对所请求范围的访问权限的有效主体.
我开始认为实现这一点最合乎逻辑的地方是在我用来装饰我的 ServiceStack 服务实现的自定义属性中:
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 };
}
}
}
这种方法还允许指定每个服务方法所需的范围。然而,这似乎与 OAuth2 背后的“可插拔”原则以及 ServiceStack 的 AuthProvider 模型中内置的可扩展性挂钩完全相反。
换句话说-我担心我会用鞋子敲钉子,因为我找不到锤子...