从身份服务器登录页面启动授权代码流的正确方法是什么?

What is the right way to start Authorization Code Flow from identity server login page?

我正在尝试使用 ASP.NET Core 和 IdentityServer4 为 SPA React 客户端实施授权代码流。

有两种情况:

1) 用户打开 SPA 应用程序,我们检查他是否有访问令牌,如果没有我们生成 url 就像

/connect/authorize?
client_id=*client_id*&
redirect_uri=*redirect_uri*&
response_type=code&
response_mode=fragment&
state=*some_state*&
nonce=*some_nonce*&
code_challenge=*code_challenge*&
code_challenge_method=S256&
scope=openid profile email

授权代码流程开始。这工作非常清楚,在所有往返行程之后,用户使用代码返回 SPA 应用程序,然后发送令牌请求(包括代码和 code_verifier),然后接收它并愉快地继续使用我们的伟大应用程序。

2) 用户直接打开登录页面,这就是我卡住的地方。 IdentityServer 上下文对这个用户、代码挑战等一无所知,因为我们没有像正常流程那样在进入此页面之前向 /connect/authorize 发出请求。下一步是什么?

我可以直接在登录页面生成 /connect/authorize link 并做丑陋的重定向到它然后返回登录页面(我不想老实说),但是我的 SPA app 会知道我在这里生成什么 code_verifier 吗?当然我可以将它存储在一些共享的跨域 cookie 中,但我相信这里应该有更好的方法。

我可以将用户从登录页面重定向到我的应用程序的另一种解决方案,它识别出用户未经授权,我们开始场景 #1。我认为也不是我的方法。

如果用户直接打开我的身份服务器页面,我该怎么办? 是否可以使用授权代码流程,或者我应该考虑将其他一些流程与此流程结合使用?

由于 OAuth 2.0 规范的新建议,我不想使用隐式流。

这个问题的答案非常简单 - 在您的第二种情况下 - 如果您的用户直接打开 IDP 登录页面,他们不想转到您的应用程序。如果您为您的 SPA 使用 Google 或 Facebook 或其他已知的 IDP 之一,并且作为用户,我只是转到他们的登录页面,这也是一样的。他们不可能知道我是否打算登录,以便稍后将我重定向到您的 SPA。

现在说了这么多 - 您可以做些什么来使这项工作有点无缝 - 是在用户通过 Identity Server 4 登录后重定向到 SPA 的受保护页面(这很简单,因为您拥有登录页面并且那里这里不涉及 OAuth)。然后将触发您的 SPA 以启动 OAuth2 流程并将重定向回 Identity Server 4。用户已经在几秒钟前在这里登录,因此将跳过登录过程并且将向用户显示同意页面或者如果您的客户端配置为跳过同意页面 - 用户将使用通常的令牌等重定向回您的 SPA。

因此将其分解为流程:

User Accesses IDS4 Login Page -> User Enters Credentials -> IDS4 Authenticates User and Redirects to your SPA protected page -> Your SPA initiates OAuth2 flow and redirects back to IDS4 -> IDS4 displays consent page -> IDS4 issues auth code back to your SPA.

这里当然有额外的步骤,您的 SPA 将交换授权代码以获取访问令牌,但为了清楚起见,我省略了它,因为它与问题无关。