为何Duende Identity Server中谷歌认证无Client Secret/错误Client ID仍可工作?
我正在构建一个多租户认证服务,部署了多个OIDC Provider。在测试添加谷歌外部认证时发现异常:即使未指定Client Secret,甚至使用错误的Client ID,认证流程仍能成功完成。我已经试过用隐身模式测试、清除所有Cookie/本地存储/会话存储,甚至删除数据库里的用户记录,但还是能从谷歌门户拿到用户数据。
相关代码如下:
动态生成的OIDC Provider配置:
OidcProvider asiaProvider = new OidcProvider { Scheme = "googledemo", DisplayName = "GOOGLE DEMO", Enabled = true, Authority = "https://accounts.google.com/", ClientId = "exampleId", ClientSecret = "exampleSecret", Scope = "openid profile email", GetClaimsFromUserInfoEndpoint = true, };
IdentityServer服务注册代码:
builder.Services .AddIdentityServer() .AddIdentityProviderStore<DynamicAuthProviderStore>();
可能的原因
谷歌账号的授权缓存
谷歌会缓存账号已授权的应用记录,要是之前用正确的Client ID给同域名/回调地址的应用授权过,哪怕现在改了错误的Client ID,谷歌可能直接跳过重新授权,返回用户数据。DynamicAuthProviderStore配置加载异常
你的DynamicAuthProviderStore可能没正确替换默认的Provider存储,导致实际生效的是之前的正确配置,而非你测试用的错误配置。比如Store里的逻辑没读取最新配置,或者初始化时出错,错误配置没被注入。IdentityServer的元数据缓存
IdentityServer会缓存OIDC Provider的元数据(从Authority获取的配置),如果之前用正确Client ID获取过元数据,缓存没失效的话,后续错误配置下还是会用旧的有效元数据完成认证。谷歌OIDC的特殊配置
对于SPA这类公开客户端,谷歌允许不用Client Secret,但前提是Client ID正确且回调地址已在控制台配置。不过你说Client ID错了也能成,这个可能性低,但可以检查回调地址的配置有没有疏漏。
解决步骤
撤销谷歌账号的应用授权
登录谷歌账号,进入安全设置里的「第三方应用访问你的账号」,找到对应的「GOOGLE DEMO」应用并撤销授权,之后再用错误Client ID测试。验证DynamicAuthProviderStore的配置加载
在DynamicAuthProviderStore获取Provider的方法里加日志,确认返回的对象确实是你设置的错误Client ID和Client Secret:
public async Task<OidcProvider> GetAsync(string scheme) { var provider = // 你的配置获取逻辑 _logger.LogInformation("加载的OIDC Provider:Scheme={Scheme}, ClientId={ClientId}", provider.Scheme, provider.ClientId); return provider; }
启动服务后看日志,确认加载的配置是否正确。
- 清空IdentityServer缓存
- 用分布式缓存的话,直接清除对应缓存数据;用内存缓存的话,重启服务清空缓存。
- 测试时可以临时禁用元数据缓存:
.AddOidcProvider("googledemo", options => { options.MetadataAddress = "https://accounts.google.com/.well-known/openid-configuration"; options.BackchannelCache = null; // 禁用元数据缓存 // 其他配置项 });
检查谷歌控制台配置
确认谷歌控制台里有没有多个Client ID,其中某个的回调地址和你的服务匹配,可能错误Client ID刚好和有效ID的配置冲突。同时检查是否开启了无需Client Secret的客户端类型(比如SPA)。调试认证流程
在认证回调代码里加日志,查看谷歌返回的令牌和用户信息对应的Client ID,确认问题出在授权请求还是令牌验证环节。
内容的提问来源于stack exchange,提问作者Kazi Minhaj

