我想通过Google、Facebook或Apple等允许SSO(单点登录)。同时在我的移动的应用程序项目的数据库(Spring JPA)中有我自己的用户实体。我的用户实体将保存一般信息(即电子邮件、第一个/最后一个等)沿着应用程序相关信息(即组、权限等)。
移动的应用程序前端是React Native,后端是Spring应用程序(仅后端),它包含REST API。
它看起来像我将首先允许SSO为谷歌,Facebook等。通过移动的应用程序前端上的OAuth2客户端。OAuth2登录的结果(一个JWT令牌)将被发送到后端(我的Spring应用程序),在那里我将验证令牌并对用户进行身份验证(即,创建新用户或更新现有用户)和授权请求。
这看起来是可行的,但我遇到了一些问题/问题,实际上完成这一点:
1.如何通过JWT正确验证用户?JWT有一个身份令牌(其中包括我需要的凭证,即“email”、“first/last”等)和访问令牌。我只需要身份令牌,还是同时需要身份令牌和访问令牌?
1.在通过Spring Security验证和认证用户后,我会返回什么?我自己的JWT,还是用户发送的JWT(Google/FB/等)?
1.这是无密码登录,所以我不仅需要我自己的AuthenticationProvider和UserDetailsService,还需要一个自定义Spring Token而不是“UsernamePasswordAuthenticationToken”吗?
我已经研究了Spring Security的身份验证过程和许多示例,但它们并不特定于我试图实现的目标。我在这里和其他网站上看到了一些关于它的其他问题,但没有提供明确的例子。
如果有人能给我指出正确的方向,那就太好了。谢谢.
1条答案
按热度按时间dxpyg8gm1#
实际上应该可以让一个移动的应用程序查询配置为OAuth2客户端的后端(不管是否是Spring)。
需要事先了解的一件重要事情是,对OAuth2客户端的请求是通过会话授权的,而不是令牌(无论是否是JWT)。这样的后端是有状态的,容易受到CSRF攻击。您必须配置您的后端以公开CSRF cookie,并在移动的应用程序中手动提取其值,以将其设置为每个
POST
、PUT
和DELETE
请求的标头(通常为X-XSRF-TOKEN
)。Web应用程序中的authorization_code流示例(如您已开始工作)
1.用户被重定向到负责发起流的客户端上的URI。假设
https://bff.demo.c4-soft.com/oauth2/authorization/keycloak-confidential-user
1.他得到的响应是到授权服务器上的授权端点的重定向。例如:
https://oidc.c4-soft.com/auth/realms/spring-addons/protocol/openid-connect/auth?response_type=code&client_id=spring-addons-bff&scope=openid%20profile%20email%20offline_access%20roles&state=nToh3rnFS-tLVTJ7ajWkq-Fbmi0fUhicoS1nxbdCh8I%3D&redirect_uri=https://bff.demo.c4-soft.com/login/oauth2/code/keycloak-confidential-user&nonce=sNWSLXrLBOfb77jZtImq3k0gV4cg_qKoFLiaEWgbsio
。这个URI后面必须有一个能够显示登录UI(登录名和密码,但也可能是多因素身份验证令牌等)的用户代理。1.使用作为查询参数传递的
redirect_uri
将用户重定向回客户端(如果他没有在授权服务器上为所使用的客户端ID和用户代理打开会话,则在具有输入凭证之后)。比如https://bff.demo.c4-soft.com/login/oauth2/code/keycloak-confidential-user?state=ZmaSZzNr5WQ8BjyOAMHtnC8SMty1kEMHuQSCLJO4NEE%3D&session_state=1ec90be5-1388-44ac-8b6c-39910558c037&code=c067d4d5-c3eb-4277-9776-9b5c2509b52a.1ec90be5-1388-44ac-8b6c-39910558c037.fb507d1e-2f06-425c-8885-5f232dc02b4e
1.客户端调用授权服务器端点以交换令牌的授权代码(直接地,这不经过用户设备,并且应该需要客户端ID和客户端秘密两者),并且将其存储在会话中。
原生应用有什么变化?
如果您使用系统浏览器(或Web视图)将用户重定向到授权服务器授权端点,并让授权代码流正常结束,则后端上的用户身份将绑定到此用户代理的会话,而不是应用中的REST客户端,并且来自应用的REST请求将保持未经授权。
我刚才想到的选项是在步骤2修改请求。将
redirect_uri
替换为指向您的应用程序的深层链接。当使用授权代码从授权服务器返回应用时,提取参数,并按照修改前的重定向操作,但使用本机应用REST客户端(而不是系统浏览器或webview)。然后,让流程正常结束。这应该足以将令牌绑定到您的本地应用REST客户端会话。为什么你不应该这样做
如上所述,OAuth2客户端是有状态的。这一点很难衡量。而且,一旦你离开单一的应用程序模型(如果你采用多服务架构),你就会遇到问题。
REST API更适合配置为OAuth2资源服务器。
诀窍在于,您列出的一些社会身份提供者提供了“不透明”的访问令牌,而不是JWT,并且在另一个数据中心的授权服务器上进行内省令牌几乎是不可接受的。这就是Google的例子。
根据OpenID规范,只有ID标记必须是JWT。发送ID令牌是安全的,包括向前端发送,但这种安全的原因是它只应该用于读取用户信息,而不是授权请求(访问ID令牌的任何人都可以读取用户信息,但不应该能够代表使用ID令牌的用户做任何事情)。
您列出的每个提供商提供的访问令牌的受众(旨在使用的人)是他们自己的API(Google API的Google访问令牌,Github API的Github访问令牌等)。不是您的REST API。
如果希望令牌查询您自己的资源服务器,则应配置自己的授权服务器。选择一个具有身份联合功能的系统(“使用...登录”)。Keycloak是一个著名的示例,你可以安装在你的桌面和服务器上。Auth0、Okta和Amazon Cognito只是众多云服务中的一小部分。您甚至可以使用
spring-authorization-server
构建自己的。然后,您将此授权服务器用作系统中的唯一引用:资源服务器和OAuth2客户端(配置为“公共”客户端的移动的应用程序或配置为“机密”客户端的BackenfF或F前端)(如对您的问题的评论中所讨论的)。
spring-cloud-gateway
可以配置为带有spring-boot-starter-oauth2-client
和TokenRelay=
滤波器的BFF。这个网关将是有状态的,但它是一个薄层,只负责路由和存储OAuth2令牌。大部分处理将由其背后的无状态资源服务器完成。