MyOIDC v1.1.2 发布,基于OIDC协议的参考实现

MyOIDC  — 基于OIDC协议的参考实现,根据各类库提供实现参考 。正式版本v1.1.2发布,此版本主要是安全升级,更新内容:

1.为了处理CVE安全漏洞,对以下依赖库进行了升级:

  • spring-boot升级到v2.5.9;
  • spring-security-oauth2升级到v2.3.8.RELEASE
  • guava升级到v31.0-jre

2.增加了banner.txt,更新README.md让使用者更易上手

3.修复已知的各类bug

v1.1.2 tag:https://gitee.com/mkk/MyOIDC/tree/v1.1.2

OAuth2中token升级使用JWT的实现参考

OAuth2中默认使用 Bearer Tokens (一般用UUID值)作为token的数据格式,但也支持升级使用JSON Web Token(JWT)来作为token的数据格式。

20200918101526

下面以 spring-oauth-server 升级使用JWT来说明

重点在于提供一个 JwtTokenStore的配置类,详细可参见 MyOIDC 工程中的配置:https://gitee.com/mkk/MyOIDC/blob/master/myoidc-server/src/main/java/myoidc/server/config/OAuth2ServerConfiguration.java

需要注意的是底层使用的算法,可以是RSA也可以对称加密的HMAC等,具体可查看 JwtAccessTokenConverter.java 类。

对应的工程中需要增加 spring-security-jwt 库的依赖(如果是Maven工程)。

 

OIDC中JWK,JWKS的介绍与使用

JWKS全称为 JSON Web Key Set,是指多个JWK组合在一起的一种格式(详见 https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-5 );

JWK全称是JSON Web Key,其标准协议链接:https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41

JWK在OIDC中的主要作用是为JWT(id_token)提供加密密钥,用于加密/解密或签名/验签,是JSON格式的数据。

综上所说,掌握了如何生成JWK,再按照JWKS协议的要求组合起来即可。根据使用不同的加密算法,各种算法的JWK展示内容会有些区别,一个使用RSA算法的JWK格式的数据如下,使用jose4j生成:

{
  "kty": "RSA",
  "kid": "myoidc-keyid",
  "use": "sig",
  "alg": "RS256",
  "n": "xMNL1jDatbHWGDH_H9GZbb2R4Ck2ga-lfE6wJnno_MfqJibSqkiLTZ7P06woJFxzB0WDu2PBe-ptRNoJhEnkzL8c1mgbGOdPVCsaaDm-POGZ3gnWGcyzyuJ9s9km41Rlan3TuuC3HIniY4bmyQAZ-SLwrFk7Bfa91ui4F9S5RvM",
  "e": "AQAB",
  "d": "q73XDM65p8vgll_VUn2NUPcdQ65VUB7y76xzHjJchX8tRj2utUj6pjaPKi_jHdG_6UHouIBa2oEE_QrfMaOZ2wA6LgYPXT_a296LKoOtKKRUlgob_leHxn0FJxLOXtEHgMqDgtMQ1-eFipsFgriip94dmcLEWW3YVK_y5JwJrnE",
  "p": "7OqN19bEbMb9cr9zA98QQq9LOgvQfq5-nOvzwMsubqMosHxViRnivFz2-3LpusK7u2XEG5EljqUxZrf4lgeVmw",
  "q": "1Jy9ksoLuQ5tuc4docgLaXQWqf3iaTm3iC07AA4v9jHzvnkewWFS_PUPPcra4475Dew-y7oIENaRBMijrrWViQ",
  "dp": "HBEdhLh4xLo-RF3R7l96uauyqcnEhX1-mnCJjAmGEq1ZoK7aI0fhyJbq25cdgXaYbvb7aJilbmS7mYOp-3wiiQ",
  "dq": "NRMLn-EgHAomCgQSEZjGgISiQ71FD8-AqVXhLJpeDq9ZkWra6ptJBCyIqXxCOBwwv_EBnAnMiaeGfBM6CRr7QQ",
  "qi": "VCdAeu4h25X_kM69Netc3SKPo5P-1VjeSHz0Ko0QuSMF0INc6H2yi7hZgZuYANVaTF1Ipf6lWfHBLpuRGh3lXw"
}

