【发布时间】:2021-01-22 07:52:39
【问题描述】:
我正在努力解决使用多个外部令牌提供程序实现 OAuth 或 OpenID 的问题。因为从我的角度来看,像谷歌这样的提供者在一个 API 中混合了这两种规范,我在保护我的资源和处理用户数据的方式上区分这两种机制。 OpenID 仅用于身份验证,我自己生成 access_tokens 并自己保存所有用户数据,而另一方面 OAuth 提供外部 access_tokens 并管理用户数据。
涉及的实体:
- 外部提供者 - 这是我对 OAuth/OpenID 提供者(如 Google OAuth)的称呼
- 后端 - 主要用作客户端的 RESTful API 的服务器
- 客户端 - 需要访问后端提供的资源的应用程序(例如 SPA、IOS 应用程序、桌面客户端)
我正在为几种不同类型的客户端(包括 web、ios/android)开发一个快速后端(rest api)。据我了解,我有以下选择:(参考我想使用的提供者的大多数实现文档而不是规范)
选项 1 - OpenID
- 客户端通过登录任何外部提供商(Apple、Google、Facebook)来获取 auth_code
- 客户端将此 auth_code 发送到我的后端,此代码用于发出 id_token
- 后端使用此 id_token 对用户进行身份验证并存储有关用户的任何所需信息
- 后端为授权生成访问/刷新令牌并将其发送回客户端
- 现在我可以使用我的 access_token 进行授权,使用刷新令牌进行身份验证状态管理(注销、无效令牌)
问题 - 真的有问题吗?
- 我不确定是否需要经常检查用户是否仍然是有效身份。对于有效身份,我的意思是外部身份(例如谷歌用户)是否仍然存在,这基本上与我的持久层是否必须使该用户无效(删除)有关。换句话说,我是否必须将我的持久层与外部提供者同步以避免死/不可用的身份。如果电子邮件地址等信息发生更改而我的后端没有收到相关通知,这尤其会成为一个问题。或者我应该接受这样一个事实,即我的后端用户只是通过 id 与外部用户相关,而客户端必须自己管理我后端中的数据(例如,在客户端更改他们的电子邮件)。这意味着我最好忽略对外部用户数据的任何更改(在提供商处)。
选项 2 - OAuth
- 客户端通过使用任何外部提供商(SiwA (ios)、Google、Facebook)登录来获取 auth_code
- 客户端将此 auth_code 发送到我的后端,该代码用于从提供者发出 access_token/refresh_token
- 后端发回从外部提供者获取的access_token/refresh_token
- 现在,每次客户端发出请求时,它都必须包含外部 access_token,然后在后端使用它来询问外部提供者此令牌是否有效以及客户端是否可以访问资源。换句话说,我使用外部 access_token 进行授权
- 每次后端需要用户数据(例如电子邮件、地址...)时,都需要通过提供客户端提供的 access_token 向外部提供商询问此数据
问题/疑问:
- 我假设刷新过程必须在客户端执行,以防万一令牌过期,后端从提供商处重定向未授权。对吗?
- 如何确定令牌来自哪个提供商。对我来说,实施试错过程并询问每个提供者这是否是有效令牌似乎很奇怪。例如。如果后端在请求的标头中收到访问令牌,则它不知道要询问哪个提供者。 (或者我应该在
Bearer Provider Token这样的标头中编码这些信息,以便知道在哪里检查访问令牌。 - 使用 选项 2,只要外部提供商遇到停机时间,任何用户都无法使用我的后端,而使用 选项 1 只能登录(初始登录或显式后注销,这会使刷新令牌无效)不适用于此特定提供商。
我有什么遗漏吗?在我看来,选项 2 向身份验证提供者引入了许多不必要的通信,而 选项 1 确实忽略了任何可能需要的通信(例如身份状态的同步) ? 对我来说主要问题是,考虑到 Option 1 似乎更适合我的场景,我是否必须对用户状态的任何状态变化做出反应,例如外部提供商的电子邮件更改或忽略外部用户 ID 以进行身份验证有任何缺点。
【问题讨论】:
标签: authentication oauth-2.0 oauth authorization openid