You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IdentityModel.OidcClient获取的Keycloak Access Token验证失败求助

问题:IdentityModel.OidcClient获取的Keycloak Access Token introspect验证失败

使用IdentityModel.OidcClient的WindowsConsoleSystemBrowser示例从Keycloak获取Access Token后,通过curl调用<oidcServer>/token/introspect端点验证时返回{"active": false},但使用curl密码模式(grant_type=password)生成的Token,用相同验证命令却能正常返回{"active": true}。

获取到的Token相关信息

jti:1fdfa552-c745-41fe-ab98-c9cc18e84d14;
sub:17826477-591d-46bc-b5da-5731ad3e10a4;
typ:ID;
azp:smxxxpm;
sid:1ee4d385-4188-46dd-a65c-72504e47206f;
acr:1;
email_verified:False;
name:nomeSmit cognomeSmxx;
preferred_username:smxx;
given_name:nomeSmxx;
family_name:cognomeSmxx;
email:smxx.xpm@common.it;
email_verified:false;
**AccessToken**:eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJUcWN1TUlTWEhSRGpReVBjT0pkc1g4WHpkNmNDVVBCQ052RndTOUstOXpJIn0.eyJleHAiOjE3MzQzNjE1NDUsImlhdCI6MTczNDM2MTI0NSwiYXV0aF90aW1lIjoxNzM0MzYxMjQ1LCJqdGkiOiJjYTkxYTViOC00NjkwLTQwNWEtOTRiOS04MDEyODcxMTViOTkiLCJpc3MiOiJodHRwczovL2dndWFpdGEtMjAxNS5vYmplY3R3YXkuaXQ6ODQ0My9yZWFsbXMvZ2d1YWl0YS0yMDE1IiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjE3ODI2NDc3LTU5MWQtNDZiYy1iNWRhLTU3MzFhZDNlMTBhNCIsInR5cCI6IkJlYXJlciIsImF6cCI6InNtaXRPcG0iLCJzaWQiOiIxZWU0ZDM4NS00MTg4LTQ2ZGQtYTY1Yy03MjUwNGU0NzIwNmYiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3QiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLWdndWFpdGEtMjAxNSJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJub21lU21pdCBjb2dub21lU21pdCIsInByZWZlcnJlZF91c2VybmFtZSI6InNtaXQiLCJnaXZlbl9uYW1lIjoibm9tZVNtaXQiLCJmYW1pbHlfbmFtZSI6ImNvZ25vbWVTbWl0IiwiZW1haWwiOiJnaW9yZ2lvLmd1YWl0YUBvYmplY3R3YXkuaXQifQ.eeDnwjnfxP_vNgEK7W-ogE0r1qzDf_XA_LzDS5pQ-3sSGNN5YPTqv-rYk81g15q16NFQBzkopCGQ7ywRZpUfL7ov17YrDg3vwqdEjnL-h174XZstAAe25kYPzsEbREaDdHIaJYZzCQO88PwsrsgS6WccWMP7dRals9krZe0aNEnUHYtJ2EIWQUe2TRSOmpbcRW0f7fePbKCVQ9DTQ-_nYZJqAgTzpdwQyTbEV9tCeTf7FH3V9AlilnhdIg0-IEWgHDvUk36n2Q5ktQgsZB1bwWpwiMybQ4ynf7GI73cusXGXaQBaYPvwuQOX7khpJHC0w6ffB0LpmlrKXHvhBGeMOg;
**TypeToken**:Bearer;
RefreshToken:eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxNGYzYjA5Ni04MzI4LTQxOTQtOTJmNy0xMzA3ODE0MDQxMzYifQ.eyJleHAiOjE3MzQzNjMwNDUsImlhdCI6MTczNDM2MTI0NSwianRpIjoiM2E5M2Q5MDktMDcwNS00YzJhLThiYTItMWJhMDY4NDQ4NTc2IiwiaXNzIjoiaHR0cHM6Ly9nZ3VhaXRhLTIwMTUub2JqZWN0d2F5Lml0Ojg0NDMvcmVhbG1zL2dndWFpdGEtMjAxNSIsImF1ZCI6Imh0dHBzOi8vZ2d1YWl0YS0yMDE1Lm9iamVjdHdheS5pdDo4NDQzL3JlYWxtcy9nZ3VhaXRhLTIwMTUiLCJzdWIiOiIxNzgyNjQ3Ny01OTFkLTQ2YmMtYjVkYS01NzMxYWQzZTEwYTQiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoic21pdE9wbSIsInNpZCI6IjFlZTRkMzg1LTQxODgtNDZkZC1hNjVjLTcyNTA0ZTQ3MjA2ZiIsInNjb3BlIjoib3BlbmlkIGJhc2ljIHJvbGVzIHdlYi1vcmlnaW5zIGVtYWlsIHByb2ZpbGUgYWNyIn0.1aQy6Q18cICSXCPTIACaNTsjPligEHepoEQco0z_j0LHQVVDkZ-aU0GrqcABdEMyU-OH97sswhwUuJb7ZqK5lw;

