Oauth 2.0 我是否应该将用于访问令牌交换的身份验证代码移动到Web API/SPA OpenID Connect实现的API?

Oauth 2.0 我是否应该将用于访问令牌交换的身份验证代码移动到Web API/SPA OpenID Connect实现的API?,oauth-2.0,identityserver4,openid-connect,Oauth 2.0,Identityserver4,Openid Connect,我正在尝试为SSO身份验证设置一个OpenID连接服务器。我认为我的基本设置/要求是相当标准的,但我在把它们放在一起有点困难 广泛的设置是一个单页应用程序、一个web API和一个身份服务器。SPA由与web API相同的域名提供,ID服务器位于不同的域上,因此我可能有几个SPA/web API组合,但当然每种情况都是相同的设置(具有静态内容和API的单个主机)。目前,我正在使用创建identity server;我可以灵活地尝试其他供应商,如果有某种问题的一个,但到目前为止还不错 我认为我的登

我正在尝试为SSO身份验证设置一个OpenID连接服务器。我认为我的基本设置/要求是相当标准的,但我在把它们放在一起有点困难

广泛的设置是一个单页应用程序、一个web API和一个身份服务器。SPA由与web API相同的域名提供,ID服务器位于不同的域上,因此我可能有几个SPA/web API组合,但当然每种情况都是相同的设置(具有静态内容和API的单个主机)。目前,我正在使用创建identity server;我可以灵活地尝试其他供应商,如果有某种问题的一个,但到目前为止还不错

我认为我的登录要求也是相当标准的;我想要短期访问令牌,我还想要使用刷新令牌来实现滑动过期,这样用户就不必被重定向出我的SPA,直到他们“一段时间”不活动为止(不过我最终定义了这一点)

经过一点研究,我想我想要的是使用授权代码流。所以一般来说,我认为这样做的方式是:

  • 用户访问应用程序主机(为web API和SPA提供服务);提供静态水疗服务
  • SPA加载并确定本地存储中没有访问令牌。SPA通过生成一个随机标识符并将其存储在会话存储中来启动登录过程,然后将浏览器导航到ID服务器主机
  • 用户使用ID服务器主机进行身份验证
  • ID服务器主机重定向到客户端,并在重定向中包含最初生成的SPA随机标识符以及授权码
  • 在加载并检测到它获得了访问代码后,SPA检查会话存储中存储在步骤2中的标识符。找到它,SPA调用web API来交换访问令牌的授权代码
  • web API使用ID服务器的反向通道来生成访问令牌和刷新令牌
  • web API存储刷新令牌和访问令牌,然后向客户端发出访问令牌
  • 在将来的所有请求中,客户端将访问令牌与Web API一起使用。当SPA确定它的访问令牌已经过期或即将过期时,它会以某种方式请求刷新(现在我将手动波动刷新)
  • 所以我经历了一段时间,令我惊讶的是,我最终处于一种不同的状态。我花了一段时间来解决这个问题;如果有人想跟随我,我要说的步骤是“添加一个JavaScript客户机”,但我愿意承认,结果在实现OpenID Connect的人中很常见。结果流与我从步骤5开始所期望的不同;SPA不使用授权码调用web API并请求访问令牌,而是使用CORS并向ID服务器发出跨域请求以请求访问令牌。本教程并没有太多地介绍刷新令牌(文档的其他部分也有介绍,但只是简单介绍),但我认为这意味着,如果我想使用刷新令牌,它们将被分发给客户机,它将使用本地存储来存储它们;然后,对于将来的刷新,它还会向ID服务器发出跨域请求。顺便说一句,另一点令人惊讶的是,本教程让您使用PKCE,在研究中,对于web应用程序来说,PKCE似乎是不必要的;这有点重要,因为在客户端包含SHA-2实现会使我的应用程序的大小增加很多

    我认为向web客户端发出刷新令牌并要求其存储是一种不好的做法;我对打开的特定漏洞有点模糊,但一般的想法是,如果有人以某种方式破坏了您的客户机,刷新令牌比短期访问令牌功能强大得多

    因此,我想,我最初认为这是可行的,我认为web API是OAuth 2术语中的“依赖方”,教程将其设置为客户机是“依赖方”。这让我想到,如果我想获得一个滑动到期,我必须越过教程的内容,将令牌交换功能从客户端移动到web API中,就像我最初设想的那样。它最终看起来有点像web API,在功能上是SPA的代理,用于将授权代码交换为访问令牌

    最终,我的问题是:我做对了吗?看起来有两种不同的模型用于实现SPA/API web应用程序的OpenID连接;一个API是RP,另一个SPA是RP。如果你想使用刷新令牌,我认为你应该选择选项1,但是如果你关心API可以模拟客户端,你会选择选项2吗?这对我来说似乎仍然无关紧要;授权代码/访问令牌交换只能用于特定的应用程序,因此一个API不会突然在该设置中作为不同的后端进行身份验证。我只是担心自己去改变教程的结构设置,因为这与安全有关

    更新

    尽管得到了公认的答案,但我还是使用了授权代码流而不是隐式流,因为这是IETF的最新建议(参见,和一篇很棒的文章)。我接受了这个答案,因为通过iframe使用静默刷新而不是刷新令牌似乎是我尝试做的最标准的方法;使用它,我能够构建一个类似于教程的工作系统。事实上,它推荐的客户机库()有一个内置函数来处理细节。为了完整起见,我首先要做的是这项服务:

    导入oidc f