两个不同的OWIN应用程序可以授权OAuth2承载访问令牌吗?

时间:2015-12-01 13:10:14

标签: asp.net asp.net-web-api oauth asp.net-identity owin

我有两个Web API:

  • Identity API 。它实现了身份验证,用户注册和OAuth客户端注册和身份验证。
  • 产品API 。一组与我的业务合作的RESTful API。

我使用 Identity API 对资源所有者(即具有用户+密码凭据的用户)进行身份验证,以使用OAuth2 OWIN中间件获取持有者令牌。

我的问题是,一旦我从 Identity API 获得访问令牌,我想用它来授权对 Product API 的请求。

两个API都访问同一个数据库,两者现在都在同一台机器上。

当我尝试针对产品API 执行请求时,我收到了响应消息"Authorization has been denied for this request",而对 Identity API 执行请求则完美无瑕。

关键是我派生OAuthAuthorizationServerProvider来满足一些自定义身份验证/授权要求,但是在发布时它永远不会到达(ValidateClientAuthenticationGrantResourceOwnerCredentials方法永远不会被调用)对 Product API 的请求。

我已经放弃了OWIN中间件的顺序可能会影响身份验证流程:两个API都以相同的方式配置。

前几天......

...在尝试以这种方式工作之前,我正在考虑创建自定义OAuthAuthorizationServerProvider和ASP.NET Identity用户存储以在内部实际查询 Identity API ,因此,身份验证和授权都将在发布访问令牌的OWIN应用程序中进行验证。

我已经为ASP.NET Identity(GitHub repository)实现了一个自定义用户存储,我还没有实现OAuthAuthorizationServerProvider来发出HTTP请求,而不是直接使用底层数据库

Anwyay,我想知道我是否可以避免这样做一段时间,如果我可以从OWIN应用程序发出访问权限并使用来自不同主机的不同OWIN应用程序访问令牌,端口。

更新:调试System.Web.Http

我从ASP.NET Web Stack GitHub repository下载了System.Web.Http源代码,我也编译了它,并且已经将已编译的程序集链接到我的 Product API WebAPI项目debug AuthorizeAttribute

已收到整个持有者令牌,但actionContext.ControllerContext.RequestContext.Principalnull。我怀疑某些与OAuth相关的中间件没有解密并将用户分配给整个属性。

重点是 Identity API

检查以下屏幕截图,我可以在其中演示正在接收的持有人令牌:

enter image description here

更新2:Identity API可以使用发出的访问令牌授权请求......

我可以确认访问令牌用于授权对Identity API资源的请求(例如,我实现了UserController以让 Identity API 注册和管理用户,以及大多数控制器操作都标有[Authorize]属性...)。

1 个答案:

答案 0 :(得分:12)

是的,您可以将授权服务器和资源服务器分离。 他们可以生活在不同的应用程序中,不仅如此,它们甚至可以存在于不同的服务器上。

授权服务器将负责向您的客户端应用程序发出访问令牌,并最终管理用户和角色。

资源服务器将托管受保护资源,接受授权服务器发布的访问令牌。

查看您的基础架构,您的 Identity API 将是授权服务器,而 Product API 将是您的资源服务器。

授权服务器需要配置和使用OAuthAuthorizationServerProvider的实现 在你的创业公司,你会做这样的事情:

app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

var OAuthOptions = new OAuthAuthorizationServerOptions
{
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString("/oauth/Token"),
    AccessTokenExpireTimeSpan = TimeSpan.FromHours(8),
    Provider = new MyAuthorizationServerProvider(),
    // RefreshTokenProvider = new MyRefreshTokenProvider(DateTime.UtcNow.AddHours(8))
};

app.UseOAuthAuthorizationServer(OAuthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

正如您所看到的,我已将MyAuthorizationServerProvider用作身份验证的自定义提供程序。

负责验证客户端(ValidateClientAuthentication)并授予访问资源(GrantResourceOwnerCredentials)的权限。

GrantResourceOwnerCredentials将检查客户端的凭据(用户名和密码)是否有效并发布有效令牌:

var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);

AuthenticationTicket收到ClaimsIdentity个对象和AuthenticationProperties的集合。

您通常会在此处添加用户名声明和角色:

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

最终,您可能想要使用其他类型的声明 AuthenticationProperties集合将定义您要传递给客户端的扩展信息:

var props = new AuthenticationProperties(new Dictionary<string, string>
{
    { 
    "name", "John"
    },
    { 
    "surname", "Smith"
    },
    { 
    "age", "40"
    },
    { 
    "gender", "Male"
    }
});

您可以查看此github repo以查看实施情况。

您的资源服务器,负责管理您的业务信息的RESTful API,不必重新实施整个授权/身份验证层。

在您的初创公司(产品API )中,您只需指示api使用和使用承载令牌:

public void Configuration(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();

    OAuthBearerAuthenticationOptions OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
    app.UseOAuthBearerAuthentication(OAuthBearerOptions);

    WebApiConfig.Register(config);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(config);
}

您的受保护资源将是这样的:

[Authorize(Roles = "Users")]
public class ProductsController : ApiController
{
    public Models.Product GetProduct(string id)
    {
        var identity = User.Identity as ClaimsIdentity;

        return new Models.Product();
    }
}

正如您所看到的,我使用了Authorize属性,因为我只想授权某种类型的用户。

注意:

如果您要将授权服务器资源服务器托管到不同的计算机上,您必须确保共享相同的{{1在服务器或资源服务器上无法解密授权服务器发布的持有者令牌:

machineKey

我建议你阅读这个article以找到关于所涉及的所有部分的非常好的解释。

Taisser也是另一个article,他使用Json Web Tokens完成相同的过程,以达到相同的效果。