1. 参考

2. 选型

3. 流程

Relying Party 根据 OpenID Connect Discovery 找到 authorization_endpoint 和 token_endpoint 等。

Web 浏览器通过远程 Relying Party 请求 Resource Server,使用 authorization code flow。

# 1. 通过 Relying Party 请求 Resource Server http://xxx/foo
GET /foo HTTP/1.1

HTTP/1.1 302 Found
Location: http://keycloak/auth/realms/test/protocol/openid-connect/auth?scope=openid&response_type=code&client_id=some-client&redirect_uri=http%3A%2F%2Fxxx%2Fcallback&state=...

# 2. 重定向到 OpenID Provider(Keycloak),显示登录框,然后输入用户名和密码后提交 (标准没有定义这步)
#  session_code 嵌在 HTML form 的 action 属性里。
POST /auth/realms/test/login-actions/authenticate?session_code=4CFTbpoDb-vLjI6MGFqj8YvKdif_tHrO9S5voqKcTMo&execution=326a0f64-2d3d-4a68-8d5d-89fae0eb8e6b&client_id=some-client&tab_id=xzJWmZ5C9ZI HTTP/1.1

username=john&password=johnpwd&credentialId=

HTTP/1.1 302 Found
Location: http://xxx/callback?code=xxxxx&state=...&session_state=yyyy

# 3. 回到 Relying Party 的 redirect_uri,relying party 可以根据 state 参数找到原始的请求地址
GET /callback?code=xxxxx&state=...&session_state=yyyy HTTP/1.1

HTTP/1.1 302 Found
Set-Cookie: JSESSIONID=....; path=/foo
Location: http://xxx/foo

# 4. 回到正常请求 Resource Server http://xxx/foo
GET /foo HTTP/1.1
Cookie: JSESSIONID=...

在上面第 3 步里,Relying Party 请求 OpenID Provider 的 token endpoint:

POST /auth/realms/test/protocol/openid-connect/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ....

grant_type=authorization_code&code=....&redirect_uri=http%3A%2F%2Fxxx%2Fcallback

HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "...",
  "token_type": "Bearer",
  "refresh_token": "...",
  "expires_in": 3600,
  "id_token": "...jwt..."
}