使用OWIN标识从多个API客户端注册Web API 2外部登录

jos*_*ley 75 asp.net-mvc oauth-2.0 owin asp.net-identity asp.net-web-api2

我想要以下架构(我已经为这个例子编写了产品名称):

在一台服务器 http://api.prettypictures.com 上运行的Web API 2应用程序

MVC 5客户端应用程序在另一台服务器上运行 http://www.webpics.com

我希望www.webpics.com客户端应用程序使用Pretty Pictures API:

  • 使用用户名和密码注册新帐户
  • 在Facebook/Google/Twitter/Microsoft注册新帐户
  • 登录
  • 检索图片

所有上述工作除了在Facebook,Google等注册外部账户外.

我无法确定从API的单独客户端用户创建外部帐户的正确流程.

我已经研究了认证流程中可用的大多数文档,如下所示: 在此输入图像描述

我已经在OWIN的新身份模型上阅读了我所能做的一切.

我已经在Visual Studio 2013中检查了SPA模板.它演示了如何完成我需要的大部分工作,但仅限于客户端和API在同一主机上时; 如果我希望多个客户端访问我的API并且能够让用户通过Google等注册,那么它就无法正常工作,而且我可以告诉OWIN身份验证流程中断.

到目前为止流程如下:

  • 用户浏览www.webpics.com/Login
  • www.webpics.com调用api.prettypictures.com/Account/ExternalLogins(用RETURNURL设置回去在回调www.webpics.com),并显示最终链接到用户
  • 用户点击"Google"
  • 浏览器使用提供者的名称重定向到api.prettypictures.com/Account/ExternalLogin等.
  • API的ExternalLogin操作实例化对google.com的挑战
  • 浏览器被重定向到google.com
  • 用户输入用户名和密码(如果他们尚未登录google.com)
  • google.com现在提供安全许可:"api.prettypictures.com"想要访问您的电子邮件地址,姓名,妻子,孩子等.这样可以吗?
  • 用户点击"是"并使用Google设置的Cookie将其带回api.prettypictures.com/Account/ExternalLogin.

这是我被卡住的地方.接下来应该发生的是以某种方式通知客户端应用程序用户已成功通过google.com进行身份验证,并获得一次性访问代码以便稍后交换访问令牌.如有必要,客户端应用程序应该有机会提示用户输入与google.com登录相关联的用户名.

我不知道如何促进这一点.

实际上,此时浏览器在谷歌回调后最终坐在api.prettypictures.com/Account/ExternalLogin端点上.该API已登录Google,但客户端不知道如何处理该问题.我应该将该饼干送回www.webpics.com吗?

在SPA应用程序中,它通过AJAX完成,google.com将返回一个令牌作为URL片段,它一切运行良好,因为它都在一个域上.但这远远超过了拥有多个客户可以充分利用的"API"的重要性.

救命!

Kév*_*let 46

更新:自从我在1月份写这篇文章以来,情况发生了变化:MSFT发布了他们的官方OpenID连接客户端中间件,我与@manfredsteyer一起努力使Katana内置的OAuth2授权服务器适应OpenID连接.这种组合可以提供更简单,功能更强大的解决方案,不需要任何自定义客户端代码,并且与标准OAuth2/OpenID连接客户端100%兼容.我在1月提到的不同步骤现在可以用几行代替:

服务器:

app.UseOpenIdConnectServer(options =>
{
    options.TokenEndpointPath = new PathString("/connect/token");
    options.SigningCredentials.AddCertificate(certificate);

    options.Provider = new CustomOpenIdConnectServerProvider();
});
Run Code Online (Sandbox Code Playgroud)

客户:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "http://localhost:55985/",

    ClientId = "myClient",
    ClientSecret = "secret_secret_secret",
    RedirectUri = "http://localhost:56854/oidc"
});
Run Code Online (Sandbox Code Playgroud)

您可以在GitHub存储库中找到所有详细信息(和不同的示例):

