diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/constants/IdTokenClaimNames.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/constants/IdTokenClaimNames.java new file mode 100644 index 0000000000000000000000000000000000000000..ff4fd46f748ee50b139ff2227c69f1bb732fbee6 --- /dev/null +++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/constants/IdTokenClaimNames.java @@ -0,0 +1,74 @@ +package com.central.oauth2.common.constants; + +/** + * id_token属性名常量 + * + * @author zlt + * @version 1.0 + * @date 2021/4/23 + *
+ * Blog: https://zlt2000.gitee.io
+ * Github: https://github.com/zlt2000
+ */
+public class IdTokenClaimNames {
+ /**
+ * {@code iss} - the Issuer identifier
+ */
+ public final static String ISS = "iss";
+
+ /**
+ * {@code sub} - the Subject identifier
+ */
+ public final static String SUB = "sub";
+
+ /**
+ * {@code aud} - the Audience(s) that the ID Token is intended for
+ */
+ public final static String AUD = "aud";
+
+ /**
+ * {@code exp} - the Expiration time on or after which the ID Token MUST NOT be accepted
+ */
+ public final static String EXP = "exp";
+
+ /**
+ * {@code iat} - the time at which the ID Token was issued
+ */
+ public final static String IAT = "iat";
+
+ /**
+ * {@code auth_time} - the time when the End-User authentication occurred
+ */
+ public final static String AUTH_TIME = "auth_time";
+
+ /**
+ * {@code nonce} - a {@code String} value used to associate a Client session with an ID Token,
+ * and to mitigate replay attacks.
+ */
+ public final static String NONCE = "nonce";
+
+ /**
+ * {@code acr} - the Authentication Context Class Reference
+ */
+ public final static String ACR = "acr";
+
+ /**
+ * {@code amr} - the Authentication Methods References
+ */
+ public final static String AMR = "amr";
+
+ /**
+ * {@code azp} - the Authorized party to which the ID Token was issued
+ */
+ public final static String AZP = "azp";
+
+ /**
+ * {@code at_hash} - the Access Token hash value
+ */
+ public final static String AT_HASH = "at_hash";
+
+ /**
+ * {@code c_hash} - the Authorization Code hash value
+ */
+ public final static String C_HASH = "c_hash";
+}
diff --git a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/JwtUtils.java b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/JwtUtils.java
index 01d3110b0c50340ad505ca70adf24fe163505a12..e56274050468259c6b071c637adee95070d68039 100644
--- a/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/JwtUtils.java
+++ b/zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/util/JwtUtils.java
@@ -4,15 +4,22 @@ import com.central.common.constant.SecurityConstants;
import com.central.common.utils.JsonUtil;
import com.central.common.utils.RsaUtils;
import com.fasterxml.jackson.databind.JsonNode;
+import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
+import org.springframework.security.jwt.crypto.sign.RsaSigner;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.security.jwt.crypto.sign.SignatureVerifier;
+import org.springframework.security.jwt.crypto.sign.Signer;
+import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.stream.Collectors;
@@ -84,4 +91,18 @@ public class JwtUtils {
public static boolean checkExp(JsonNode claims) {
return checkExp(claims, System.currentTimeMillis());
}
+
+ public static Jwt encode(CharSequence content, KeyProperties keyProperties) {
+ KeyPair keyPair = new KeyStoreKeyFactory(
+ keyProperties.getKeyStore().getLocation(),
+ keyProperties.getKeyStore().getSecret().toCharArray())
+ .getKeyPair(keyProperties.getKeyStore().getAlias());
+ PrivateKey privateKey = keyPair.getPrivate();
+ Signer rsaSigner = new RsaSigner((RSAPrivateKey) privateKey);
+ return JwtHelper.encode(content, rsaSigner);
+ }
+
+ public static String encodeStr(CharSequence content, KeyProperties keyProperties) {
+ return encode(content, keyProperties).getEncoded();
+ }
}
diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java
index 6900d2aa40431f7aa6f77fa04c59d3dcbac295e6..0152632680d29d8f010450964b967d24413389ae 100644
--- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java
+++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/constant/SecurityConstants.java
@@ -158,4 +158,13 @@ public interface SecurityConstants {
* rsa公钥
*/
String RSA_PUBLIC_KEY = "pubkey.txt";
+ /**
+ * 获取id_token的response_type
+ */
+ String ID_TOKEN = "id_token";
+
+ /**
+ * 令牌颁发者
+ */
+ String ISS = "http://zlt2000.cn";
}
diff --git a/zlt-doc/sql/oauth-center.sql b/zlt-doc/sql/oauth-center.sql
index a7dcb74b773cb183fdec95df47208cb7103ed9d8..4a947608a73575c6598b5876a87bc5c69d0f6ac6 100644
--- a/zlt-doc/sql/oauth-center.sql
+++ b/zlt-doc/sql/oauth-center.sql
@@ -22,6 +22,8 @@ CREATE TABLE `oauth_client_details` (
`create_time` datetime(0) NULL DEFAULT NULL,
`update_time` datetime(0) NULL DEFAULT NULL,
`client_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '应用名称',
+ `support_id_token` tinyint(1) DEFAULT 1 COMMENT '是否支持id_token',
+ `id_token_validity` int(11) COMMENT 'id_token有效期',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
diff --git "a/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v4.5.0.sql" "b/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v4.5.0.sql"
new file mode 100644
index 0000000000000000000000000000000000000000..9deec5251b4af38dff90899131ce8a3e6ba2553f
--- /dev/null
+++ "b/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v4.5.0.sql"
@@ -0,0 +1,4 @@
+------------更新语句
+Use `oauth-center`;
+alter table oauth_client_details add support_id_token tinyint(1) DEFAULT 1 COMMENT '是否支持id_token';
+alter table oauth_client_details add id_token_validity int(11) DEFAULT 60 COMMENT 'id_token有效期';
\ No newline at end of file
diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java
index a32c0af43dc39e9fe89760ed0fa13ce74571af25..41306120bc205d5d352cb1f08c57dc80897123f6 100644
--- a/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java
+++ b/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java
@@ -1,22 +1,38 @@
package com.central.oauth.config;
+import com.central.common.constant.SecurityConstants;
+import com.central.common.model.SysUser;
+import com.central.oauth.model.Client;
+import com.central.oauth.service.IClientService;
import com.central.oauth.service.impl.RedisClientDetailsService;
+import com.central.oauth.utils.OidcIdTokenBuilder;
+import com.central.oauth2.common.constants.IdTokenClaimNames;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.TokenGranter;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
+import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
/**
* OAuth2 授权服务器配置
@@ -55,6 +71,9 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
@Autowired
private TokenGranter tokenGranter;
+ @Value("${zlt.oauth2.token.store.type:'redis'}")
+ private String tokenStoreType;
+
/**
* 配置身份认证器,配置认证方式,TokenStore,TokenGranter,OAuth2RequestFactory
* @param endpoints
@@ -93,4 +112,59 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
//让/oauth/token支持client_id以及client_secret作登录认证
.allowFormAuthenticationForClients();
}
+
+ @Bean
+ @Order(1)
+ public TokenEnhancer tokenEnhancer(@Autowired(required = false) KeyProperties keyProperties
+ , IClientService clientService) {
+ return (accessToken, authentication) -> {
+ Set
+ * Blog: https://zlt2000.gitee.io
+ * Github: https://github.com/zlt2000
+ */
+@Getter
+public class OidcIdTokenBuilder {
+ private final Map