Apereo CAS OAuth2 接入 JWT Access Token:按服务配置、签名加密密钥与实现原理
后端认证鉴权单点登录【免费下载链接】casApereo CAS - Identity Single Sign On for all earthlings and beyond.项目地址https://gitcode.com/gh_mirrors/ca/cas点击查看免费下载导读本文基于 OAuth-Authentication-JWT-AccessTokens.md 展开讲解 Apereo CAS 如何将 OAuth2 的 access token 从默认的不透明标识符opaque identifier切换为自包含的 JWT包括按注册服务per-service开启、签名/加密密钥的按服务与全局配置方式并结合仓库源码剖析 JWT 的构建、签名、加密与校验链路。读完本文你将能够为指定的 OAuth2 客户端单独启用 JWT access token正确配置accessTokenAsJwt*系列服务属性并理解 CAS 在底层如何决定某个 token 是否以 JWT 形式签发。一、从 Opaque 到 JWT两种 Access Token 形态在 Apereo CAS 中OAuth2 授权码或客户端凭证等流程成功后签发的 access token默认是一个不透明的随机标识符opaque identifier客户端拿到它之后必须携带它回调 CAS 的/profile等端点换取用户信息无法自行解读其内容token 的实际状态用户、过期时间、作用域等保存在 CAS 的 ticket registry 中。CAS 同时提供了第二种形态按注册服务决定是否把 access token 生成成 JWT。JWT 自包含、可离线解析与验签客户端拿到后无需再回调 CAS 即可读取其中的声明claims。这一能力在 CAS 中由注册服务模型与 JWT 构建器共同支撑注册服务端OAuthRegisteredService提供了jwtAccessToken以及配套的jwtRefreshToken开关字段见 OAuthRegisteredService.java编码端OAuth20JwtAccessTokenEncodableCipher负责把票据说成 JWT见 OAuth20JwtAccessTokenEncodableCipher.java。两种形态可以并存默认仍是 opaque只有显式开启 JWT 的客户端才走 JWT 路径。二、按服务启用 JWT Access Token注册服务 JSON 详解原文档给出的注册服务定义如下这是启用该能力最核心的配置入口{ class : org.apereo.cas.support.oauth.services.OAuthRegisteredService, clientId: clientid, clientSecret: clientSecret, serviceId : ^(https|imaps)://redirect-uri.*, name : OAuthService, id : 100, jwtAccessToken: true, properties : { class : java.util.HashMap, accessTokenAsJwtSigningKey : { class : org.apereo.cas.services.DefaultRegisteredServiceProperty, values : [ java.util.HashSet, [ ... ] ] }, accessTokenAsJwtEncryptionKey : { class : org.apereo.cas.services.DefaultRegisteredServiceProperty, values : [ java.util.HashSet, [ ... ] ] }, accessTokenAsJwtSigningEnabled : { class : org.apereo.cas.services.DefaultRegisteredServiceProperty, values : [ java.util.HashSet, [ true ] ] }, accessTokenAsJwtEncryptionEnabled : { class : org.apereo.cas.services.DefaultRegisteredServiceProperty, values : [ java.util.HashSet, [ true ] ] }, accessTokenAsJwtCipherStrategyType : { class : org.apereo.cas.services.DefaultRegisteredServiceProperty, values : [ java.util.HashSet, [ ENCRYPT_AND_SIGN ] ] } } }要点逐项说明jwtAccessToken: true这是总开关。对应OAuthRegisteredService中的jwtAccessToken布尔字段OAuthRegisteredService.java含义为为该服务签发 JWT 形式的 access token。同文件还定义了jwtRefreshToken可单独控制刷新令牌是否也以 JWT 签发。properties块是 CAS 注册服务的通用扩展属性机制RegisteredServiceProperty以class: java.util.HashMap声明每个属性值是DefaultRegisteredServiceProperty内部以HashSet包装实际取值字符串、布尔或枚举。属性键与语义均由 RegisteredServiceProperty.java 中RegisteredServiceProperties枚举统一定义归属JWT_ACCESS_TOKENS分组。属性速查表属性键类型默认值说明accessTokenAsJwtSigningKeySTRING空签发 JWT access token 时使用的签名密钥按服务提供accessTokenAsJwtEncryptionKeySTRING空签发 JWT access token 时使用的加密密钥按服务提供accessTokenAsJwtSigningEnabledBOOLEANtrue是否对生成的 JWT 做签名accessTokenAsJwtEncryptionEnabledBOOLEANfalse是否对生成的 JWT 做加密注意原文档示例显式置为true而枚举默认值为falseaccessTokenAsJwtCipherStrategyTypeSTRINGENCRYPT_AND_SIGN签名/加密操作的先后策略accessTokenAsJwtEncryptionAlgSTRING空加密算法需要时指定提示accessTokenAsJwtSigningKey/accessTokenAsJwtEncryptionKey中的...是占位符实际部署时应替换为符合密钥尺寸要求的 Base64 编码密钥材料默认签名/加密密钥尺寸由 CAS 的 JWT 加密配置模型给出见下文第三节。三、签名与加密密钥按服务定义或全局统一定义原文档明确指出签名与加密密钥可以按服务per-service定义也可以全局globally via CAS settings定义。按服务定义即上面 JSON 中的accessTokenAsJwtSigningKey、accessTokenAsJwtEncryptionKey属性每个客户端可使用自己的密钥对适合密钥隔离要求高的场景。全局定义通过 CAS 配置文件中的cas.authn.oauth.accessToken属性块统一定义。对应配置模型为 OAuthAccessTokenProperties.java其中createAsJwt默认false全局开关置为true时所有 OAuth2 客户端的 access token 都以 JWT 签发见 OAuthAccessTokenProperties.java。includeClaimsInJwt默认true控制 JWT access token 是否把 CAS 的属性claims一并放入 JWT仅当 token 确认为 JWT 时生效见 OAuthAccessTokenProperties.java。crypto嵌套的EncryptionOptionalSigningOptionalJwtCryptographyProperties承载全局签名/加密密钥与密钥尺寸其构造器会把加密与签名密钥尺寸分别设为DEFAULT_STRINGABLE_ENCRYPTION_KEY_SIZE/DEFAULT_STRINGABLE_SIGNING_KEY_SIZE见同文件OAuthAccessTokenProperties()构造方法表明未显式提供密钥时 CAS 会按内置默认尺寸生成。优先级方面从shouldEncodeAsJwt()的判定逻辑看服务级jwtAccessToken与全局createAsJwt是**或OR**关系任一为真即按 JWT 签发详见第四节密钥层面服务级accessTokenAsJwt*属性存在时优先生效否则回落到全局 crypto 配置。四、底层原理CAS 如何决定并构建 JWT Access Token4.1 编码链路JWT access token 的生成入口是 OAuth20JwtAccessTokenEncoder.java它把普通 token包装成可编码/可解码的 cipher 对象EncodableCipher/DecodableCipher供 token 响应生成器在签发时调用。真正执行编码的是OAuth20JwtAccessTokenEncodableCipher.encode(...)只有当注册服务是OAuthRegisteredService且shouldEncodeAsJwt()判定成立时才调用AccessTokenJwtBuilder.build(...)构建 JWT否则原样返回token.getId()即退化为不透明标识符。4.2 shouldEncodeAsJwt 判定逻辑见 OAuth20JwtAccessTokenEncodableCipher.java以下任一条件满足即按 JWT 编码forceEncodeAsJwt调用方强制例如 token exchange 流程中客户端显式请求 JWT 类型的 tokenaccess tokentoken instanceof OAuth20AccessToken且全局oauth.accessToken.createAsJwt为真或服务级jwtAccessToken为真refresh tokentoken instanceof OAuth20RefreshToken且全局oauth.refreshToken.createAsJwt为真或服务级jwtRefreshToken为真dpopRequest请求携带 DPoPDemonstrating Proof of Possession确认信息时强制编码为 JWT。4.3 JWT 的声明claims构成构建请求由getJwtRequestBuilder()组装OAuth20JwtAccessTokenEncodableCipher.javaississuer默认取cas.server.prefixCAS 服务前缀可被调用方显式覆盖subsubject认证主体的 principal idjtiJWT ID即 access token 自身的 idtoken.getId()用于关联 ticket registryiatissue date取认证时间authentication.getAuthenticationDate()expexpiration认证时间加上 token 过期策略的 TTLtoken.getExpirationPolicy().getTimeToLive()见determineValidUntilDate()audaudience默认取token.getClientId()若注册服务配置了audience集合则取其值token exchange 场景还可显式指定 audience见determineServiceAudience()业务 claims当 token 是OAuth20AccessToken且全局includeClaimsInJwt为真时通过collectClaimsForAccessToken()收集属性先按服务属性释放策略构建主属性buildPrincipalForAttributeFilter再经ProfileScopeToAttributesFilter按 OAuth2 scope 过滤后才写入 JWT并补充grant_type、response_type等声明同时剔除password等敏感参数DPoP、X.509 证书摘要x5t#S256等确认信息也会转为对应 claim。签名与加密的顺序由accessTokenAsJwtCipherStrategyType默认ENCRYPT_AND_SIGN即先加密再签名决定与 JWT 服务票据jwtAsServiceTicket的策略机制同源二者共用RegisteredServiceProperties枚举中同一套 cipher 策略语义。4.4 消费端校验客户端携带 JWT access token 回调 CAS 的/profile端点时由OAuth20AccessTokenAuthenticator见 OAuth20AccessTokenAuthenticator.java执行校验它通过OAuth20JwtAccessTokenEncoder.toDecodableCipher(...)得到解码器OAuth20JwtAccessTokenDecodableCipher按对应注册服务的密钥完成验签/解密再解析出原 access token 继续走后续的 profile 处理流程。若 token 并非 JWT则直接以 opaque 标识符查 ticket registry。五、测试验证与参考实现仓库中已有完整的单元测试覆盖该能力可作为行为规范参考OAuth20JwtAccessTokenEncoderTests.java验证编码/解码 cipher 的互逆行为OAuth20RegisteredServiceJwtAccessTokenCipherExecutorTests.java验证按服务级密钥执行签名/加密OAuth20JwtAccessTokenCipherExecutorTests.java验证全局 cipher executorOAuth20DefaultTokenGeneratorTests.java验证 token 生成流程中对 JWT 分支的处理。六、配置小结与注意事项开关两处服务级jwtAccessToken: true只影响该客户端全局cas.authn.oauth.accessToken.createAsJwt: true影响全部客户端二者取或。密钥三要素签名密钥accessTokenAsJwtSigningKey/ 全局 crypto、加密密钥accessTokenAsJwtEncryptionKey/ 全局 crypto、策略类型accessTokenAsJwtCipherStrategyType原文档建议同时开启签名与加密时注意显式设置accessTokenAsJwtEncryptionEnabled: true因为其枚举默认值为false。claims 控制默认includeClaimsInJwttrueJWT 会携带经 scope 过滤后的用户属性如客户端只需要sub等标准声明可将其置为false以减小 token 体积。audience 默认值未配置audience时aud取clientId资源服务器做 audience 校验时应与 clientId 对齐。特殊触发DPoP 请求与 token exchange 请求请求 JWT 类型会强制走 JWT 编码即使未开启上述任一开关。以上配置与实现全部以当前仓库gh_mirrors/ca/cas源码为准属性枚举见 RegisteredServiceProperty.java服务模型见 OAuthRegisteredService.java配置模型见 OAuthAccessTokenProperties.java。赞分享后端认证鉴权单点登录【免费下载链接】casApereo CAS - Identity Single Sign On for all earthlings and beyond.项目地址https://gitcode.com/gh_mirrors/ca/cas点击查看免费下载相关推荐Apereo CAS JWT Service Ticket 配置指南把 ST 变成自包含 JWT 的原理、逐服务密钥与客户端验签实现Apereo CAS JWT Service Ticket 配置指南把 ST 变成自包含 JWT 的原理、逐服务密钥与客户端验签实现 本文围绕 Apereo后端认证鉴权单点登录Apereo CAS 配置安全Spring Cloud 配置服务器加密/解密实战指南Apereo CAS 配置安全Spring Cloud 配置服务器加密/解密实战指南 导读 本文聚焦 Apereo CAS 项目中基于 Spring Clo后端认证鉴权单点登录Apereo CAS SAML2 IdP 安全配置签名与加密算法的层级化配置及源码实现解析Apereo CAS SAML2 IdP 安全配置签名与加密算法的层级化配置及源码实现解析 Apereo CAS 作为 SAML2 身份提供者IdP时其后端认证鉴权单点登录创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →