使用 OWIN 身份从多个 API 客户端注册 Web API 2 外部登录
Posted
技术标签:
【中文标题】使用 OWIN 身份从多个 API 客户端注册 Web API 2 外部登录【英文标题】:Registering Web API 2 external logins from multiple API clients with OWIN Identity 【发布时间】:2014-02-05 16:56:53 【问题描述】:我想要以下架构(我已经为这个示例编造了产品名称):
在一台服务器上运行的 Web API 2 应用程序 http://api.prettypictures.com
在另一台服务器上运行的 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”想要访问您的电子邮件地址、姓名、妻子、孩子等。可以吗? 用户点击“是”并返回到 api.prettypictures.com/Account/ExternalLogin 并使用 Google 设置的 cookie。这就是我卡住的地方。接下来应该发生的事情是以某种方式通知客户端应用程序,用户已成功通过 google.com 进行身份验证,并获得一次性访问代码,以便稍后交换访问令牌。如有必要,客户端应用程序应有机会提示用户输入用户名,以便与他们的 google.com 登录相关联。
我不知道该怎么做。
事实上,此时浏览器在 Google 回调后最终位于 api.prettypictures.com/Account/ExternalLogin 端点。 API 已为 Google 登录,但客户端不知道如何处理。我应该将该 cookie 传回 www.webpics.com 吗?
在 SPA 应用程序中,它是通过 AJAX 完成的,google.com 将返回一个令牌作为 URL 片段,这一切都很好,因为它都位于一个域上。但这在很大程度上违背了拥有多个客户端可以充分使用的“API”的意义。
救命!
【问题讨论】:
嗨乔希!我目前也在做这件事。我们有一个 Web Api 和一个 html5/angularJS SPA,我们想使用 google/facebook 进行身份验证。您没有博客或 github 存储库,其中包含有关如何解决此问题的演示?会很感兴趣! 嗨阿什坎,很遗憾我没有!您是否在与 Web API 不同的域上运行您的 SPA(如上所述)? 是的,我们正在开发一个 phonegap 应用程序,所以我们有一个 Web API 作为我们的后端和一个纯 html5/angularjs SPA 作为我们在不同域上的前端,这将成为稍后将成为的应用程序从用户手机访问 API。 Josh 或 @AshkanAldini ,你最终解决了这个问题吗?我正在尝试做类似的事情,Pinpoint 的回答很有帮助,但我仍然对实现感到困惑。 【参考方案1】:更新:自从我在一月份写这篇文章后,情况发生了变化:MSFT 发布了他们的官方 OpenID 连接客户端中间件,我与 @manfredsteyer 一起努力使 Katana 中内置的 OAuth2 授权服务器适应 OpenID 连接.这种组合产生了一个更简单、更强大的解决方案,不需要任何自定义客户端代码,并且与标准 OAuth2/OpenID 连接客户端 100% 兼容。我在一月份提到的不同步骤现在可以只用几行代替:
服务器:
app.UseOpenIdConnectServer(options =>
options.TokenEndpointPath = new PathString("/connect/token");
options.SigningCredentials.AddCertificate(certificate);
options.Provider = new CustomOpenIdConnectServerProvider();
);
客户:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
Authority = "http://localhost:55985/",
ClientId = "myClient",
ClientSecret = "secret_secret_secret",
RedirectUri = "http://localhost:56854/oidc"
);
您可以在 GitHub 存储库中找到所有详细信息(以及不同的示例):
https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server
https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/dev/samples/Nancy
Josh,您绝对走在正确的轨道上,并且您的委托/联合身份验证实现看起来相当不错(我想您已经使用了来自Microsoft.Owin.Security.Facebook/Google/Twitter
的预定义 OWIN 中间件)。
您需要做的是创建自己的自定义 OAuth2 授权服务器。您有很多选择来实现这一目标,但最简单的方法可能是将OAuthAuthorizationServerMiddleware
插入您的 OWIN Startup 类。您可以在 Microsoft.Owin.Security.OAuth
Nuget 包中找到它。
虽然最佳做法是创建一个单独的项目(通常称为“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,
);
不要犹豫,浏览整个项目,看看授权同意书是如何使用简单的 Razor 文件实现的。如果您更喜欢 ASP.NET MVC 或 NancyFX 等更高级别的框架,请创建自己的 AuthorizationController
控制器和 Authorize
方法(确保同时接受 GET 和 POST)并使用属性路由来匹配 OAuth2 中定义的 AuthorizeEndpointPath授权服务器(即我的示例中的[Route("oauth2/authorize")]
,我已将AuthorizeEndpointPath
更改为使用oauth2/
作为路径库)。
您需要做的另一件事是在您的 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
(您必须删除与 Google OpenID 实现相对应的前 2 个方法)、IGoogleOAuth2AuthenticationProvider
、GoogleOAuth2ReturnEndpointContext
、@ 987654343@、GoogleOAuth2AuthenticatedContext
和 GoogleOAuth2ApplyRedirectContext
。在托管“webpics.com”的项目中插入这些文件后,相应地重命名它们并更改GoogleOAuth2AuthenticationHandler
中的授权和访问令牌端点 URL 以匹配您在 OAuth2 授权服务器中定义的那些。
然后,将重命名/自定义 GoogleAuthenticationExtensions
中的 Use 方法添加到 OWIN Startup 类。我建议使用AuthenticationMode.Active
,这样您的用户将被直接重定向到您的 API OAuth2 授权端点。因此,您应该禁止“api.prettypictures.com/Account/ExternalLogins”往返并让 OAuth2 客户端中间件更改 401 响应以将客户端重定向到您的 API。
祝你好运。如果您需要更多信息,请不要犹豫;)
【讨论】:
您好,非常感谢您的回答,它几乎为我指明了所有正确的方向,我就快到了。我已经使用您指向的类创建了自己的中间件实现。我坚持的是当我重定向回客户端的原始redirect_uri
,例如http://www.webpic.com/signin-prettypictures
,我在查询字符串中输入了什么以便中间件日志知道该怎么做?
(我尝试将状态作为查询字符串参数放在那里,但中间件似乎只是吞下它并将我重定向到我的客户端主页)
很高兴听到!我不知道你是否已经解决了上一个问题,但我想在传递给 IAuthenticationManager.Challenge 的 AuthenticationProperties 上设置 RedirectUri 可以解决问题;)
@mayabelle:当然,请在此处查看我的答案:***.com/questions/28487586/…
@CularBytes 我会看看你的其他“POST”以上是关于使用 OWIN 身份从多个 API 客户端注册 Web API 2 外部登录的主要内容,如果未能解决你的问题,请参考以下文章
具有混合身份验证 JWT 和 SAML 的 ASP.NET Web API 2.2 OWIN