JWK数据的格式具体可参见 https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4

主要属性:kty(Key类型),use(两个可选值:sig or enc),alg(具体的算法),kid(Key的唯一标识id)

 

有了JWK数据,只需要按照JWKS的格式组装成对应的JSON数据即可,以上面的JWK组装的JWKS数据如下:

{
  "keys": [
    {
      "p": "7OqN19bEbMb9cr9zA98QQq9LOgvQfq5-nOvzwMsubqMosHxViRnivFz2-3LpusK7u2XEG5EljqUxZrf4lgeVmw",
      "kty": "RSA",
      "q": "1Jy9ksoLuQ5tuc4docgLaXQWqf3iaTm3iC07AA4v9jHzvnkewWFS_PUPPcra4475Dew-y7oIENaRBMijrrWViQ",
      "d": "q73XDM65p8vgll_VUn2NUPcdQ65VUB7y76xzHjJchX8tRj2utUj6pjaPKi_jHdG_6UHouIBa2oEE_QrfMaOZ2wA6LgYPXT_a296LKoOtKKRUlgob_leHxn0FJxLOXtEHgMqDgtMQ1-eFipsFgriip94dmcLEWW3YVK_y5JwJrnE",
      "e": "AQAB",
      "use": "sig",
      "kid": "myoidc-keyid",
      "qi": "VCdAeu4h25X_kM69Netc3SKPo5P-1VjeSHz0Ko0QuSMF0INc6H2yi7hZgZuYANVaTF1Ipf6lWfHBLpuRGh3lXw",
      "dp": "HBEdhLh4xLo-RF3R7l96uauyqcnEhX1-mnCJjAmGEq1ZoK7aI0fhyJbq25cdgXaYbvb7aJilbmS7mYOp-3wiiQ",
      "alg": "RS256",
      "dq": "NRMLn-EgHAomCgQSEZjGgISiQ71FD8-AqVXhLJpeDq9ZkWra6ptJBCyIqXxCOBwwv_EBnAnMiaeGfBM6CRr7QQ",
      "n": "xMNL1jDatbHWGDH_H9GZbb2R4Ck2ga-lfE6wJnno_MfqJibSqkiLTZ7P06woJFxzB0WDu2PBe-ptRNoJhEnkzL8c1mgbGOdPVCsaaDm-POGZ3gnWGcyzyuJ9s9km41Rlan3TuuC3HIniY4bmyQAZ-SLwrFk7Bfa91ui4F9S5RvM"
    }
  ]
}

以上的JWK,JWKS的示例的完整代码(JAVA实现)可在此查看 https://gitee.com/mkk/MyOIDC/blob/master/myoidc-server/src/test/java/myoidc/server/infrastructure/JWKSTest.java。代码中还包括除RSA外,ECC,OCT的示例实现。

 

JWK本身未定义一种新的加密算法或变种,只是定义一种JSON格式的数据展示(更符合互联网传输),其底层实现依旧依赖PKI体系的技术,如x509,公钥/私钥体系。在其协议介绍中能更好地体现出来。

20200920160628

 

如果是使用非JAVA语言,也可以使用对应的PKI技术生成JWK,如openssl;

一个使用JDK自带的 keytool 工具生成的示例如下:

keytool -genkeypair -alias oidc-demo -validity 180 -keyalg RSA -keypass oidc-demo -keystore oidc-demo.jks -storepass oidc-demo

命令输入后依次填写DN的各类信息,即可生成 oidc-demo.jks文件,密码为 oidc-demo,文件中有私钥公钥等信息。

若需要导出为 x509格式数据,使用keytool命令:

keytool -exportcert -keystore oidc-demo.jks -rfc -file oidc-demo.cer -alias oidc-demo

输入密码后生成的 oidc-demo.cer文件为x509格式。

 

