使用 OAuth and/or OpenID 开发 RESTful API

Developing a RESTful API with OAuth and/or OpenID

我正在努力思考如何使用多个外部令牌提供商实施 OAuth 或 OpenID。从我的角度来看,像 google 这样的提供者将两种规范混合在一个 api 中,我在保护资源和处理用户数据的方式上区分了这两种机制。 OpenID 仅用于身份验证,我自己生成 access_tokens 并自己保存所有用户数据,而另一方面 OAuth 提供外部 access_tokens 并管理用户数据。

涉及的实体:

  1. 外部提供商 - 这是我对 OAuth/OpenID 提供商的称呼,例如 Google OAuth
  2. 后端 - 主要用作客户端RESTful API的服务器
  3. 客户端 - 需要访问后端提供的资源的应用程序(例如 SPA、IOS 应用程序、桌面客户端)

我正在为包括网络在内的几种不同类型的客户端开发一个快速后端(rest api),ios/android。根据我的理解,我有以下选项:(指的是我想使用的提供商的大多数实现文档,而不是规范)

选项 1 - OpenID

  1. 客户通过与任何外部提供商(Apple、Google、Facebook)登录获得 auth_code
  2. 客户端将此 auth_code 发送到我的后端,此代码用于发出 id_token
  3. 后端使用此 id_token 对用户进行身份验证并存储有关用户的任何必需信息
  4. 后端生成一个 access/refresh 令牌用于授权并将其发送回客户端
  5. 现在我可以使用我的 access_token 进行授权,使用刷新令牌 auth-state-management(注销,使令牌无效)

问题 - 真的有问题吗?

选项 2 - OAuth

  1. 客户通过与任何外部提供商(SiwA(ios)、Google、Facebook)登录获得auth_code
  2. 客户端将此 auth_code 发送到我的后端,此代码用于从提供商
  3. 发出 access_token/refresh_token
  4. 后端发回从外部提供者
  5. 获得的access_token/refresh_token
  6. 现在每次客户端发出请求时,它都必须包含外部 access_token,然后在后端使用它来询问外部提供者此令牌是否有效以及客户端是否可以访问资源。换句话说,我使用外部 access_token 进行授权
  7. 每当后端需要用户数据(例如电子邮件、地址...)时,有必要通过提供客户提供的 access_token 向外部提供商请求此数据

Problems/Questions:

有什么我遗漏的吗?在我看来,选项 2 向身份验证提供者引入了很多不必要的通信,而 选项 1 确实忽略了可能需要的任何通信(例如身份状态的同步)? 我的主要问题是,考虑到 Option 1 这似乎更适合我的场景,我是否必须对用户状态的任何状态变化做出反应,比如外部电子邮件的变化提供者或忽略任何东西是否有任何缺点允许身份验证的外部用户 ID。

我最终实现了 OpenID,意识到我只需要身份验证,不需要授权,也不需要用户数据的严格耦合。在提出问题时,我意识到了差异,但是我没有深入研究我的项目的要求。因此我放弃了基本的 OAuth 协议,因为我不需要对外部资源的任何授权。

关于 OpenID,来自 OpenID 提供商的外部身份管理不在协议范围内,必须独立完成。还有其他协议和方法可以解决这个问题,例如SCIM.

我最终依靠 id_token 提供的外部 ID 是唯一的这一事实,并在第一次验证(基本上是注册)时初始化一次性映射。从这一刻起,我的服务器将管理用户数据。随后的身份验证请求依赖于此映射永远不会更改的事实,并且任何用户数据可能与保存在提供者处的任何数据不同,例如与外部身份的 google 邮件相比,我服务器上的不同邮件地址。不过这并不违反我的要求。

此外,我想补充一点,我最终支持隐式流和授权码流,这意味着客户端可以直接发送 id_token,而不是发送 auth_code。我没有完全理解为什么这更不安全,因为从我目前的角度来看,我的服务器要求提供者验证 id_token,它通过提供错误的 id_tokens 来防止任何恶意意图。