在之前的博客文章中, 曾不止一次介绍了OIDC协议及相关知识(详细访问: https://andaily.com/blog/?s=OIDC)
现在,开始一个新的开源项目: MyOIDC (https://git.oschina.net/mkk/MyOIDC), 将其相关的知识与实现给代码化,
我们将着重提供比OAuth2实现更好,更安全的认证与授权 安全框架实现.
顺便传播OIDC, 使用OIDC, 拥抱OIDC…
欢迎你的关注与支持…
在之前的博客文章中, 曾不止一次介绍了OIDC协议及相关知识(详细访问: https://andaily.com/blog/?s=OIDC)
现在,开始一个新的开源项目: MyOIDC (https://git.oschina.net/mkk/MyOIDC), 将其相关的知识与实现给代码化,
我们将着重提供比OAuth2实现更好,更安全的认证与授权 安全框架实现.
顺便传播OIDC, 使用OIDC, 拥抱OIDC…
欢迎你的关注与支持…
OIDC(OpenID-Connect) 1.0协议的最终版本早已确认, 用自己的语言在进行翻译中(core部分),
OpenID Connect Core 1.0 incorporating errata set 1
截止2016-08-28的翻译进度(章节3.1.2.3)
中文版: https://monkeyk.com/oidc/Final_OpenID-Connect-Core-1.0-incorporating-errata-set-1_CN.html
英文原版: http://openid.net/specs/openid-connect-core-1_0.html
JSON Web Signature(JWS): https://tools.ietf.org/html/rfc7515
持续更新中…
也可访问: http://www.cnblogs.com/linianhui/p/openid-connect-core.html
与OIDC相关介绍请访问: https://andaily.com/blog/?p=440
OIDC(OpenID Connect), 下一代的身份认证授权协议; 当前发布版本1.0;
OIDC是基于OAuth2+OpenID整合的新的认证授权协议; OAuth2是一个授权(authorization)的开放协议, 在全世界得到广泛使用, 但在实际使用中,OAuth2只解决了授权问题, 没有实现认证部分,往往需要添加额外的API来实现认证; 而OpenID呢,是一个认证(authentication )的协议, 二者在实际使用过程中都有其局限性;
综合二者,即是OIDC; 通过OIDC,既能有OAUTH2的功能,也有OpenID的功能; 恰到好处…
OIDC将是替换(或升级)OAuth2, OpenID的不二选择..
OIDC在OAuth2的access_token的基础上增加了身份认证信息; 通过公钥私钥配合校验获取身份等其他信息—– 即idToken;
一个使用JWT生成的idToken(base64):
eyJhbGciOiJSUzI1NiIsImtpZCI6IjM3MTc2NjA0OTExODEyNzkwNzgifQ.eyJpc3MiOiIxMTExIiwiYXVkIjoiMTExMSIsImF0X2hhc2giOiI4ZjgxYThjOS1jNWJiLTQwOWMtYjI0Ni1lMzEyZmUwYzM4NWMiLCJyZWdpc3RyYXRpb24iOiIxMjM0NTY3OCIsImV4cCI6MTQ2MzYyMjA4NiwianRpIjoiRnl5aGZOYnQtU0NLR2tpTWRGMVg2dyIsImlhdCI6MTQ2MzU3ODg4NiwibmJmIjoxNDYzNTc4ODI2LCJzdWIiOiJsc3otb2lkYyJ9.hDCcs8PISdwUPp6Eyd-9JCeeTJ2ZtscBeuPITIt43gMYbddiUBLC90uT9bxKe6e3awHels3asEMreFtlnlY09PwdCxXvhjYcEiXO_dnzqu-zQXESHzPEE6d1WsZUcbj6yxoxMh0laba24uu3CbqSRQbOrsYmh2_XA5Q5eP66iOajRUDhNXhmsWEL85jtL9_h0SyfRNPZ9C0mRu2x9YZTHT129O53ggqtjwQxrXLAbCd1dd35DyIztagqQWDpo3gFG7YseNEiQ6Mf2D6nIBU9llAqH4sTThq_ahME06qKENat_sxnmIJN2UHw7u0E08S-59oxtOY9winT78Qj5IfWJw
在OIDC协议的实现中, 其底层是基于OAuth2. 一些常用的库如: JWT(https://jwt.io/), JWS; OAuth2的实现如: Spring Security OAuth, OLTU.
更多信息可参考: http://openid.net/connect/
OIDC 1.0协议: http://openid.net/specs/openid-connect-core-1_0.html
拥抱OIDC…
适用版本:spring-security-oauth2 v1.1及以上
| URI | Filter | 说明 |
| /.well-known/openid-configuration | OidcProviderConfigurationEndpointFilter | 获取配置OIDC的meta数据信息 |
| /.well-known/oauth-authorization-server | OAuth2AuthorizationServerMetadataEndpointFilter | 获取配置OAuth2的meta数据信息 |
| /userinfo | OidcUserInfoEndpointFilter | 获取OIDC用户信息 |
| /connect/logout | OidcLogoutEndpointFilter | 处理RP端发起的退出请求 |
| /connect/register | OidcClientRegistrationEndpointFilter | 允许注册client端的默认实现 |
| /oauth2/authorize | OAuth2AuthorizationEndpointFilter | OAuth2中认证逻辑处理入口 |
| /oauth2/jwks | NimbusJwkSetEndpointFilter | 获取jwks配置信息 |
| /oauth2/device_authorization | OAuth2DeviceAuthorizationEndpointFilter | OAuth2中设备授权处理入口 |
| /oauth2/device_verification | OAuth2DeviceVerificationEndpointFilter | OAuth2中设备校验处理入口 |
| /oauth2/token | OAuth2TokenEndpointFilter | OAuth2中token处理入口 |
| /oauth2/introspect | OAuth2TokenIntrospectionEndpointFilter | OAuth2中检查token状态入口(是否激活) |
| /oauth2/revoke | OAuth2TokenRevocationEndpointFilter | OAuth2中撤回已签发的token入口 |
具体的实现与参考请访问:https://gitee.com/shengzhao/spring-oauth-server
Java中要生成PublicKey需要KeyPair对象,先生成KeyPair,通过KeyPairGenerator,这需要结合算法并设置长度,常用的为RSA,长度可以是 1024,2048等。示例如下:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
assertNotNull(keyPair);
PrivateKey aPrivate = keyPair.getPrivate();
PublicKey aPublic = keyPair.getPublic();
//base64
String base64PrivateKey = new String(Base64.encodeBase64Chunked(aPrivate.getEncoded()));
// System.out.println(base64PrivateKey);
String base64PublicKey = new String(Base64.encodeBase64Chunked(aPublic.getEncoded()));
// System.out.println(base64PublicKey);
使用Base64可将生成的PublicKey,PrivateKey转化为方便传输的 base64格式数据,转化后的PublicKey数据如:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq7h9NrI7OF4m2R53nemmih4N2ds13n/L
ARfFO1hDGKwE36iU+bCLlkw59gPrWgcsc4lKqVrQC3S3NlBIbkX7pcP2zGth3j5uCfM9DOnM+Jxg XyYVDf9YduuevII142BmG/5CGjrdJmDS4wdUZ+vXJPiSGXMdpRM4+p8jcPoZ71YUPJzxu9pOgD37 RL1UdD3wvM63sixPSmmwTua4GExcKnNZzeiM91UqvI90CG+gH/YG0hf2Pnd5ACquToFLPsUn95d6 cqIERTDi8NiBzB/AhlISM69IDnLhRdU8YjZuxoaFZhQT8eZ6Qhr75/aiUu0zN3aNeOHnrJHKV/Lq
xng6VQIDAQAB
当需要使用时可通过 KeyFactory 将base64数据转化为具体的PublicKey或PrivateKey对象。代码如下:
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64PrivateKey));
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
assertNotNull(privateKey);
assertEquals(privateKey, aPrivate);
PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(base64PublicKey)));
assertNotNull(publicKey);
assertEquals(publicKey, aPublic);
转化后的对象与原生的是一样的,可用于加密/解密, 签名验签等。
OAuth2中默认使用 Bearer Tokens (一般用UUID值)作为token的数据格式,但也支持升级使用JSON Web Token(JWT)来作为token的数据格式。
下面以 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工程)。
过去几年的OAuth2经历与使用,总结一下,记录有关 access_token, refresh_token的各类配置与场景适应,到此以自问自答的形式把这些琐碎的点总结下来。
说明:以下问答中的截图或表等信息以 spring-oauth-server 中配置为参考。
答:可以,需要按以下步骤操作:首先在client_details定义中不设置 refresh_token_validity 字段值(即默认null),其次在配置OAuth2的DefaultTokenServices时将refreshTokenValiditySeconds属性值配置为0或小于0(默认为30天,若想修改为其他默认值也在此配置),关键代码看下图
答:可以,但不推荐使用(因为永不过期意味着除手动清除外无安全性可言);若需要按以下步骤操作:首先在client_details定义中不设置 access_token_validity字段值(即默认null),其次在配置OAuth2的DefaultTokenServices时将accessTokenValiditySeconds属性值配置为0或小于0(默认为12小时,若想修改为其他默认值也在此配置),关键代码看下图
答:可以,首先要求client_details的grant_type不支持 refresh_token,即authorized_grant_types字段中无 refresh_token,其次在配置OAuth2的DefaultTokenServices时将supportRefreshToken配置为false即可,关键代码看下图
答:默认access_token有效时间为12小时,默认refresh_token有效时间为30天,这两默认值在OAuth2的DefaultTokenServices中定义的,如下图:
若想改变默认值,只需要在定义client_details是修改字段access_token_validity (access_token有效时间)与 refresh_token_validity (refresh_token有效时间),单位为:秒
答:可以支持此功能,具体为在配置OAuth2的DefaultTokenServices时将reuseRefreshToken属性配置为fasle即可(默认true),关键代码看下图
答:可以加自己的扩展逻辑。首先需要写一个类实现接口 TokenEnhancer.java ,实现方法 enhance方法,一示例如下:
其次在配置 OAuth2的DefaultTokenServices时增加tokenEnhancer属性配置,关联扩展实现的类即可,关键代码如下
实际上Spring Security OAuth2中实现JWT从而支持OIDC流程就是扩展TokenEnhancer.java来实现的(有一个实现类 JwtAccessTokenConverter.java)
答:确实生成的access_token是一UUID值,若要扩展不使用UUID,需要这样做:首先写一个子类继承DefaultTokenServices.java,其次将DefaultTokenServices.java的源代码复制到扩展的子类中,并修改createAccessToken方法与createRefreshToken方法中的代码(如此做是因为两方法定义的private的),关键代码如下
另一种办法是通过扩展TokenEnhancer.java 来实现(详细见上一问答)
答:在大数据高并发环境时,建议使用Redis,将access_token, refresh_token存储在Redis中实现,具体在配置OAuth2的TokenStore时使用子类 RedisTokenStore(默认使用的子类为JdbcTokenStore),更多信息请查看 http://andaily.com/blog/?p=19776
更高的性能推荐使用JWT格式的token,详见 https://andaily.com/blog/?p=20133。
答:有,OAuth2.1版本协议,状态与特征详见 https://andaily.com/blog/?p=20004。