通过第三方服务授权后,如何使用 OAuth 2.0 保持会话? [关闭]

Posted

技术标签:

【中文标题】通过第三方服务授权后,如何使用 OAuth 2.0 保持会话? [关闭]【英文标题】:How do I persist a session using OAuth 2.0 after authorization through a third party service? [closed] 【发布时间】:2016-04-16 10:25:20 【问题描述】:

我正在为我正在开发的应用程序实施基于 OAuth 2 的授权模型。我为最终用户提供了使用 Facebook 登录或使用我的 API 设置电子邮件/密码帐户的能力。使用密码授权可以直接进行电子邮件/密码身份验证。我正在寻求有关 Facebook 登录流程的帮助。

我的应用程序是一个使用 JSON API(我的“资源服务器”)的单页应用程序。我正在使用 Facebook javascript SDK 授权网络应用访问最终用户的电子邮件地址。

当用户尝试使用 Facebook 登录时,整个过程发生在 Facebook 和 Web 应用程序之间。因此,我的 API 在使用 Facebook 的 OAuth 服务器验证令牌之前无法信任 Facebook 授权令牌。

截至目前,我将 Facebook accessToken 传递给我的 API,然后 API 通过“me”图形 API 的服务器到服务器调用验证用户对 Facebook 的授权。这是我当前设置的示意图:

所以,此时,我有一个 Facebook 访问令牌和一个电子邮件地址。我需要在我的 API 服务器和 Web 应用程序之间保持我的会话。此时保持会话的标准方法是什么?

通过阅读 OAuth 文档,似乎这种情况需要在我的 API 服务器和 Web 应用程序之间进行“隐式授权”,但这种授权类型在 OAuth package I'm using 中不可用。也是包says implicit grants are "very insecure"的作者。

我的另一个想法是我可以创建一个随机的客户端 ID 和客户端密码,然后将它们传递回 Web 应用程序,以便它可以通过凭据授予请求访问令牌。这对我来说似乎不合逻辑。为什么我不直接创建一个访问令牌并将其发送回客户端直接使用?

在获得 Facebook 的初始授权后,我应该直接在我的 Web 应用程序和 API 服务器之间维护身份验证,对吗?

我意识到我可以生成一个随机密码并向用户发送一个 HTTP Basic 令牌,但我更喜欢使用 OAuth,除非没有任何好处。

【问题讨论】:

【参考方案1】:

我们所做的正是您在 DynamicApis.com 上所说的。

这是我们正在做的事情:

1) 提示用户登录。在我们的例子中,我们自己编写 oAuth2 访问令牌,或者我们可以将您代理到 facebook、github 等……但最终驱动会话的 oAuth2 令牌因为 DynamicApis 归我们所有。但如果工作流程的其余部分完全由 GitHub 之类的第三方编写。

2) 用户使用电子邮件/密码登录。

3) 使用授权码将用户重定向到 DynamicApis.com

4) DynamicApis.com 交换访问令牌的授权代码(服务器到服务器调用)。 此时我刚刚解释了 oAuth2 流程

5)此时我们(假设加密)代表该用户返回和发布的访问令牌,并将其用作会话提供者的密钥(假设基于 Sql Server)。此会话提供程序归 DynamicApis.com 所有。

6) 现在您的会话提供程序可以正常工作了。您有一个代表登录用户的密钥(散列/加密的访问令牌)以及与该密钥关联的多个密钥/值。

您的会话提供者将代表用户将数据的会话状态(键值对)保存在数据库或您使用的任何东西中

会话提供程序的到期日期应等于访问令牌的到期日期(或小于访问令牌的日期)。

当用户注销时会话被销毁。

会话密钥应该以加密形式存在于 cookie、url 中或隐藏在页面上(就像今天保留会话密钥一样)

7) 噗。您有一个已登录用户的会话。

如果您愿意,您实际上可以重用大部分内置的 ASP.NET 会话提供程序逻辑。或者,您可以像 DynamicApis.com 一样构建自己的本地系统。

【讨论】:

这个答案看起来不仅仅是一个广告,而不是问题的解决方案。 不,不是。这就是我在今天正在运行的平台上做这件事的方式。提出问题的人以及正确回答问题的人都可以看到和使用它。【参考方案2】:

如果可以,您可以在 oauth 实现中编写自己的自定义授权类和身份验证提供程序。

为这种身份验证定义一个新的客户端 ID。

    用户通过 Facebook 进行身份验证。

    Facebook 为客户端生成令牌。

    客户端向您的后端发送请求 具有此访问令牌、电子邮件地址和身份验证的应用程序 类型/客户 ID(比如说“facebook”)

    您的自定义授权决定 将使用哪种令牌。您可以控制客户端 id/认证类型(上)。 如果身份验证类型是“facebook”,您 如果它不在这里你会询问会话存储的访问令牌 将询问 Facebook api,然后如果没问题,将其保存在您的 会话存储(数据库,redis 其他)。我们放入了一个会话存储而不是 每次都问fb。(这是非常基本的概念) 然后oauth将 使用您的配置返回令牌。 您的客户端将为具有客户端 ID/身份验证类型的下一个请求发送令牌。凭据将是 facebook 令牌,电子邮件将是用户名。

自定义授权决定令牌类型(Spring security-oauth 实现)

    String clientId = tokenRequest.getClientId();
    ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
    Map<String, String> parameters = tokenRequest.getRequestParameters();
    String username = parameters.get("username"); //username is email
    String password = parameters.get("password"); //password is fb access token
    Authentication authentication = null;
    if ("facebook".equals(clientId)) 
        authentication = new FacebookAuthenticationToken(username, password);
     else 
        authentication = new UserAuthenticationToken(username, password);
    
    authentication = authenticationManager.authenticate(authentication);

身份验证提供程序检查 facebook 令牌并对其进行验证。

public class FacebookAuthenticationProvider implements AuthenticationProvider 

@Autowired
private FacebookApi facebookApi;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException 
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();
    // you can check your facebook session store
    boolean valid = facebookApi.isValidToken(username, password);

    if (!valid) 
        throw new BadCredentialsException("Username not found.");
    

    Collection<? extends GrantedAuthority> authorities = user.getAuthorities();

    return new FacebookAuthenticationToken(user, password, authorities);


@Override
public boolean supports(Class<?> authentication) 
    return FacebookAuthenticationToken.class.isAssignableFrom(authentication);


我把代码作为示例。

我通常会强制用户在第一次登录 Facebook(获取他们的电子邮件)后为我的内部应用设置密码。然后一切都变得简单多了。你可以明白我的意思。

【讨论】:

以上是关于通过第三方服务授权后,如何使用 OAuth 2.0 保持会话? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

OAuth 2.0

OAuth 2.0 的四种授权模式

OAuth 2.0

OAuth 2.0 授权认证详解

OAUTH 2.0的应用

基于oauth 2.0 开发第三方开放平台