我有一个基于 java 的桌面应用程序(带有 java 服务器),它使用 OIDC 授权代码流和 Okta 进行身份验证。它在多个不同的实例中工作正常,但客户端设置的本地服务器出现故障。我将“state”参数存储在仅服务器 cookie 中,以便我可以根据身份验证响应中的状态值对其进行检查。问题是当我的应用程序服务器收到身份验证响应时,状态 cookie 为空。
我怀疑这与客户端的网络设置有关。我的信息有限,因此我试图找出向他们的 IT 人员询问哪些问题,或者尝试排除故障的步骤。我对他们的设置有两个细节表示怀疑:
我有尝试登录的用户的网络日志(通过 chrome://net-export/ 收集)。看起来最终重定向回我们的服务器对原始请求没有源依赖性,因此应用程序服务器不知道它应该恢复服务器上的原始 HTTPSession。
在客户端(损坏)示例中,源依赖项指向与 Kerberos 相关的 Okta 服务器的重定向。
如果我进一步追溯依赖关系,它会命中此 Okta URL...
在我的工作示例中,最终重定向的依赖项直接指向应用服务器的原始请求。 收到原始请求后,服务器设置状态 cookie:
我不知道我是否正确解释了这些日志,或者为什么这些依赖链如此不同,但似乎在 Okta 和 Kerberos 之间的通信中的某个地方发生了中断。除了禁用无代理 SSO 之外,还有什么方法可以确认这一点吗?
我感谢对此的任何帮助或见解。
更新:添加 OIDC 实施的详细信息。
当您点击应用程序上的登录按钮时,会发生以下情况:
我很高兴进行重构以避免 cookie,但我不确定如何将状态参数值连接回原始状态值。也许这有点矫枉过正,服务器可以只保存一组有效状态并验证返回的参数是否位于该组中的某个位置? (或者实际上是一组状态代码验证器对。)
Cookie 通常只应返回到浏览器客户端。在浏览器之外使用 cookie 是非标准的,并且更有可能遇到基础设施问题。例如,如果请求具有
origin
标头,代理服务器或防火墙可能仅返回 cookie。在某些情况下,有效来源也可能被列入白名单。
桌面客户端中的state
和
code_verifier
参数通常存储在应用程序中,而登录则在系统浏览器中运行。这在RFC8252中进行了解释。有时,人们尝试将网站解决方案用于本机应用程序,但这通常效果不佳。
建议的更新
这里是一些示例代码(在 Node.js 中,您需要将其转换为 Java),显示了在桌面应用程序中实现流程的最典型方法。请求状态只是存储在内存中,然后与响应 URL 中的响应状态进行比较。
export async function login(): Promise<string> {
const port = getFreePort();
const redirectUri = `http://127.0.0.1:${port}`;
const state = generateRandomString();
const codeVerifier = generateRandomString();
const codeChallenge = generateHash(codeVerifier);
const authorizationUrl = buildAuthorizationRequestUrl(redirectUri, state, codeChallenge);
return new Promise<string>((resolve, reject) => {
let server: Http.Server | null = null;
const callback = async (request: Http.IncomingMessage, response: Http.ServerResponse) => {
response.end();
server.close();
server = null;
const authorizationResponseUrl = request.url!;
processAuthorizationResponseUrl(authorizationResponseUrl, state, codeVerifier);
}
server = Http.createServer(callback);
server.listen(port);
openSystemBrowser(authorizationUrl);
});
}
这可能无法正确解释您所遇到的基础设施问题,但它将消除您的 OAuth 流程中涉及服务器组件或 cookie 的需要。因此,它可能会解决您的客户问题。