管理使用 OAuth2 进行身份验证的用户

问题描述 投票:0回答:1
我正在按照

本教程学习在我的 Spring Boot 应用程序中使用 OAuth2。为了管理经过身份验证的用户,我从一个简单的解决方案开始,该解决方案使用 principal.getName()

 作为用户的唯一 ID 将其存储在 MongoDB 中。

@GetMapping("/user") public ResponseEntity<UserDTO> user (@AuthenticationPrincipal OAuth2User principal) { User user = userService.findOrCreateUser (principal); //... }

public User findOrCreateUser (OAuth2User principal) { String id = principal.getName (); //... }
这非常有效 - 当用户通过 Github 进行身份验证时,

principal

 对象的 
getName()
 值与用户通过 Google 进行身份验证时不同。在这两种情况下,当用户注销并再次登录时,
principal
对象具有一致的
getName()
值。我的问题是 OAuth2 是否保证 
getName()
 在所有可能的 OAuth2 身份验证提供商中具有唯一值。我找不到任何有关此的信息。如果不是,唯一标识用户的正确方法是什么?

在提出上述解决方案之前,我尝试实现“正确”的方式,但在“如何添加本地用户数据库”部分中,

教程相当模糊:

实现并公开 OAuth2UserService 以调用授权服务器以及您的数据库。您的实现可以委托给默认实现,这将完成调用授权服务器的繁重工作。您的实现应该返回扩展您的自定义 User 对象并实现 OAuth2User 的内容。

我尝试了下面的解决方案,将

OAuth2User

 对象与每个用户一起存储。然而,当从 MongoDB 读取 
User
 对象时,会出现异常,因为找不到合适的构造函数(尽管构造函数具有该类的所有字段的参数)。

public class User implements OAuth2User { private final String id; private final OAuth2User principal;
感谢任何帮助,包括指向进一步文档的指示。

java spring-boot spring-security oauth-2.0 spring-security-oauth2
1个回答
0
投票
所有 OAuth 提供商均不保证

principal.getName()

 的唯一性。

为了确保唯一性,您可以执行类似于 Auth0 在跨多个提供商联合用户时所做的操作。您可以将 ID 构造为

${provider_name)|${sub}

 因此,如果用户通过 Google 登录,他们的 ID 将类似于 
google|123456789012345678901

这保证了唯一性,因为

sub

 声明是标准(注册)声明,保证在每个提供商内是唯一标识符。此外,
sub
声明保证存在于任何 OIDC 
id_token
中,这与其他声明(例如 
name
)不同,后者可能存在也可能不存在。

© www.soinside.com 2019 - 2024. All rights reserved.