OIDC中的术语介绍与示例

 

以下对OIDC主要的术语进行说明,并与OAuth2作相关对比。

  • EU End-User, 指用户(一般指有账号的个体,资源的拥有者)
  • RP Relying Party, 信任方(一般是一个软件应用), 理解为OAuth2中的客户端(client)即可, 需要在OP中注册
  • OP OpenID Provider, 能提供对EU进行认证的服务端(可理解为OAuth2中授权服务端),
    提供RP的注册(或管理)能力,EU管理,ID Token的签发与管理等。OIDC中的核心组件。
    OIDC-Server 就是一个OP的参考实现
  • ID Token 格式为JSON Web Token(JWT),
    包含EU认证授权信息等. 有关JWT请访问 https://jwt.io/除了JWT, 知道以下概念对掌握OIDC会很有帮助
    JSON Web Key(JWK),
    JSON Web Encryption(JWE),
    JSON Web Algorithm(JWA),
    JSON Web Signature(JWS)
  • UserInfo Endpoint EU信息接口(OAuth2保护), 在RP获取到access_token后,可调用此接口获取EU的详细信息.
    OIDC要求此接口必须使用https访问(更安全);一般在OP中提供的Discovery中获取
  • Claim EU信息的载体, 可在id_token中获取,主要包括认证信息与授权信息,可根据实际扩展
  • 查看完整术语定义请访问 https://openid.net/specs/openid-connect-core-1_0.html#Terminology

OIDC协议中抽象了一个主要的操作步骤与流程示意图,如下:

20200920150958

下面以AWS提供的OIDC服务来举例说明。 假设你现在有一个应用A想集成使用AWS的OIDC服务,在实现OIDC之前需要先做几件事

  1. 应用A(RP)先去AWS(OP)中注册一个应用并获取对应的client_id, client_secret,public key等信息( 一般这步骤是开发者去完成)。注册时一般需要提供应用名称,redirect_uri等信息。
  2. 根据AWS提供的实现文档进行应用A(RP)的集成(也是开发者完成)。

OIDC流程在此示例中的关系图如下:

20200920151748

结束。

 

详细完整的使用请访问 MyOIDC: https://gitee.com/mkk/MyOIDC

 

MyOIDC v1.1.1 发布,基于 OIDC 协议的参考实现,根据各类库提供实现参考

MyOIDC  –基于OIDC协议的参考实现,根据各类库提供实现参考 。正式版本v1.1.1发布,主要更新内容:

  1. 修改启动方法为jar直接运行
  2. 更新How-To-Use.txt
  3. AccessToken使用时允许获取更详细用户信息
  4. 增加 JWKS test与使用说明示例
  5. jose4j升级使用0.7.1版本

openid

GitHub:   https://github.com/monkeyk/MyOIDC/tree/v1.1.1

Gitee:  https://gitee.com/mkk/MyOIDC/tree/v1.1.1

MyOIDC v1.1.0 发布–基于OIDC协议的参考实现,根据各类库提供实现参考

MyOIDC  –基于OIDC协议的参考实现,根据各类库提供实现参考 。第1个正式版本v1.1.0发布,主要更新内容:

  1. 实现OIDC协议的主要流程,包括 DiscoveryEndpoint等各类Endpoint提供实现参考;实现OIDC中主要的认证授权流程;JWKS API实现等。
  2. 实现myoidc-server, myoidc-client 两模块的各类功能细节,能实际使用,形成操作闭环。
  3. openid

V1.1.0 代码库链接:

GitHub:  https://github.com/monkeyk/MyOIDC/tree/v1.1.0

Gitee: https://gitee.com/mkk/MyOIDC/tree/v1.1.0/

 

各类JWT库(java)的使用与评价

https://jwt.io/ 网站中收录有各类语言的JWT库实现(有关JWT详细介绍请访问 https://jwt.io/introduction/),

其中JAVA语言到目前(2018-06)有6个实现库,如下图:

jwt

按顺序依次是

Auth0实现 的 java-jwt