验证Token的curl命令

curl -s --insecure -X "POST" "<oidcServer>/token/introspect" ^
    -H "accept: application/json" ^
    -H 'Content-Type: application/x-www-form-urlencoded' ^
    -d "client_id=smxxxpm" ^
    -d "client_secret=<oidcClientSecret>" ^
    -d "token=<AccessToken>"

验证结果

{
  "active": false
}

curl密码模式生成Token的命令

curl -s --insecure -X "POST" "<oidcServer>/token" ^
    -H "accept: application/json" ^
    -H 'Content-Type: application/x-www-form-urlencoded' ^
    -d "username=<username>" ^
    -d "password=<password>" ^
    -d "grant_type=password" ^
    -d "client_id=smxxxpm" ^
    -d "client_secret=<oidcClientSecret>"

密码模式Token的验证结果

{
  "exp": 1734362264,
  "iat": 1734361964,
  "jti": "ab514bb3-17e3-46b6-8da0-46ef03adf5a8",
  "iss": "<odicServer>+realms",
  "aud": "account",
  "sub": "17826477-591d-46bc-b5da-5731ad3e10a4",
  "typ": "Bearer",
  "azp": "smxxxpm",
  "sid": "0640bef6-7b49-4af0-bf8d-ab05745558ab",
  "acr": "1",
  "allowed-origins": [
    "http://localhost"
  ],
  "realm_access": {
    "roles": [
      "offline_access",
      "uma_authorization",
      "default-roles-xxxxxx-xxxx"
    ]
  },
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "email profile",
  "email_verified": false,
  "name": "nomeSmxx cognomeSmxx",
  "preferred_username": "smxx",
  "given_name": "nomeSmxx",
  "family_name": "cognomeSmxx",
  "email": "smxx.xpm@common.it",
  "client_id": "smxxxpm",
  "username": "smxx",
  "token_type": "Bearer",
  "active": true
}

排查与解决方案

核心问题

你标注为AccessToken的内容实际上是ID Token(从typ:ID字段可判断),而Keycloak的/token/introspect端点默认验证的是Bearer类型的Access Token,传入ID Token会直接返回active:false。

解决步骤

  1. 获取正确的Access Token
    在OidcClient的调用中,确保从TokenResponse.AccessToken属性获取值,而非ID Token。WindowsConsoleSystemBrowser示例中,RequestTokenAsync返回的TokenResponse包含AccessToken、IdToken等字段,注意区分。

  2. 确认OidcClient配置

    • 确保客户端配置的Scope包含openid(必须),以及所需的权限如email、profile
    • 检查RedirectUri是否与Keycloak客户端配置的Valid Redirect URIs一致(通常为http://localhost:xxxx这类本地回调地址)
    • 客户端Access Type需设置为confidential,因为你使用了client_secret
  3. 修正introspect调用
    将token参数替换为真正的Access Token,示例:

    curl -s --insecure -X "POST" "<oidcServer>/token/introspect" ^
        -H "accept: application/json" ^
        -H 'Content-Type: application/x-www-form-urlencoded' ^
        -d "client_id=smxxxpm" ^
        -d "client_secret=<oidcClientSecret>" ^
        -d "token=<从TokenResponse.AccessToken获取的正确值>"
    
  4. 额外检查

    • 用JWT解析工具查看Token的typ字段是否为Bearer,exp是否未过期
    • 在Keycloak后台的Realm Settings -> Events中开启登录和Token事件,排查是否有授权错误日志

内容的提问来源于stack exchange,提问作者gguaita

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:55:54