https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server

https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/dev/samples/Nancy


Josh,你肯定是在正确的轨道上,你的委托/联合身份验证实现似乎相当不错(我想你已经使用了预定义的OWIN中间件Microsoft.Owin.Security.Facebook/Google/Twitter).

您需要做的是创建自己的自定义OAuth2授权服务器.你有很多选择来实现这一目标,但最简单的方法就是插入OAuthAuthorizationServerMiddleware你的OWIN Startup类.你会在Microsoft.Owin.Security.OAuthNuget包中找到它.

虽然最好的做法是创建一个单独的项目(通常称为"AuthorizationServer"),但我个人更喜欢将它添加到我的"API项目"中,而不是要在多个API中使用它(在这里,你必须插入它)在托管"api.prettypictures.com"的项目中.

您将在Katana存储库中找到一个很好的示例:

https://katanaproject.codeplex.com/SourceControl/latest#tests/Katana.Sandbox.WebServer/Startup.cs

app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
    AuthorizeEndpointPath = new PathString("/oauth2/authorize"),
    TokenEndpointPath = new PathString("/oauth2/token"),
    ApplicationCanDisplayErrors = true,

    AllowInsecureHttp = true,

    Provider = new OAuthAuthorizationServerProvider
    {
        OnValidateClientRedirectUri = ValidateClientRedirectUri,
        OnValidateClientAuthentication = ValidateClientAuthentication,
        OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
    },
    AuthorizationCodeProvider = new AuthenticationTokenProvider
    {
        OnCreate = CreateAuthenticationCode,
        OnReceive = ReceiveAuthenticationCode,
    },
    RefreshTokenProvider = new AuthenticationTokenProvider
    {
        OnCreate = CreateRefreshToken,
        OnReceive = ReceiveRefreshToken,
    }
});
Run Code Online (Sandbox Code Playgroud)

不要犹豫,浏览整个项目,看看如何使用简单的Razor文件实现授权许可表.如果你喜欢像ASP.NET MVC或NancyFX更高层次的框架,创建自己的AuthorizationController控制器和Authorize方法(确保接受GET和POST),并使用属性路由来匹配您的OAuth2授权服务器定义的AuthorizeEndpointPath(即[Route("oauth2/authorize")]在我的示例,我已将其更改AuthorizeEndpointPathoauth2/用作路径库).

您需要做的另一件事是在您的Web应用程序中添加OAuth2授权客户端.不幸的是,Katana中没有通用的OAuth2客户端支持,你必须自己构建.我个人向​​Katana团队提交了一份提案,但遭到拒绝.但不要惊慌,这很容易做到:

从位于那里的Microsoft.Owin.Security.Google存储库中复制相应的文件:https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs

你需要GoogleOAuth2AuthenticationHandler,GoogleOAuth2AuthenticationMiddleware,GoogleOAuth2AuthenticationOptions,GoogleAuthenticationExtensions(你就必须删除对应谷歌的OpenID执行第2种方法)IGoogleOAuth2AuthenticationProvider,GoogleOAuth2ReturnEndpointContext,GoogleOAuth2AuthenticationProvider,GoogleOAuth2AuthenticatedContextGoogleOAuth2ApplyRedirectContext.在托管"webpics.com"的项目中插入这些文件后,请相应地重命名这些文件并更改授权和访问令牌端点URL,GoogleOAuth2AuthenticationHandler以匹配您在OAuth2授权服务器中定义的URL .

然后,将重命名的/ custom中的Use方法添加GoogleAuthenticationExtensions到OWIN Startup类.我建议AuthenticationMode.Active您使用,以便将您的用户直接重定向到您的API OAuth2授权终结点.因此,您应该禁止"api.prettypictures.com/Account/ExternalLogins"往返,并让OAuth2客户端中间件更改401响应以将客户端重定向到您的API.

祝好运.如果您需要更多信息,请不要犹豫;)