Brian Campbell实现的 jose4j

connect2id实现的 nimbus-jose-jwt

Les Haziewood实现的 jjwt

Inversoft实现的prime-jwt

Vertx实现的vertx-auth-jwt.

 

以下是各个库的使用测试

java-jwt

oauth0

完整测试链接  https://github.com/monkeyk/MyOIDC/blob/1.1.0/myoidc-server/src/test/java/myoidc/server/infrastructure/Auth0JwtTest.java

点评:

Auth0提供的JWT库简单实用, 依赖第三方(如JAVA运行环境)提供的证书信息(keypair);

有一问题是在 生成id_token与 校验(verify)id_token时都需要 公钥(public key)与密钥(private key), 个人感觉是一不足(实际上在校验时只需要public key即可)

 

jose4j

jose4j

完整测试链接: https://github.com/monkeyk/MyOIDC/blob/1.1.0/myoidc-server/src/test/java/myoidc/server/infrastructure/Jose4JTest.java

点评:

jose4j提供了完整的JWT实现, 可以不依赖第三方提供的证书信息(keypair, 库本身自带有RSA的实现),类定义与JWT协议规定匹配度高,易理解与上手

对称加密与非对称加密都有提供实现

 

nimbus-jose-jwt

nimbus

完整测试链接: https://github.com/monkeyk/MyOIDC/blob/1.1.0/myoidc-server/src/test/java/myoidc/server/infrastructure/NimbusJoseJwtTest.java

点评:

nimbus-jose-jwt库类定义清晰,简单易用,易理解 , 依赖第三方提供的证书信息(keypair), 对称算法 与非对称算法皆有实现.

 

jjwt

jjwt

完整测试链接: https://github.com/monkeyk/MyOIDC/blob/1.1.0/myoidc-server/src/test/java/myoidc/server/infrastructure/JJwtTest.java

点评:

jjwt小巧够用, 但对JWT的一些细节包装不够, 比如 Claims (只提供获取header,body)

 

prime-jwt

primejwt

完整测试链接: https://github.com/monkeyk/MyOIDC/blob/1.1.0/myoidc-server/src/test/java/myoidc/server/infrastructure/PrimeJwtTest.java

点评:

prime jwt库怎么说呢, 有些地方不符合JAVA语言规范, 支持对称算法(HMAC) 与非对称算法(RSA), 也算容易理解

 

vertx-auth-jwt

vertxjwt

完整测试链接: https://github.com/monkeyk/MyOIDC/blob/1.1.0/myoidc-server/src/test/java/myoidc/server/infrastructure/VertxAuthJwtTest.java

 点评:

Vertx Auth Jwt 库算是最不容易理解的一个库了.花了不少时间才弄通这一示例. 不容易上手. 并且生成与校验id_token 时都需要公钥与私钥,不足.

 

———————————————————

以下是在使用中的一些总结或注意点

1. 几乎所有库都要求JAVA版本1.7或更高版本, 1.6或以下的版本需要二次开发(或不支持)

2.从易用性, 扩展性, 完整性等来看, 使用首先推荐 jose4j, 其次是 Nimbus-jose-jwt.

3. JWT是实现OIDC的基石,掌握其使用对实现OIDC有很大帮助(同时对JAVA证书使用, PKI体系的掌握也有要求)

 

 

https://github.com/monkeyk/MyOIDC

spring-oauth-server 2.0.0 发布,使用Spring-Boot2.0实现

经过一年多的时间后,我们发布了 spring-oauth-server 2.0.0版本.

使用Spring-Boot 2.0版本重构, 进入模块化,零配置时代. 更符合技术发展与实际需要.

相比之前的版本(1.0及之前版本), 更新如下:

1. 全新的 Spring-Boot风格

2.ClientDetails中的 client_secret 字段加密保存

3.密码加密方式由MD5变成 BCrypt

4.增加CSRF机制支持

5.resourceId变为可选(但建议使用固定的resourceId)

https://gitee.com/shengzhao/spring-oauth-server/tree/2.0.0/