MaxKey 3 jaren geleden
bovenliggende
commit
120f8b3d8e
79 gewijzigde bestanden met toevoegingen van 1981 en 1486 verwijderingen
  1. 17 0
      maxkey-authentications/maxkey-authentication-otp/src/main/java/org/maxkey/password/onetimepwd/OtpAuthnService.java
  2. 17 0
      maxkey-authentications/maxkey-authentication-social/src/main/java/me/zhyd/oauth/request/AuthHuaweiWeLinkRequest.java
  3. 17 0
      maxkey-authentications/maxkey-authentication-social/src/main/java/me/zhyd/oauth/request/WeLinkAuthDefaultSource.java
  4. 10 0
      maxkey-common/src/main/java/org/maxkey/crypto/jose/keystore/JWKSetKeyStore.java
  5. 23 1
      maxkey-common/src/main/java/org/maxkey/crypto/jwt/encryption/service/impl/DefaultJwtEncryptionAndDecryptionService.java
  6. 78 0
      maxkey-common/src/test/java/org/maxkey/crypto/signature/RSAKeyTest.java
  7. 6 6
      maxkey-core/src/main/java/org/maxkey/entity/Accounts.java
  8. 17 0
      maxkey-core/src/main/java/org/maxkey/entity/EmailSenders.java
  9. 0 12
      maxkey-core/src/main/java/org/maxkey/entity/apps/Apps.java
  10. 10 0
      maxkey-core/src/main/java/org/maxkey/entity/apps/AppsCasDetails.java
  11. 89 12
      maxkey-core/src/main/java/org/maxkey/entity/apps/AppsJwtDetails.java
  12. 149 108
      maxkey-core/src/main/java/org/maxkey/entity/apps/AppsOAuth20Details.java
  13. 11 7
      maxkey-core/src/main/java/org/maxkey/entity/apps/oauth2/provider/ClientDetails.java
  14. 109 80
      maxkey-core/src/main/java/org/maxkey/entity/apps/oauth2/provider/client/BaseClientDetails.java
  15. 17 18
      maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/endpoint/AuthorizeBaseEndpoint.java
  16. 2 0
      maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/endpoint/AuthorizeCredentialEndpoint.java
  17. 78 18
      maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/endpoint/adapter/AbstractAuthorizeAdapter.java
  18. 2 2
      maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/Cas10AuthorizeEndpoint.java
  19. 33 13
      maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/Cas20AuthorizeEndpoint.java
  20. 31 13
      maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/Cas30AuthorizeEndpoint.java
  21. 6 6
      maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/CasAuthorizeEndpoint.java
  22. 19 7
      maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/adapter/CasDefaultAdapter.java
  23. 8 4
      maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/st/RedisTicketServices.java
  24. 13 43
      maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/ExtendApiAuthorizeEndpoint.java
  25. 6 5
      maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiCndnsApiMailAdapter.java
  26. 6 12
      maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiQQExmailAdapter.java
  27. 6 5
      maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiTimestampSignAdapter.java
  28. 6 5
      maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiZentaoAdapter.java
  29. 18 17
      maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/FormBasedAuthorizeEndpoint.java
  30. 8 15
      maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedDefaultAdapter.java
  31. 6 13
      maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedNetease163EmailAdapter.java
  32. 4 23
      maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedNeteaseNoteYoudaoAdapter.java
  33. 6 13
      maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedRedirectAdapter.java
  34. 125 55
      maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/jwt/endpoint/adapter/JwtAdapter.java
  35. 0 115
      maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/jwt/endpoint/adapter/JwtDefaultAdapter.java
  36. 0 124
      maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/jwt/endpoint/adapter/JwtHS256Adapter.java
  37. 26 33
      maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/token/endpoint/JwtAuthorizeEndpoint.java
  38. 1 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/ClientDetailsService.java
  39. 1 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java
  40. 1 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/TokenStoreUserApprovalHandler.java
  41. 1 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/endpoint/OAuth20AccessConfirmationEndpoint.java
  42. 1 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/endpoint/OAuth20UserApprovalHandler.java
  43. 1 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/ClientDetailsUserDetailsService.java
  44. 25 18
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/JdbcClientDetailsService.java
  45. 2 2
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AuthorizationEndpoint.java
  46. 1 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/TokenEndpoint.java
  47. 2 2
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/request/DefaultOAuth2RequestFactory.java
  48. 1 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/AbstractTokenGranter.java
  49. 4 4
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/DefaultTokenServices.java
  50. 27 14
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/userinfo/endpoint/OAuthDefaultUserInfoAdapter.java
  51. 21 40
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/userinfo/endpoint/UserInfoEndpoint.java
  52. 106 101
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/userinfo/endpoint/UserInfoOIDCEndpoint.java
  53. 91 89
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oidc/idtoken/OIDCIdTokenEnhancer.java
  54. 0 4
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/autoconfigure/Oauth20AutoConfiguration.java
  55. 14 30
      maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/TokenBasedAuthorizeEndpoint.java
  56. 17 10
      maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/adapter/TokenBasedDefaultAdapter.java
  57. 15 10
      maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/adapter/TokenBasedSimpleAdapter.java
  58. 1 1
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/authorize/jwt_sso_submint.ftl
  59. 51 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/ApplicationsController.java
  60. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/BasicDetailsController.java
  61. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/CasDetailsController.java
  62. 0 5
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/JwtDetailsController.java
  63. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/OAuth20DetailsController.java
  64. 18 8
      maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message.properties
  65. 17 8
      maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message_en.properties
  66. 18 9
      maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message_zh_CN.properties
  67. 2 2
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/appAddCommon.ftl
  68. 18 9
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/appCommonHead.ftl
  69. 22 2
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/cas/appAdd.ftl
  70. 23 14
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/cas/appUpdate.ftl
  71. 12 8
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/extendapi/appAdd.ftl
  72. 36 26
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/formbased/appAdd.ftl
  73. 25 9
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/formbased/appUpdate.ftl
  74. 92 16
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/jwt/appAdd.ftl
  75. 101 25
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/jwt/appUpdate.ftl
  76. 113 108
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/oauth20/appAdd.ftl
  77. 118 110
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/oauth20/appUpdate.ftl
  78. 0 2
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/tokenbased/appAdd.ftl
  79. 0 3
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/tokenbased/appUpdate.ftl

+ 17 - 0
maxkey-authentications/maxkey-authentication-otp/src/main/java/org/maxkey/password/onetimepwd/OtpAuthnService.java

@@ -1,3 +1,20 @@
+/*
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
 package org.maxkey.password.onetimepwd;
 
 import java.sql.Types;

+ 17 - 0
maxkey-authentications/maxkey-authentication-social/src/main/java/me/zhyd/oauth/request/AuthHuaweiWeLinkRequest.java

@@ -1,3 +1,20 @@
+/*
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
 package me.zhyd.oauth.request;
 import com.alibaba.fastjson.JSONObject;
 import me.zhyd.oauth.cache.AuthStateCache;

+ 17 - 0
maxkey-authentications/maxkey-authentication-social/src/main/java/me/zhyd/oauth/request/WeLinkAuthDefaultSource.java

@@ -1,3 +1,20 @@
+/*
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
 package me.zhyd.oauth.request;
 
 import me.zhyd.oauth.config.AuthSource;

+ 10 - 0
maxkey-common/src/main/java/org/maxkey/crypto/jose/keystore/JWKSetKeyStore.java

@@ -47,6 +47,16 @@ public class JWKSetKeyStore {
         this.jwkSet = jwkSet;
         initializeJwkSet();
     }
+    
+    public JWKSetKeyStore(String  jwkSetJsonString) {
+        try {
+			this.jwkSet = JWKSet.parse(jwkSetJsonString);
+		} catch (ParseException e) {
+			_logger.error("ParseException", e);
+		}
+        initializeJwkSet();
+    }
+    
 
     private void initializeJwkSet() {
 

+ 23 - 1
maxkey-common/src/main/java/org/maxkey/crypto/jwt/encryption/service/impl/DefaultJwtEncryptionAndDecryptionService.java

@@ -159,6 +159,10 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
 		return defaultAlgorithm;
 	}
 
+	public void setDefaultAlgorithm(String algorithm) {
+		defaultAlgorithm = JWEAlgorithm.parse(algorithm);
+	}
+	
 	public void setDefaultAlgorithm(JWEAlgorithm defaultAlgorithm) {
 		this.defaultAlgorithm = defaultAlgorithm;
 	}
@@ -297,5 +301,23 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
 		return encs;
 	}
 
-
+	public EncryptionMethod parseEncryptionMethod(String encryptionMethodName) {
+		EncryptionMethod encryptionMethod = null;
+		if(encryptionMethodName.equalsIgnoreCase("A128GCM")) {
+			encryptionMethod = EncryptionMethod.A128GCM;
+		}else if(encryptionMethodName.equalsIgnoreCase("A192GCM")) {
+			encryptionMethod = EncryptionMethod.A192GCM;
+		}else if(encryptionMethodName.equalsIgnoreCase("A256GCM")) {
+			encryptionMethod = EncryptionMethod.A256GCM;
+		}else if(encryptionMethodName.equalsIgnoreCase("A128CBC_HS256")) {
+			encryptionMethod = EncryptionMethod.A128CBC_HS256;
+		}else if(encryptionMethodName.equalsIgnoreCase("A192CBC_HS384")) {
+			encryptionMethod = EncryptionMethod.A192CBC_HS384;
+		}else if(encryptionMethodName.equalsIgnoreCase("A256CBC_HS512")) {
+			encryptionMethod = EncryptionMethod.A256CBC_HS512;
+		}else if(encryptionMethodName.equalsIgnoreCase("XC20P")) {
+			encryptionMethod = EncryptionMethod.XC20P;
+		}
+		return encryptionMethod;
+	}
 }

+ 78 - 0
maxkey-common/src/test/java/org/maxkey/crypto/signature/RSAKeyTest.java

@@ -0,0 +1,78 @@
+/*
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.maxkey.crypto.signature;
+
+import java.security.SecureRandom;
+
+import org.maxkey.crypto.Base64Utils;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSObject;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.Payload;
+import com.nimbusds.jose.crypto.MACSigner;
+import com.nimbusds.jose.jwk.KeyUse;
+import com.nimbusds.jose.jwk.OctetSequenceKey;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.jose.jwk.gen.OctetSequenceKeyGenerator;
+import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
+
+public class RSAKeyTest {
+
+	public static void main(String[] args) throws JOSEException {
+		// RSA signatures require a public and private RSA key pair, the public key 
+		// must be made known to the JWS recipient in order to verify the signatures
+		RSAKey rsaJWK = new RSAKeyGenerator(2048)
+		    .keyID("123")
+		    .keyUse(KeyUse.SIGNATURE)
+		    .algorithm(JWSAlgorithm.RS256)
+		    .generate();
+		RSAKey rsaPublicJWK = rsaJWK.toPublicJWK();
+		System.out.println(rsaPublicJWK.toJSONString());
+		
+		System.out.println(rsaJWK.toJSONString());
+		
+		byte[] sharedKey = new byte[32];
+		new SecureRandom().nextBytes(sharedKey);
+		System.out.println(Base64Utils.encoder(sharedKey));
+		
+		
+		OctetSequenceKey octKey=  new OctetSequenceKeyGenerator(2048)
+				.keyID("123")
+				.keyUse(KeyUse.SIGNATURE)
+				.algorithm(JWSAlgorithm.HS256)
+				.generate();
+		System.out.println(octKey.toJSONString());
+		
+		// Create HMAC signer
+		JWSSigner signer = new MACSigner(octKey);
+
+		// Prepare JWS object with "Hello, world!" payload
+		JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256), new Payload("Hello, world!"));
+
+		// Apply the HMAC
+		jwsObject.sign(signer);
+		String s = jwsObject.serialize();
+		System.out.println(s);
+		
+		System.out.print("A128KW".substring(1, 4));
+	}
+
+}

+ 6 - 6
maxkey-core/src/main/java/org/maxkey/entity/Accounts.java

@@ -87,13 +87,13 @@ public class Accounts extends JpaBaseEntity implements Serializable {
         this.id = id;
     }
 
-    public Accounts(String uid, String appId) {
-        this.userId = uid;
+    public Accounts(String userId, String appId) {
+        this.userId = userId;
         this.appId = appId;
     }
 
-    public Accounts(String uid, String appId, String password) {
-        this.userId = uid;
+    public Accounts(String userId, String appId, String password) {
+        this.userId = userId;
         this.appId = appId;
         this.relatedPassword = password;
     }
@@ -102,8 +102,8 @@ public class Accounts extends JpaBaseEntity implements Serializable {
         return userId;
     }
 
-    public void setUserId(String uid) {
-        this.userId = uid;
+    public void setUserId(String userId) {
+        this.userId = userId;
     }
 
     public String getUsername() {

+ 17 - 0
maxkey-core/src/main/java/org/maxkey/entity/EmailSenders.java

@@ -1,3 +1,20 @@
+/*
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
 package org.maxkey.entity;
 
 import javax.persistence.Column;

+ 0 - 12
maxkey-core/src/main/java/org/maxkey/entity/apps/Apps.java

@@ -28,7 +28,6 @@ import javax.persistence.Table;
 
 import org.apache.mybatis.jpa.persistence.JpaBaseEntity;
 import org.maxkey.constants.ConstsBoolean;
-import org.maxkey.entity.Accounts;
 import org.springframework.web.multipart.MultipartFile;
 
 @Entity
@@ -141,7 +140,6 @@ public class Apps extends JpaBaseEntity implements Serializable {
     @Column
     private String adapter;
 
-    protected Accounts appUser;
     @Column
     protected int sortIndex;
 
@@ -464,14 +462,6 @@ public class Apps extends JpaBaseEntity implements Serializable {
         this.adapter = adapter;
     }
 
-    public Accounts getAppUser() {
-        return appUser;
-    }
-
-    public void setAppUser(Accounts appUser) {
-        this.appUser = appUser;
-    }
-
     public String getPrincipal() {
         return principal;
     }
@@ -659,8 +649,6 @@ public class Apps extends JpaBaseEntity implements Serializable {
 		builder.append(adapterName);
 		builder.append(", adapter=");
 		builder.append(adapter);
-		builder.append(", appUser=");
-		builder.append(appUser);
 		builder.append(", sortIndex=");
 		builder.append(sortIndex);
 		builder.append(", status=");

+ 10 - 0
maxkey-core/src/main/java/org/maxkey/entity/apps/AppsCasDetails.java

@@ -44,6 +44,8 @@ public class AppsCasDetails extends Apps {
     private String callbackUrl;
 	@Column
 	private String instId;
+	@Column
+	private String casUser;
 
 	private String instName;
 
@@ -79,6 +81,14 @@ public class AppsCasDetails extends Apps {
 		this.expires = expires;
 	}
 
+	public String getCasUser() {
+		return casUser;
+	}
+
+	public void setCasUser(String casUser) {
+		this.casUser = casUser;
+	}
+
 	public String getInstId() {
 		return instId;
 	}

+ 89 - 12
maxkey-core/src/main/java/org/maxkey/entity/apps/AppsJwtDetails.java

@@ -44,6 +44,15 @@ public class AppsJwtDetails  extends Apps {
 	@Column
 	@GeneratedValue(strategy=GenerationType.AUTO,generator="snowflakeid")
 	protected String id;
+	
+	@Column
+	private String subject;
+	
+	@Column
+	private String issuer;
+	
+	@Column
+	private String audience;
 	/**
 	 * 
 	 */
@@ -53,12 +62,18 @@ public class AppsJwtDetails  extends Apps {
 	@Column
 	private String tokenType;
 	@Column
-	private String cookieName;
+	private String jwtName;
 	@Column
 	private String algorithm;
 	@Column
 	private String algorithmKey;
 	@Column
+	private String encryptionMethod;
+	@Column
+	private String signature;
+	@Column
+	private String signatureKey;
+	@Column
 	private String expires;
 	@Column
 	private String instId;
@@ -80,7 +95,37 @@ public class AppsJwtDetails  extends Apps {
     }
 
 
-    public String getRedirectUri() {
+    public String getSubject() {
+		return subject;
+	}
+
+
+	public void setSubject(String subject) {
+		this.subject = subject;
+	}
+
+
+	public String getIssuer() {
+		return issuer;
+	}
+
+
+	public void setIssuer(String issuer) {
+		this.issuer = issuer;
+	}
+
+
+	public String getAudience() {
+		return audience;
+	}
+
+
+	public void setAudience(String audience) {
+		this.audience = audience;
+	}
+
+
+	public String getRedirectUri() {
         return redirectUri;
     }
 
@@ -100,17 +145,19 @@ public class AppsJwtDetails  extends Apps {
     }
 
 
-    public String getCookieName() {
-        return cookieName;
-    }
 
 
-    public void setCookieName(String cookieName) {
-        this.cookieName = cookieName;
-    }
+    public String getJwtName() {
+		return jwtName;
+	}
+
+
+	public void setJwtName(String jwtName) {
+		this.jwtName = jwtName;
+	}
 
 
-    public String getAlgorithm() {
+	public String getAlgorithm() {
         return algorithm;
     }
 
@@ -130,7 +177,37 @@ public class AppsJwtDetails  extends Apps {
     }
 
 
-    public String getExpires() {
+    public String getEncryptionMethod() {
+		return encryptionMethod;
+	}
+
+
+	public void setEncryptionMethod(String encryptionMethod) {
+		this.encryptionMethod = encryptionMethod;
+	}
+
+
+	public String getSignature() {
+		return signature;
+	}
+
+
+	public void setSignature(String signature) {
+		this.signature = signature;
+	}
+
+
+	public String getSignatureKey() {
+		return signatureKey;
+	}
+
+
+	public void setSignatureKey(String signatureKey) {
+		this.signatureKey = signatureKey;
+	}
+
+
+	public String getExpires() {
         return expires;
     }
 
@@ -169,8 +246,8 @@ public class AppsJwtDetails  extends Apps {
 		builder.append(redirectUri);
 		builder.append(", tokenType=");
 		builder.append(tokenType);
-		builder.append(", cookieName=");
-		builder.append(cookieName);
+		builder.append(", jwtName=");
+		builder.append(jwtName);
 		builder.append(", algorithm=");
 		builder.append(algorithm);
 		builder.append(", algorithmKey=");

+ 149 - 108
maxkey-core/src/main/java/org/maxkey/entity/apps/AppsOAuth20Details.java

@@ -53,15 +53,24 @@ public class AppsOAuth20Details extends Apps {
     private String approvalPrompt;
 
     // for OpenID Connect
-    private String idTokenSigningAlgorithm;
-    private String idTokenEncryptedAlgorithm;
-    private String idTokenEncryptionMethod;
 
-    private String userInfoSigningAlgorithm;
-    private String userInfoEncryptedAlgorithm;
-    private String userInfoEncryptionMethod;
-
-    private String jwksUri;
+	private String issuer;
+	
+	private String audience;
+	
+	private String algorithm;
+	
+	private String algorithmKey;
+	
+	private String encryptionMethod;
+	
+	private String signature;
+	
+	private String signatureKey;
+	
+	private String subject;
+	
+	private String userInfoResponse;
     
     private String pkce;
 
@@ -109,19 +118,22 @@ public class AppsOAuth20Details extends Apps {
         this.refreshTokenValiditySeconds = baseClientDetails.getRefreshTokenValiditySeconds();
         this.approvalPrompt = baseClientDetails.isAutoApprove("all") + "";
 
-        this.idTokenEncryptedAlgorithm = baseClientDetails.getIdTokenEncryptedAlgorithm();
-        this.idTokenEncryptionMethod = baseClientDetails.getIdTokenEncryptionMethod();
-        this.idTokenSigningAlgorithm = baseClientDetails.getIdTokenSigningAlgorithm();
-
-        this.userInfoEncryptedAlgorithm = baseClientDetails.getUserInfoEncryptedAlgorithm();
-        this.userInfoEncryptionMethod = baseClientDetails.getUserInfoEncryptionMethod();
-        this.userInfoSigningAlgorithm = baseClientDetails.getUserInfoSigningAlgorithm();
-
-        this.jwksUri = baseClientDetails.getJwksUri();
+        this.audience = baseClientDetails.getAudience();
+        this.issuer = baseClientDetails.getIssuer();
+        
+        this.algorithm = baseClientDetails.getAlgorithm();
+        this.algorithmKey = baseClientDetails.getAlgorithmKey();
+        this.encryptionMethod = baseClientDetails.getEncryptionMethod();
+        
+        this.signature = baseClientDetails.getSignature();
+        this.signatureKey = baseClientDetails.getSignatureKey();
+        
         this.approvalPrompt = baseClientDetails.getApprovalPrompt();
         
         this.pkce = baseClientDetails.getPkce();
         this.instId = baseClientDetails.getInstId();
+        this.subject = baseClientDetails.getSubject();
+        this.userInfoResponse = baseClientDetails.getUserInfoResponse();
         
 
     }
@@ -155,7 +167,23 @@ public class AppsOAuth20Details extends Apps {
         this.approvalPrompt = approvalPrompt;
     }
 
-    /**
+    public String getSubject() {
+		return subject;
+	}
+
+	public void setSubject(String subject) {
+		this.subject = subject;
+	}
+
+	public String getUserInfoResponse() {
+		return userInfoResponse;
+	}
+
+	public void setUserInfoResponse(String userInfoResponse) {
+		this.userInfoResponse = userInfoResponse;
+	}
+
+	/**
      * @param clientId the clientId to set
      */
     public void setClientId(String clientId) {
@@ -274,61 +302,64 @@ public class AppsOAuth20Details extends Apps {
         this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
     }
 
-    public String getIdTokenSigningAlgorithm() {
-        return idTokenSigningAlgorithm;
-    }
+  
+    public String getIssuer() {
+		return issuer;
+	}
 
-    public void setIdTokenSigningAlgorithm(String idTokenSigningAlgorithm) {
-        this.idTokenSigningAlgorithm = idTokenSigningAlgorithm;
-    }
+	public void setIssuer(String issuer) {
+		this.issuer = issuer;
+	}
 
-    public String getIdTokenEncryptedAlgorithm() {
-        return idTokenEncryptedAlgorithm;
-    }
+	public String getAudience() {
+		return audience;
+	}
 
-    public void setIdTokenEncryptedAlgorithm(String idTokenEncryptedAlgorithm) {
-        this.idTokenEncryptedAlgorithm = idTokenEncryptedAlgorithm;
-    }
+	public void setAudience(String audience) {
+		this.audience = audience;
+	}
 
-    public String getIdTokenEncryptionMethod() {
-        return idTokenEncryptionMethod;
-    }
+	public String getAlgorithm() {
+		return algorithm;
+	}
 
-    public void setIdTokenEncryptionMethod(String idTokenEncryptionMethod) {
-        this.idTokenEncryptionMethod = idTokenEncryptionMethod;
-    }
+	public void setAlgorithm(String algorithm) {
+		this.algorithm = algorithm;
+	}
 
-    public String getUserInfoSigningAlgorithm() {
-        return userInfoSigningAlgorithm;
-    }
+	public String getAlgorithmKey() {
+		return algorithmKey;
+	}
 
-    public void setUserInfoSigningAlgorithm(String userInfoSigningAlgorithm) {
-        this.userInfoSigningAlgorithm = userInfoSigningAlgorithm;
-    }
+	public void setAlgorithmKey(String algorithmKey) {
+		this.algorithmKey = algorithmKey;
+	}
 
-    public String getUserInfoEncryptedAlgorithm() {
-        return userInfoEncryptedAlgorithm;
-    }
+	public String getEncryptionMethod() {
+		return encryptionMethod;
+	}
 
-    public void setUserInfoEncryptedAlgorithm(String userInfoEncryptedAlgorithm) {
-        this.userInfoEncryptedAlgorithm = userInfoEncryptedAlgorithm;
-    }
+	public void setEncryptionMethod(String encryptionMethod) {
+		this.encryptionMethod = encryptionMethod;
+	}
 
-    public String getUserInfoEncryptionMethod() {
-        return userInfoEncryptionMethod;
-    }
+	public String getSignature() {
+		return signature;
+	}
 
-    public void setUserInfoEncryptionMethod(String userInfoEncryptionMethod) {
-        this.userInfoEncryptionMethod = userInfoEncryptionMethod;
-    }
+	public void setSignature(String signature) {
+		this.signature = signature;
+	}
+
+	public String getSignatureKey() {
+		return signatureKey;
+	}
+
+	public void setSignatureKey(String signatureKey) {
+		this.signatureKey = signatureKey;
+	}
 
-    public String getJwksUri() {
-        return jwksUri;
-    }
 
-    public void setJwksUri(String jwksUri) {
-        this.jwksUri = jwksUri;
-    }
 
     public String getInstId() {
 		return instId;
@@ -354,15 +385,19 @@ public class AppsOAuth20Details extends Apps {
         baseClientDetails.setClientSecret(this.getClientSecret());
         baseClientDetails.setAutoApproveScopes(baseClientDetails.getScope());
 
-        baseClientDetails.setIdTokenEncryptedAlgorithm(this.getIdTokenEncryptedAlgorithm());
-        baseClientDetails.setIdTokenEncryptionMethod(this.getIdTokenEncryptionMethod());
-        baseClientDetails.setIdTokenSigningAlgorithm(this.getIdTokenSigningAlgorithm());
-
-        baseClientDetails.setUserInfoEncryptedAlgorithm(this.getUserInfoEncryptedAlgorithm());
-        baseClientDetails.setUserInfoEncryptionMethod(this.getUserInfoEncryptionMethod());
-        baseClientDetails.setUserInfoSigningAlgorithm(this.getUserInfoSigningAlgorithm());
-
-        baseClientDetails.setJwksUri(this.getJwksUri());
+        baseClientDetails.setAudience(this.getAudience());
+        baseClientDetails.setIssuer(this.getIssuer());
+        
+        baseClientDetails.setAlgorithm(this.getAlgorithm());
+        baseClientDetails.setAlgorithmKey(this.getAlgorithmKey());
+        baseClientDetails.setEncryptionMethod(this.getEncryptionMethod());
+        
+        baseClientDetails.setSignature(this.getSignature());
+        baseClientDetails.setSignatureKey(this.getSignatureKey());
+        
+        baseClientDetails.setSubject(this.getSubject());
+        baseClientDetails.setUserInfoResponse(this.userInfoResponse);
+        
         baseClientDetails.setApprovalPrompt(this.getApprovalPrompt());
         baseClientDetails.setPkce(this.getPkce());
         baseClientDetails.setProtocol(this.getProtocol());
@@ -371,44 +406,50 @@ public class AppsOAuth20Details extends Apps {
     }
 
     @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append("AppsOAuth20Details [clientId=");
-        builder.append(clientId);
-        builder.append(", clientSecret=");
-        builder.append(clientSecret);
-        builder.append(", scope=");
-        builder.append(scope);
-        builder.append(", resourceIds=");
-        builder.append(resourceIds);
-        builder.append(", authorizedGrantTypes=");
-        builder.append(authorizedGrantTypes);
-        builder.append(", registeredRedirectUris=");
-        builder.append(registeredRedirectUris);
-        builder.append(", authorities=");
-        builder.append(authorities);
-        builder.append(", accessTokenValiditySeconds=");
-        builder.append(accessTokenValiditySeconds);
-        builder.append(", refreshTokenValiditySeconds=");
-        builder.append(refreshTokenValiditySeconds);
-        builder.append(", approvalPrompt=");
-        builder.append(approvalPrompt);
-        builder.append(", idTokenSigningAlgorithm=");
-        builder.append(idTokenSigningAlgorithm);
-        builder.append(", idTokenEncryptedAlgorithm=");
-        builder.append(idTokenEncryptedAlgorithm);
-        builder.append(", idTokenEncryptionMethod=");
-        builder.append(idTokenEncryptionMethod);
-        builder.append(", userInfoSigningAlgorithm=");
-        builder.append(userInfoSigningAlgorithm);
-        builder.append(", userInfoEncryptedAlgorithm=");
-        builder.append(userInfoEncryptedAlgorithm);
-        builder.append(", userInfoEncryptionMethod=");
-        builder.append(userInfoEncryptionMethod);
-        builder.append(", jwksUri=");
-        builder.append(jwksUri);
-        builder.append("]");
-        return builder.toString();
-    }
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("AppsOAuth20Details [clientId=");
+		builder.append(clientId);
+		builder.append(", clientSecret=");
+		builder.append(clientSecret);
+		builder.append(", scope=");
+		builder.append(scope);
+		builder.append(", resourceIds=");
+		builder.append(resourceIds);
+		builder.append(", authorizedGrantTypes=");
+		builder.append(authorizedGrantTypes);
+		builder.append(", registeredRedirectUris=");
+		builder.append(registeredRedirectUris);
+		builder.append(", authorities=");
+		builder.append(authorities);
+		builder.append(", accessTokenValiditySeconds=");
+		builder.append(accessTokenValiditySeconds);
+		builder.append(", refreshTokenValiditySeconds=");
+		builder.append(refreshTokenValiditySeconds);
+		builder.append(", approvalPrompt=");
+		builder.append(approvalPrompt);
+		builder.append(", issuer=");
+		builder.append(issuer);
+		builder.append(", audience=");
+		builder.append(audience);
+		builder.append(", algorithm=");
+		builder.append(algorithm);
+		builder.append(", algorithmKey=");
+		builder.append(algorithmKey);
+		builder.append(", encryptionMethod=");
+		builder.append(encryptionMethod);
+		builder.append(", signature=");
+		builder.append(signature);
+		builder.append(", signatureKey=");
+		builder.append(signatureKey);
+		builder.append(", pkce=");
+		builder.append(pkce);
+		builder.append(", instId=");
+		builder.append(instId);
+		builder.append(", instName=");
+		builder.append(instName);
+		builder.append("]");
+		return builder.toString();
+	}
 
 }

+ 11 - 7
maxkey-core/src/main/java/org/maxkey/entity/apps/oauth2/provider/ClientDetails.java

@@ -132,22 +132,26 @@ public interface ClientDetails extends Serializable {
 	/*
 	 * for OpenID Connect
 	 */
-	public String getIdTokenEncryptedAlgorithm() ;
+	public String getIssuer() ;
 	
-	public String getIdTokenSigningAlgorithm() ;
+	public String getAudience() ;
 	
-	public String getIdTokenEncryptionMethod();
+	public String getAlgorithm();
 	
-	public String getUserInfoSigningAlgorithm();
+	public String getAlgorithmKey();
 	
-	public String getUserInfoEncryptedAlgorithm();
+	public String getEncryptionMethod();
 	
-	public String getUserInfoEncryptionMethod();
+	public String getSignature();
 	
-	public String getJwksUri();
+	public String getSignatureKey();
 	
 	public String getApprovalPrompt();
 	
+	public String getSubject();
+	
+	public String getUserInfoResponse();
+	
 	public String getPkce();
 	
 	public String getProtocol();

+ 109 - 80
maxkey-core/src/main/java/org/maxkey/entity/apps/oauth2/provider/client/BaseClientDetails.java

@@ -82,15 +82,24 @@ public class BaseClientDetails implements ClientDetails {
 	private Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();
 
 	//for OpenID Connect
-	private String idTokenSigningAlgorithm;
-	private String idTokenEncryptedAlgorithm;
-	private String idTokenEncryptionMethod;
 
-	private String userInfoSigningAlgorithm;
-	private String userInfoEncryptedAlgorithm;
-	private String userInfoEncryptionMethod;
+	private String issuer;
 	
-	private String jwksUri;
+	private String audience;
+	
+	private String algorithm;
+	
+	private String algorithmKey;
+	
+	private String encryptionMethod;
+	
+	private String signature;
+	
+	private String signatureKey;
+	
+	private String subject;
+	
+	private String userInfoResponse;
 	
 	private String approvalPrompt;
 	
@@ -310,65 +319,79 @@ public class BaseClientDetails implements ClientDetails {
 		this.additionalInformation.put(key, value);
 	}
 	
-	
-
-	public String getIdTokenEncryptedAlgorithm() {
-		return idTokenEncryptedAlgorithm;
+	public String getIssuer() {
+		return issuer;
 	}
 
-	public void setIdTokenEncryptedAlgorithm(String idTokenEncryptedAlgorithm) {
-		this.idTokenEncryptedAlgorithm = idTokenEncryptedAlgorithm;
+	public void setIssuer(String issuer) {
+		this.issuer = issuer;
 	}
 
-	public String getIdTokenSigningAlgorithm() {
-		return idTokenSigningAlgorithm;
+	public String getAudience() {
+		return audience;
 	}
 
-	public void setIdTokenSigningAlgorithm(String idTokenSigningAlgorithm) {
-		this.idTokenSigningAlgorithm = idTokenSigningAlgorithm;
+	public void setAudience(String audience) {
+		this.audience = audience;
 	}
 
-	public String getIdTokenEncryptionMethod() {
-		return idTokenEncryptionMethod;
+	public String getAlgorithm() {
+		return algorithm;
 	}
 
-	public void setIdTokenEncryptionMethod(String idTokenEncryptionMethod) {
-		this.idTokenEncryptionMethod = idTokenEncryptionMethod;
+	public void setAlgorithm(String algorithm) {
+		this.algorithm = algorithm;
 	}
 
-	public String getUserInfoSigningAlgorithm() {
-		return userInfoSigningAlgorithm;
+	public String getAlgorithmKey() {
+		return algorithmKey;
 	}
 
-	public void setUserInfoSigningAlgorithm(String userInfoSigningAlgorithm) {
-		this.userInfoSigningAlgorithm = userInfoSigningAlgorithm;
+	public void setAlgorithmKey(String algorithmKey) {
+		this.algorithmKey = algorithmKey;
 	}
 
-	public String getUserInfoEncryptedAlgorithm() {
-		return userInfoEncryptedAlgorithm;
+	public String getEncryptionMethod() {
+		return encryptionMethod;
 	}
 
-	public void setUserInfoEncryptedAlgorithm(String userInfoEncryptedAlgorithm) {
-		this.userInfoEncryptedAlgorithm = userInfoEncryptedAlgorithm;
+	public void setEncryptionMethod(String encryptionMethod) {
+		this.encryptionMethod = encryptionMethod;
 	}
 
-	public String getUserInfoEncryptionMethod() {
-		return userInfoEncryptionMethod;
+	public String getSignature() {
+		return signature;
 	}
 
-	public void setUserInfoEncryptionMethod(String userInfoEncryptionMethod) {
-		this.userInfoEncryptionMethod = userInfoEncryptionMethod;
+	public void setSignature(String signature) {
+		this.signature = signature;
 	}
 
-	public String getJwksUri() {
-		return jwksUri;
+	public String getSignatureKey() {
+		return signatureKey;
 	}
 
-	public void setJwksUri(String jwksUri) {
-		this.jwksUri = jwksUri;
+	public void setSignatureKey(String signatureKey) {
+		this.signatureKey = signatureKey;
 	}
 
 	
+	public String getSubject() {
+		return subject;
+	}
+
+	public void setSubject(String subject) {
+		this.subject = subject;
+	}
+
+	public String getUserInfoResponse() {
+		return userInfoResponse;
+	}
+
+	public void setUserInfoResponse(String userInfoResponse) {
+		this.userInfoResponse = userInfoResponse;
+	}
+
 	public String getApprovalPrompt() {
         return approvalPrompt;
     }
@@ -492,49 +515,55 @@ public class BaseClientDetails implements ClientDetails {
 	}
 
 	@Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append("BaseClientDetails [clientId=");
-        builder.append(clientId);
-        builder.append(", clientSecret=");
-        builder.append(clientSecret);
-        builder.append(", scope=");
-        builder.append(scope);
-        builder.append(", resourceIds=");
-        builder.append(resourceIds);
-        builder.append(", authorizedGrantTypes=");
-        builder.append(authorizedGrantTypes);
-        builder.append(", registeredRedirectUris=");
-        builder.append(registeredRedirectUris);
-        builder.append(", autoApproveScopes=");
-        builder.append(autoApproveScopes);
-        builder.append(", authorities=");
-        builder.append(authorities);
-        builder.append(", accessTokenValiditySeconds=");
-        builder.append(accessTokenValiditySeconds);
-        builder.append(", refreshTokenValiditySeconds=");
-        builder.append(refreshTokenValiditySeconds);
-        builder.append(", additionalInformation=");
-        builder.append(additionalInformation);
-        builder.append(", idTokenSigningAlgorithm=");
-        builder.append(idTokenSigningAlgorithm);
-        builder.append(", idTokenEncryptedAlgorithm=");
-        builder.append(idTokenEncryptedAlgorithm);
-        builder.append(", idTokenEncryptionMethod=");
-        builder.append(idTokenEncryptionMethod);
-        builder.append(", userInfoSigningAlgorithm=");
-        builder.append(userInfoSigningAlgorithm);
-        builder.append(", userInfoEncryptedAlgorithm=");
-        builder.append(userInfoEncryptedAlgorithm);
-        builder.append(", userInfoEncryptionMethod=");
-        builder.append(userInfoEncryptionMethod);
-        builder.append(", jwksUri=");
-        builder.append(jwksUri);
-        builder.append(", approvalPrompt=");
-        builder.append(approvalPrompt);
-        builder.append("]");
-        return builder.toString();
-    }
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("BaseClientDetails [clientId=");
+		builder.append(clientId);
+		builder.append(", clientSecret=");
+		builder.append(clientSecret);
+		builder.append(", scope=");
+		builder.append(scope);
+		builder.append(", resourceIds=");
+		builder.append(resourceIds);
+		builder.append(", authorizedGrantTypes=");
+		builder.append(authorizedGrantTypes);
+		builder.append(", registeredRedirectUris=");
+		builder.append(registeredRedirectUris);
+		builder.append(", autoApproveScopes=");
+		builder.append(autoApproveScopes);
+		builder.append(", authorities=");
+		builder.append(authorities);
+		builder.append(", accessTokenValiditySeconds=");
+		builder.append(accessTokenValiditySeconds);
+		builder.append(", refreshTokenValiditySeconds=");
+		builder.append(refreshTokenValiditySeconds);
+		builder.append(", additionalInformation=");
+		builder.append(additionalInformation);
+		builder.append(", issuer=");
+		builder.append(issuer);
+		builder.append(", audience=");
+		builder.append(audience);
+		builder.append(", algorithm=");
+		builder.append(algorithm);
+		builder.append(", algorithmKey=");
+		builder.append(algorithmKey);
+		builder.append(", encryptionMethod=");
+		builder.append(encryptionMethod);
+		builder.append(", signature=");
+		builder.append(signature);
+		builder.append(", signatureKey=");
+		builder.append(signatureKey);
+		builder.append(", approvalPrompt=");
+		builder.append(approvalPrompt);
+		builder.append(", pkce=");
+		builder.append(pkce);
+		builder.append(", protocol=");
+		builder.append(protocol);
+		builder.append(", instId=");
+		builder.append(instId);
+		builder.append("]");
+		return builder.toString();
+	}
 
 
 

+ 17 - 18
maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/endpoint/AuthorizeBaseEndpoint.java

@@ -21,6 +21,7 @@
 package org.maxkey.authz.endpoint;
 
 import org.apache.commons.lang3.StringUtils;
+import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.configuration.ApplicationConfig;
 import org.maxkey.crypto.password.PasswordReciprocal;
 import org.maxkey.entity.Accounts;
@@ -73,34 +74,30 @@ public class AuthorizeBaseEndpoint {
 	}
 	
 	protected Accounts getAccounts(Apps app){
-		Accounts account=new Accounts();
-		UserInfo userInfo=WebContext.getUserInfo();
+		UserInfo userInfo = WebContext.getUserInfo();
 		Apps  loadApp = getApp(app.getId());
+		
+		Accounts account = new Accounts(userInfo.getId(),loadApp.getId());
+		account.setUsername(userInfo.getUsername());
+		account.setAppName(app.getName());
+		
 		if(loadApp.getCredential() == Apps.CREDENTIALS.USER_DEFINED){
 			account = accountsService.load(new Accounts(userInfo.getId(),loadApp.getId()));
 			if(account != null){
-				account.setRelatedPassword(PasswordReciprocal.getInstance().decoder(account.getRelatedPassword()));
+				account.setRelatedPassword(
+						PasswordReciprocal.getInstance().decoder(account.getRelatedPassword()));
 			}
 			
 		}else if(loadApp.getCredential() == Apps.CREDENTIALS.SHARED){
 			account.setRelatedUsername(loadApp.getSharedUsername());
 			account.setRelatedPassword(PasswordReciprocal.getInstance().decoder(loadApp.getSharedPassword()));	
-		
 		}else if(loadApp.getCredential() == Apps.CREDENTIALS.SYSTEM){
-			if(loadApp.getSystemUserAttr().equalsIgnoreCase("userId")){
-				account.setUsername(userInfo.getId());
-			}else if(loadApp.getSystemUserAttr().equalsIgnoreCase("username")){
-				account.setUsername(userInfo.getUsername());
-			}else if(loadApp.getSystemUserAttr().equalsIgnoreCase("employeeNumber")){
-				account.setUsername(userInfo.getEmployeeNumber());
-			}else if(loadApp.getSystemUserAttr().equalsIgnoreCase("email")){
-				account.setUsername(userInfo.getEmail());
-			}else if(loadApp.getSystemUserAttr().equalsIgnoreCase("windowsAccount")){
-				account.setUsername(userInfo.getWindowsAccount());
-			}
+			account.setUsername(
+					AbstractAuthorizeAdapter.getValueByUserAttr(userInfo, loadApp.getSystemUserAttr())
+			);
 			//decoder database stored encode password
-			account.setRelatedPassword(PasswordReciprocal.getInstance().decoder(WebContext.getUserInfo().getDecipherable()));
-			
+			account.setRelatedPassword(
+					PasswordReciprocal.getInstance().decoder(WebContext.getUserInfo().getDecipherable()));
 		}else if(loadApp.getCredential()==Apps.CREDENTIALS.NONE){
 			account.setUsername(userInfo.getUsername());
 			account.setRelatedPassword(userInfo.getUsername());
@@ -110,8 +107,10 @@ public class AuthorizeBaseEndpoint {
 	}
 	
 	public ModelAndView generateInitCredentialModelAndView(String appId,String redirect_uri){
-		ModelAndView modelAndView=new ModelAndView("redirect:/authz/credential/forward?appId="+appId+"&redirect_uri="+redirect_uri);
+		ModelAndView modelAndView = 
+				new ModelAndView(String.format(InitCredentialURL,appId, redirect_uri));
 		return modelAndView;
 	}
 	
+	public static String InitCredentialURL = "redirect:/authz/credential/forward?appId=%s&redirect_uri=%s";
 }

+ 2 - 0
maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/endpoint/AuthorizeCredentialEndpoint.java

@@ -77,6 +77,8 @@ public class AuthorizeCredentialEndpoint extends AuthorizeBaseEndpoint{
 			appUser.setRelatedUsername(identity_username);
 			appUser.setRelatedPassword(PasswordReciprocal.getInstance().encode(identity_password));
 			
+			appUser.setInstId(WebContext.getUserInfo().getInstId());
+			
 			if(accountsService.insert(appUser)){
 				
 			}

+ 78 - 18
maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/endpoint/adapter/AbstractAuthorizeAdapter.java

@@ -19,6 +19,7 @@ package org.maxkey.authz.endpoint.adapter;
 
 import java.io.UnsupportedEncodingException;
 import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang3.StringUtils;
 import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.constants.ConstsBoolean;
 import org.maxkey.crypto.Base64Utils;
@@ -26,6 +27,7 @@ import org.maxkey.crypto.ReciprocalUtils;
 import org.maxkey.crypto.cert.CertSigner;
 import org.maxkey.crypto.keystore.KeyStoreLoader;
 import org.maxkey.crypto.password.PasswordReciprocal;
+import org.maxkey.entity.Accounts;
 import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.Apps;
 import org.maxkey.web.WebContext;
@@ -36,51 +38,109 @@ import org.springframework.web.servlet.ModelAndView;
 public abstract class AbstractAuthorizeAdapter {
 	final static Logger _logger = LoggerFactory.getLogger(AbstractAuthorizeAdapter.class);
 	
-	public  PasswordReciprocal passwordReciprocal=PasswordReciprocal.getInstance();
+	protected Apps app;
 	
-	public abstract ModelAndView authorize(UserInfo userInfo,Object app,String data,ModelAndView modelAndView);
+	protected UserInfo userInfo;
 	
-	public abstract String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app);
+	protected Accounts account;
 	
-	public String  sign(String data,Apps app){
+	protected SigninPrincipal authentication;
+	
+	public abstract Object generateInfo();
+	
+	public  ModelAndView authorize(ModelAndView modelAndView) {
+		return modelAndView;
+	}
+	
+	public Object  sign(Object data,String signatureKey,String signature){
 		if(ConstsBoolean.isTrue(app.getIsSignature())){
-			KeyStoreLoader keyStoreLoader=WebContext.getBean("keyStoreLoader",KeyStoreLoader.class);
+			KeyStoreLoader keyStoreLoader = WebContext.getBean("keyStoreLoader",KeyStoreLoader.class);
 			try {	
-				byte[] signature= CertSigner.sign(data.getBytes(), keyStoreLoader.getKeyStore(), keyStoreLoader.getEntityName(), keyStoreLoader.getKeystorePassword());
+				byte[] signData= CertSigner.sign(data.toString().getBytes(), keyStoreLoader.getKeyStore(), keyStoreLoader.getEntityName(), keyStoreLoader.getKeystorePassword());
 				_logger.debug("signed Token : "+data);
-				_logger.debug("signature : "+signature.toString());
-				
+				_logger.debug("signature : "+signData.toString());
 				
-				data=Base64Utils.base64UrlEncode(data.getBytes("UTF-8"))+"."+Base64Utils.base64UrlEncode(signature);
+				return Base64Utils.base64UrlEncode(data.toString().getBytes("UTF-8"))+"."+Base64Utils.base64UrlEncode(signData);
 			} catch (UnsupportedEncodingException e) {
-				e.printStackTrace();
+				_logger.error("UnsupportedEncodingException " , e);
 			} catch (Exception e) {
-				e.printStackTrace();
+				_logger.error("Exception " , e);
 			}
-			_logger.debug("Token : "+data);
+			_logger.debug("Token {}" , data);
 			
 		}else{
 			_logger.debug("data not need sign .");
+			return data;
 		}
 		
-		return data;
+		return null;
 	}
 	
-	public  String encrypt(String data,String algorithmKey,String algorithm){
+	public  Object encrypt(Object data,String algorithmKey,String algorithm){
 		
-		algorithmKey=passwordReciprocal.decoder(algorithmKey);
+		algorithmKey = PasswordReciprocal.getInstance().decoder(algorithmKey);
 		_logger.debug("algorithm : "+algorithm);
 		_logger.debug("algorithmKey : "+algorithmKey);
 		//Chinese , encode data to HEX
 		try {
-			data = new String(Hex.encodeHex(data.getBytes("UTF-8")));
+			data = new String(Hex.encodeHex(data.toString().getBytes("UTF-8")));
 		} catch (UnsupportedEncodingException e) { 
 			e.printStackTrace();
 		}     
-		byte[] encodeData=ReciprocalUtils.encode(data, algorithmKey, algorithm);
-		String tokenString=Base64Utils.base64UrlEncode(encodeData);
+		byte[] encodeData = ReciprocalUtils.encode(data.toString(), algorithmKey, algorithm);
+		String tokenString = Base64Utils.base64UrlEncode(encodeData);
 		_logger.trace("Reciprocal then HEX  Token : "+tokenString);
 		
 		return tokenString;
 	}
+	
+	public static String getValueByUserAttr(UserInfo userInfo,String userAttr) {
+		String value = "";
+		if(StringUtils.isBlank(userAttr)) {
+			value = userInfo.getUsername();
+		}else if(userAttr.equalsIgnoreCase("username")){
+			value = userInfo.getUsername();
+		}else if(userAttr.equalsIgnoreCase("userId")){
+			value = userInfo.getId();
+		}else if(userAttr.equalsIgnoreCase("email")){
+			value = userInfo.getEmail();
+		}else if(userAttr.equalsIgnoreCase("mobile")){
+			value = userInfo.getMobile();
+		}else if(userAttr.equalsIgnoreCase("workEmail")) {
+			value = userInfo.getWorkEmail();
+		}else if(userAttr.equalsIgnoreCase("windowsAccount")){
+			value = userInfo.getWindowsAccount();
+		}else if(userAttr.equalsIgnoreCase("employeeNumber")){
+			value = userInfo.getEmployeeNumber();
+		}else {
+			value = userInfo.getId();
+		}
+		
+		if(StringUtils.isBlank(value)) {
+			value = userInfo.getUsername();
+		}
+		
+		return value;
+	}
+	
+	public  String serialize() {
+		return "";
+	};
+
+	public void setAuthentication(SigninPrincipal authentication) {
+		this.authentication = authentication;
+	}
+
+	public void setUserInfo(UserInfo userInfo) {
+		this.userInfo = userInfo;
+	}
+
+	public void setApp(Apps app) {
+		this.app = app;
+	}
+
+	public void setAccount(Accounts account) {
+		this.account = account;
+	}	
+	
 }

+ 2 - 2
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/Cas10AuthorizeEndpoint.java

@@ -97,14 +97,14 @@ renew [OPTIONAL] - if this parameter is set, ticket validation will only succeed
                 +" , renew " + renew
         );
 	    
-		Ticket storedTicket=null;
+		Ticket storedTicket = null;
 		try {
 			storedTicket = ticketServices.consumeTicket(ticket);
 		} catch (Exception e) {
 			_logger.error("consume Ticket error " , e);
 		}
 		
-		if(storedTicket!=null){
+		if(storedTicket != null){
 			String principal=((SigninPrincipal)storedTicket.getAuthentication().getPrincipal()).getUsername();
 			_logger.debug("principal "+principal);
 			return new Service10ResponseBuilder().success()

+ 33 - 13
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/Cas20AuthorizeEndpoint.java

@@ -20,8 +20,12 @@
  */
 package org.maxkey.authz.cas.endpoint;
 
+import java.lang.reflect.InvocationTargetException;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.beanutils.BeanUtils;
 import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.cas.endpoint.response.ProxyServiceResponseBuilder;
 import org.maxkey.authz.cas.endpoint.response.ServiceResponseBuilder;
@@ -202,9 +206,6 @@ For all error codes, it is RECOMMENDED that CAS provide a more detailed message
 		
 		if(storedTicket!=null){
 		    SigninPrincipal authentication = ((SigninPrincipal)storedTicket.getAuthentication().getPrincipal());
-			String principal=authentication.getUsername();
-			_logger.debug("principal "+principal);
-			serviceResponseBuilder.success().setUser(principal);
 			if(StringUtils.isNotBlank(pgtUrl)) {
 				ProxyGrantingTicketIOUImpl proxyGrantingTicketIOUImpl =new ProxyGrantingTicketIOUImpl();
 				String proxyGrantingTicketIOU=casProxyGrantingTicketServices.createTicket(proxyGrantingTicketIOUImpl);
@@ -219,9 +220,21 @@ For all error codes, it is RECOMMENDED that CAS provide a more detailed message
 			}
 			
 			if(ConstsBoolean.isTrue(storedTicket.getCasDetails().getIsAdapter())){
-				AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)Instance.newInstance(storedTicket.getCasDetails().getAdapter());
-				UserInfo userInfo = (UserInfo) userInfoService.findByUsername(principal);
-				adapter.generateInfo(authentication,userInfo, serviceResponseBuilder);
+				
+				Object samlAdapter = Instance.newInstance(storedTicket.getCasDetails().getAdapter());
+				try {
+					BeanUtils.setProperty(samlAdapter, "serviceResponseBuilder", serviceResponseBuilder);
+				} catch (IllegalAccessException | InvocationTargetException e) {
+					_logger.error("setProperty error . ", e);
+				}
+				
+				UserInfo userInfo = (UserInfo) userInfoService.findByUsername(authentication.getUsername());
+				
+				AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)samlAdapter;
+				adapter.setAuthentication(authentication);
+				adapter.setUserInfo(userInfo);
+				adapter.setApp(storedTicket.getCasDetails());
+				adapter.generateInfo();
 			}
 		}else{
 			serviceResponseBuilder.failure()
@@ -324,14 +337,21 @@ Response on ticket validation failure:
 		
 		if(storedTicket!=null){
 		    SigninPrincipal authentication = ((SigninPrincipal)storedTicket.getAuthentication().getPrincipal());
-			String principal=authentication.getUsername();
-			_logger.debug("principal "+principal);
-			serviceResponseBuilder.success().setUser(principal);
-			
 			if(ConstsBoolean.isTrue(storedTicket.getCasDetails().getIsAdapter())){
-				AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)Instance.newInstance(storedTicket.getCasDetails().getAdapter());
-				UserInfo userInfo = (UserInfo) userInfoService.findByUsername(principal);
-				adapter.generateInfo(authentication,userInfo, serviceResponseBuilder);
+				Object samlAdapter = Instance.newInstance(storedTicket.getCasDetails().getAdapter());
+				try {
+					BeanUtils.setProperty(samlAdapter, "serviceResponseBuilder", serviceResponseBuilder);
+				} catch (IllegalAccessException | InvocationTargetException e) {
+					_logger.error("setProperty error . ", e);
+				}
+				
+				UserInfo userInfo = (UserInfo) userInfoService.findByUsername(authentication.getUsername());
+				
+				AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)samlAdapter;
+				adapter.setAuthentication(authentication);
+				adapter.setUserInfo(userInfo);
+				adapter.setApp(storedTicket.getCasDetails());
+				adapter.generateInfo();
 			}
 		}else{
 			serviceResponseBuilder.failure()

+ 31 - 13
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/Cas30AuthorizeEndpoint.java

@@ -20,9 +20,12 @@
  */
 package org.maxkey.authz.cas.endpoint;
 
+import java.lang.reflect.InvocationTargetException;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.beanutils.BeanUtils;
 import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.cas.endpoint.response.ProxyServiceResponseBuilder;
 import org.maxkey.authz.cas.endpoint.response.ServiceResponseBuilder;
@@ -85,9 +88,6 @@ public class Cas30AuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 		
 		if(storedTicket!=null){
 		    SigninPrincipal authentication = ((SigninPrincipal)storedTicket.getAuthentication().getPrincipal());
-			String principal=authentication.getUsername();
-			_logger.debug("principal "+principal);
-			serviceResponseBuilder.success().setUser(principal);
 			if(StringUtils.isNotBlank(pgtUrl)) {
 				ProxyGrantingTicketIOUImpl proxyGrantingTicketIOUImpl =new ProxyGrantingTicketIOUImpl();
 				String proxyGrantingTicketIOU=casProxyGrantingTicketServices.createTicket(proxyGrantingTicketIOUImpl);
@@ -102,9 +102,20 @@ public class Cas30AuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 			}
 			
 			if(ConstsBoolean.isTrue(storedTicket.getCasDetails().getIsAdapter())){
-				AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)Instance.newInstance(storedTicket.getCasDetails().getAdapter());
-				UserInfo userInfo = (UserInfo) userInfoService.findByUsername(principal);
-				adapter.generateInfo(authentication,userInfo, serviceResponseBuilder);
+				Object samlAdapter = Instance.newInstance(storedTicket.getCasDetails().getAdapter());
+				try {
+					BeanUtils.setProperty(samlAdapter, "serviceResponseBuilder", serviceResponseBuilder);
+				} catch (IllegalAccessException | InvocationTargetException e) {
+					_logger.error("setProperty error . ", e);
+				}
+				
+				UserInfo userInfo = (UserInfo) userInfoService.findByUsername(authentication.getUsername());
+				
+				AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)samlAdapter;
+				adapter.setAuthentication(authentication);
+				adapter.setUserInfo(userInfo);
+				adapter.setApp(storedTicket.getCasDetails());
+				adapter.generateInfo();
 			}
 		}else{
 			serviceResponseBuilder.failure()
@@ -171,14 +182,21 @@ public class Cas30AuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 		
 		if(storedTicket!=null){
 		    SigninPrincipal authentication = ((SigninPrincipal)storedTicket.getAuthentication().getPrincipal());
-			String principal=authentication.getUsername();
-			_logger.debug("principal "+principal);
-			serviceResponseBuilder.success().setUser(principal);
-			
 			if(ConstsBoolean.isTrue(storedTicket.getCasDetails().getIsAdapter())){
-				AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)Instance.newInstance(storedTicket.getCasDetails().getAdapter());
-				UserInfo userInfo = (UserInfo) userInfoService.findByUsername(principal);
-				adapter.generateInfo(authentication,userInfo, serviceResponseBuilder);
+				Object samlAdapter = Instance.newInstance(storedTicket.getCasDetails().getAdapter());
+				try {
+					BeanUtils.setProperty(samlAdapter, "serviceResponseBuilder", serviceResponseBuilder);
+				} catch (IllegalAccessException | InvocationTargetException e) {
+					_logger.error("setProperty error . ", e);
+				}
+				
+				UserInfo userInfo = (UserInfo) userInfoService.findByUsername(authentication.getUsername());
+				
+				AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)samlAdapter;
+				adapter.setAuthentication(authentication);
+				adapter.setUserInfo(userInfo);
+				adapter.setApp(storedTicket.getCasDetails());
+				adapter.generateInfo();
 			}
 		}else{
 			serviceResponseBuilder.failure()

+ 6 - 6
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/CasAuthorizeEndpoint.java

@@ -90,7 +90,7 @@ public class CasAuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 		_logger.debug(""+casDetails);
 		Map<String, String> parameterMap = WebContext.getRequestParameterMap(request);
 		String service = casService;
-		_logger.debug("CAS Parameter service = " + service);
+		_logger.debug("CAS Parameter service = {}" , service);
 		if(casService.indexOf("?") >-1 ) {
 		    service = casService.substring(casService.indexOf("?") + 1);
 		    if(service.indexOf("=") > -1) {
@@ -99,7 +99,7 @@ public class CasAuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 		            parameterMap.put(parameterValues[0], parameterValues[1]);
 		        }
 		    }
-		    _logger.debug("CAS service with Parameter : " + service);
+		    _logger.debug("CAS service with Parameter : {}" , parameterMap);
 		}
 		WebContext.setAttribute(
     		        CasConstants.PARAMETER.PARAMETER_MAP, 
@@ -117,10 +117,10 @@ public class CasAuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 	        @AuthenticationPrincipal Object user,
 			HttpServletRequest request,
 			HttpServletResponse response){
-		AppsCasDetails casDetails=(AppsCasDetails)WebContext.getAttribute(CasConstants.PARAMETER.ENDPOINT_CAS_DETAILS);
-		ServiceTicketImpl serviceTicket=new ServiceTicketImpl(WebContext.getAuthentication(),casDetails);
+		AppsCasDetails casDetails = (AppsCasDetails)WebContext.getAttribute(CasConstants.PARAMETER.ENDPOINT_CAS_DETAILS);
+		ServiceTicketImpl serviceTicket = new ServiceTicketImpl(WebContext.getAuthentication(),casDetails);
 		
-		String ticket=ticketServices.createTicket(serviceTicket);
+		String ticket = ticketServices.createTicket(serviceTicket);
 		
 		StringBuffer callbackUrl = new StringBuffer(casDetails.getCallbackUrl());
 		if(casDetails.getCallbackUrl().indexOf("?")==-1) {
@@ -158,7 +158,7 @@ public class CasAuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 		    onlineTicketServices.store(onlineTicketId, onlineTicket);
 		}
 		
-		_logger.debug("redirect to CAS Client URL " + callbackUrl);
+		_logger.debug("redirect to CAS Client URL {}" , callbackUrl);
 		
 		ModelAndView modelAndView=new ModelAndView("authorize/cas_sso_submint");
 		modelAndView.addObject("callbackUrl", callbackUrl.toString());

+ 19 - 7
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/adapter/CasDefaultAdapter.java

@@ -20,21 +20,25 @@ package org.maxkey.authz.cas.endpoint.adapter;
 import java.io.UnsupportedEncodingException;
 
 import org.apache.commons.codec.binary.Base64;
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.cas.endpoint.response.ServiceResponseBuilder;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.entity.UserInfo;
+import org.maxkey.entity.apps.AppsCasDetails;
 import org.maxkey.web.WebConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.web.servlet.ModelAndView;
 
 public class CasDefaultAdapter extends AbstractAuthorizeAdapter {
+	final static Logger _logger = LoggerFactory.getLogger(CasDefaultAdapter.class);
 	
 	static String Charset_UTF8="UTF-8";
 	
+	ServiceResponseBuilder serviceResponseBuilder;
+	
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data, ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 
-		return null;
+		return modelAndView;
 	}
 
 	public String base64Attr(String attrValue){
@@ -48,8 +52,12 @@ public class CasDefaultAdapter extends AbstractAuthorizeAdapter {
 	}
 	
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo, Object serviceResponseObject) {
-		ServiceResponseBuilder serviceResponseBuilder=(ServiceResponseBuilder)serviceResponseObject;
+	public Object generateInfo() {
+		//user for return 
+		String user = getValueByUserAttr(userInfo,((AppsCasDetails)this.app).getCasUser());
+		_logger.debug("cas user {}",user);
+		serviceResponseBuilder.success().setUser(user);
+		
 		//for user
 		serviceResponseBuilder.setAttribute("uid", userInfo.getId());
 		serviceResponseBuilder.setAttribute("displayName", base64Attr(userInfo.getDisplayName()));
@@ -69,7 +77,11 @@ public class CasDefaultAdapter extends AbstractAuthorizeAdapter {
 		serviceResponseBuilder.setAttribute("institution", userInfo.getInstId());
 		serviceResponseBuilder.setAttribute(WebConstants.ONLINE_TICKET_NAME,authentication.getOnlineTicket().getTicketId());
 	
-		return null;
+		return serviceResponseBuilder;
+	}
+
+	public void setServiceResponseBuilder(ServiceResponseBuilder serviceResponseBuilder) {
+		this.serviceResponseBuilder = serviceResponseBuilder;
 	}
 
 }

+ 8 - 4
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/st/RedisTicketServices.java

@@ -53,15 +53,15 @@ public class RedisTicketServices extends RandomServiceTicketServices {
 	@Override
 	public void store(String ticketId, Ticket ticket) {
 		RedisConnection conn=connectionFactory.getConnection();
-		conn.setexObject(PREFIX+ticketId, serviceTicketValiditySeconds, ticket);
+		conn.setexObject(prefixTicketId(ticketId), serviceTicketValiditySeconds, ticket);
 		conn.close();
 	}
 
 	@Override
 	public Ticket remove(String ticketId) {
 		RedisConnection conn=connectionFactory.getConnection();
-		Ticket ticket = conn.getObject(PREFIX+ticketId);
-		conn.delete(PREFIX+ticketId);
+		Ticket ticket = conn.getObject(prefixTicketId(ticketId));
+		conn.delete(prefixTicketId(ticketId));
 		conn.close();
 		return ticket;
 	}
@@ -69,10 +69,14 @@ public class RedisTicketServices extends RandomServiceTicketServices {
     @Override
     public Ticket get(String ticketId) {
         RedisConnection conn=connectionFactory.getConnection();
-        Ticket ticket = conn.getObject(PREFIX+ticketId);
+        Ticket ticket = conn.getObject(prefixTicketId(ticketId));
         conn.close();
         return ticket;
     }
+    
+    public String prefixTicketId(String ticketId) {
+    	return PREFIX + ticketId;
+    }
 
 	
 }

+ 13 - 43
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/ExtendApiAuthorizeEndpoint.java

@@ -22,11 +22,11 @@ package org.maxkey.authz.exapi.endpoint;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.AuthorizeBaseEndpoint;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.constants.ConstsBoolean;
 import org.maxkey.entity.Accounts;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.Apps;
 import org.maxkey.util.Instance;
 import org.maxkey.web.WebContext;
@@ -54,53 +54,23 @@ public class ExtendApiAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 	public ModelAndView authorize(HttpServletRequest request,@PathVariable("id") String id){
 	    
 	    ModelAndView modelAndView=new ModelAndView("authorize/redirect_sso_submit");
-		Apps apps=getApp(id);
+		Apps apps = getApp(id);
 		_logger.debug(""+apps);
-		UserInfo userInfo = WebContext.getUserInfo();
 		if(ConstsBoolean.isTrue(apps.getIsAdapter())){
-			
-			AbstractAuthorizeAdapter adapter =(AbstractAuthorizeAdapter)Instance.newInstance(apps.getAdapter());
-			String username ="";
-			String password ="";
-			if(apps.getCredential()==1) {
-				if(apps.getSystemUserAttr().equalsIgnoreCase("userId")) {
-					username = userInfo.getId();
-				}else if(apps.getSystemUserAttr().equalsIgnoreCase("username")) {
-					username = userInfo.getUsername();
-				}else if(apps.getSystemUserAttr().equalsIgnoreCase("email")) {
-					username = userInfo.getEmail();
-				}else if(apps.getSystemUserAttr().equalsIgnoreCase("employeeNumber")) {
-					username = userInfo.getEmployeeNumber();
-				}else if(apps.getSystemUserAttr().equalsIgnoreCase("windowsaccount")) {
-					username = userInfo.getWindowsAccount();
-				}else if(apps.getSystemUserAttr().equalsIgnoreCase("mobile")) {
-					username = userInfo.getMobile();
-				}else if(apps.getSystemUserAttr().equalsIgnoreCase("workEmail")) {
-					username = userInfo.getWorkEmail();
-				}else {
-					username = userInfo.getEmail();
-				}
-					
-			} else if(apps.getCredential()==2) {
-				username = apps.getSharedUsername();
-				password = apps.getSharedPassword();
-			}else if(apps.getCredential()==3) {
-				Accounts appUser=getAccounts(apps);
-				if(appUser	==	null){
-						return generateInitCredentialModelAndView(id,"/authorize/api/"+id);
-				}
-				apps.setAppUser(appUser);
+			AbstractAuthorizeAdapter adapter = (AbstractAuthorizeAdapter)Instance.newInstance(apps.getAdapter());
+			Accounts account = getAccounts(apps);
+			if(apps.getCredential()==Apps.CREDENTIALS.USER_DEFINED && account == null) {
+				return generateInitCredentialModelAndView(id,"/authorize/api/"+id);
 			}
 			
-			modelAndView=adapter.authorize(
-					WebContext.getUserInfo(), 
-					apps, 
-					username+"="+password, 
-					modelAndView);
-			return modelAndView;
+			adapter.setAuthentication((SigninPrincipal)WebContext.getAuthentication().getPrincipal());
+			adapter.setUserInfo(WebContext.getUserInfo());
+			adapter.setApp(apps);
+			adapter.setAccount(account);
+			
+			return adapter.authorize(modelAndView);
 		}else{
-	        modelAndView.addObject("redirect_uri", getApp(id).getLoginUrl());
-	        
+	        modelAndView.addObject("redirect_uri", apps.getLoginUrl());
 	        return modelAndView;
 		}
 		

+ 6 - 5
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiCndnsApiMailAdapter.java

@@ -19,13 +19,12 @@ package org.maxkey.authz.exapi.endpoint.adapter;
 
 import java.time.Instant;
 import java.util.HashMap;
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.client.http.HttpVerb;
 import org.maxkey.client.oauth.OAuthClient;
 import org.maxkey.crypto.DigestUtils;
+import org.maxkey.entity.Accounts;
 import org.maxkey.entity.ExtraAttrs;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.Apps;
 import org.maxkey.util.HttpsTrusts;
 import org.maxkey.util.JsonUtils;
@@ -45,6 +44,8 @@ public class ExtendApiCndnsApiMailAdapter extends AbstractAuthorizeAdapter {
 	//sign with parameter
 	//sign=md5(action=getUserInfo&appid=***&email=admin@maxkey.org&time=1579736456 + md5(token))
 
+	Accounts account;
+	
 	static String SIGN_STRING 		="action=getDomainInfo&appid=%s%s";
 	
 	static String SIGN_EMAIL_STRING ="action=getUserInfo&appid=%s&email=%s&time=%s%s";
@@ -55,18 +56,18 @@ public class ExtendApiCndnsApiMailAdapter extends AbstractAuthorizeAdapter {
 	
 	
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		return null;
 	}
 
 	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
+	public Object encrypt(Object data, String algorithmKey, String algorithm) {
 		return null;
 	}
 
 	@SuppressWarnings("unchecked")
     @Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		HttpsTrusts.beforeConnection();
 		
 		Apps details=(Apps)app;

+ 6 - 12
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiQQExmailAdapter.java

@@ -18,12 +18,11 @@
 package org.maxkey.authz.exapi.endpoint.adapter;
 
 import java.util.HashMap;
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.client.oauth.OAuthClient;
 import org.maxkey.client.oauth.model.Token;
+import org.maxkey.entity.Accounts;
 import org.maxkey.entity.ExtraAttrs;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.Apps;
 import org.maxkey.util.HttpsTrusts;
 import org.maxkey.util.JsonUtils;
@@ -43,25 +42,20 @@ public class ExtendApiQQExmailAdapter extends AbstractAuthorizeAdapter {
 	//https://exmail.qq.com/qy_mng_logic/doc#10036
 	static String AUTHKEY_URI="https://api.exmail.qq.com/cgi-bin/service/get_login_url?access_token=%s&userid=%s";
 	
+	Accounts account;
+	
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		return null;
 	}
 
-	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return null;
-	}
 
 	@SuppressWarnings("unchecked")
     @Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		HttpsTrusts.beforeConnection();
 		
 		Apps details=(Apps)app;
-		String username = data.substring(0, data.indexOf("="));
-		String password = data.substring(data.indexOf("=") + 1);
-		_logger.trace("username " + username +" password " + password);
 		//extraAttrs from Applications
 		ExtraAttrs extraAttrs=null;
 		if(details.getIsExtendAttr()==1){
@@ -74,7 +68,7 @@ public class ExtendApiQQExmailAdapter extends AbstractAuthorizeAdapter {
 		_logger.debug(""+token);
 		
 		OAuthClient authkeyRestClient=new OAuthClient(
-				String.format(AUTHKEY_URI,token.getAccess_token(),username));
+				String.format(AUTHKEY_URI,token.getAccess_token(),userInfo.getUsername()));
 		
 		HashMap<String, String> authKey=JsonUtils.gson2Object(authkeyRestClient.execute().getBody(), HashMap.class);
 		_logger.debug("authKey : "+authKey);

+ 6 - 5
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiTimestampSignAdapter.java

@@ -18,11 +18,10 @@
 package org.maxkey.authz.exapi.endpoint.adapter;
 
 import java.time.Instant;
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.crypto.DigestUtils;
+import org.maxkey.entity.Accounts;
 import org.maxkey.entity.ExtraAttrs;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.Apps;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -43,18 +42,20 @@ import org.springframework.web.servlet.ModelAndView;
 public class ExtendApiTimestampSignAdapter extends AbstractAuthorizeAdapter {
 	final static Logger _logger = LoggerFactory.getLogger(ExtendApiTimestampSignAdapter.class);
 	
+	Accounts account;
+	
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		return null;
 	}
 
 	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
+	public Object encrypt(Object data, String algorithmKey, String algorithm) {
 		return null;
 	}
 
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		Apps details=(Apps)app;
 		
 		String code = details.getPrincipal();

+ 6 - 5
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiZentaoAdapter.java

@@ -18,11 +18,10 @@
 package org.maxkey.authz.exapi.endpoint.adapter;
 
 import java.time.Instant;
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.crypto.DigestUtils;
+import org.maxkey.entity.Accounts;
 import org.maxkey.entity.ExtraAttrs;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.Apps;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -44,18 +43,20 @@ public class ExtendApiZentaoAdapter extends AbstractAuthorizeAdapter {
 	static String login_url_template="api.php?m=user&f=apilogin&account=%s&code=%s&time=%s&token=%s";
 	static String login_url_m_template="account=%s&code=%s&time=%s&token=%s";
 	
+	Accounts account;
+	
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		return null;
 	}
 
 	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
+	public Object encrypt(Object data, String algorithmKey, String algorithm) {
 		return null;
 	}
 
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		Apps details=(Apps)app;
 		//extraAttrs from Applications
 		ExtraAttrs extraAttrs=null;

+ 18 - 17
maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/FormBasedAuthorizeEndpoint.java

@@ -22,6 +22,7 @@ package org.maxkey.authz.formbased.endpoint;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.AuthorizeBaseEndpoint;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.authz.formbased.endpoint.adapter.FormBasedDefaultAdapter;
@@ -62,40 +63,40 @@ public class FormBasedAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 	public ModelAndView authorize(
 			HttpServletRequest request,
 			@PathVariable("id") String id){
-		AppsFormBasedDetails formBasedDetails=formBasedDetailsService.getAppDetails(id);
-		_logger.debug(""+formBasedDetails);
-		Apps  application= getApp(id);
+		
+		AppsFormBasedDetails formBasedDetails = formBasedDetailsService.getAppDetails(id);
+		_logger.debug("formBasedDetails {}",formBasedDetails);
+		Apps  application = getApp(id);
 		formBasedDetails.setAdapter(application.getAdapter());
 		formBasedDetails.setIsAdapter(application.getIsAdapter());
 		ModelAndView modelAndView=null;
 		
-		Accounts appUser=getAccounts(formBasedDetails);
+		Accounts account = getAccounts(formBasedDetails);
+		_logger.debug("Accounts {}",account);
 		
-		_logger.debug("Accounts "+appUser);
-		if(appUser	==	null){
+		if(account	==	null){
 			return generateInitCredentialModelAndView(id,"/authz/formbased/"+id);
-			
 		}else{
-			formBasedDetails.setAppUser(appUser);
-			
 			modelAndView=new ModelAndView();
 			
 			AbstractAuthorizeAdapter adapter;
 			
 			if(ConstsBoolean.isTrue(formBasedDetails.getIsAdapter())){
-				adapter =(AbstractAuthorizeAdapter)Instance.newInstance(formBasedDetails.getAdapter());
+				Object formBasedAdapter = Instance.newInstance(formBasedDetails.getAdapter());
+				adapter =(AbstractAuthorizeAdapter)formBasedAdapter;
 			}else{
-				adapter =(AbstractAuthorizeAdapter)defaultFormBasedAdapter;
+				FormBasedDefaultAdapter formBasedDefaultAdapter =new FormBasedDefaultAdapter();
+				adapter =(AbstractAuthorizeAdapter)formBasedDefaultAdapter;
 			}
+			adapter.setAuthentication((SigninPrincipal)WebContext.getAuthentication().getPrincipal());
+			adapter.setUserInfo(WebContext.getUserInfo());
+			adapter.setApp(formBasedDetails);
+			adapter.setAccount(account);
 			
-			modelAndView=adapter.authorize(
-					WebContext.getUserInfo(), 
-					formBasedDetails, 
-					appUser.getRelatedUsername()+"."+appUser.getRelatedPassword(), 
-					modelAndView);
+			modelAndView = adapter.authorize(modelAndView);
 		}
 		
-		_logger.debug("FormBased View Name " + modelAndView.getViewName());
+		_logger.debug("FormBased View Name {}" , modelAndView.getViewName());
 		
 		return modelAndView;
 	}

+ 8 - 15
maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedDefaultAdapter.java

@@ -19,37 +19,30 @@ package org.maxkey.authz.formbased.endpoint.adapter;
 
 import java.time.Instant;
 
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.constants.ConstsBoolean;
 import org.maxkey.crypto.DigestUtils;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.AppsFormBasedDetails;
 import org.springframework.web.servlet.ModelAndView;
 
 public class FormBasedDefaultAdapter extends AbstractAuthorizeAdapter {
 
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		return null;
 	}
-
-	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return null;
-	}
-
+	
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		modelAndView.setViewName("authorize/formbased_sso_submint");
 		AppsFormBasedDetails details=(AppsFormBasedDetails)app;
 		
-		String password = details.getAppUser().getRelatedPassword();
+		String password = account.getRelatedPassword();
         if(null==details.getPasswordAlgorithm()||details.getPasswordAlgorithm().equals("")){
         }else if(details.getPasswordAlgorithm().indexOf("HEX")>-1){
-            password = DigestUtils.digestHex(details.getAppUser().getRelatedPassword(),details.getPasswordAlgorithm().substring(0, details.getPasswordAlgorithm().indexOf("HEX")));
+            password = DigestUtils.digestHex(account.getRelatedPassword(),details.getPasswordAlgorithm().substring(0, details.getPasswordAlgorithm().indexOf("HEX")));
         }else{
-            password = DigestUtils.digestBase64(details.getAppUser().getRelatedPassword(),details.getPasswordAlgorithm());
+            password = DigestUtils.digestBase64(account.getRelatedPassword(),details.getPasswordAlgorithm());
         }
         
         modelAndView.addObject("id", details.getId());
@@ -58,9 +51,9 @@ public class FormBasedDefaultAdapter extends AbstractAuthorizeAdapter {
 		modelAndView.addObject("loginUrl", details.getLoginUrl());
 		modelAndView.addObject("usernameMapping", details.getUsernameMapping());
 		modelAndView.addObject("passwordMapping", details.getPasswordMapping());
-		modelAndView.addObject("username", details.getAppUser().getRelatedUsername());    
+		modelAndView.addObject("username", account.getRelatedUsername());    
         modelAndView.addObject("password",  password);
-        modelAndView.addObject("timestamp",  ""+Instant.now().getEpochSecond());
+        modelAndView.addObject("timestamp",  "" + Instant.now().getEpochSecond());
 		
 	    if(ConstsBoolean.isTrue(details.getIsExtendAttr())){
 	        modelAndView.addObject("extendAttr", details.getExtendAttr());

+ 6 - 13
maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedNetease163EmailAdapter.java

@@ -17,32 +17,25 @@
 
 package org.maxkey.authz.formbased.endpoint.adapter;
 
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.constants.ConstsBoolean;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.AppsFormBasedDetails;
 import org.springframework.web.servlet.ModelAndView;
 
 public class FormBasedNetease163EmailAdapter extends AbstractAuthorizeAdapter {
-
-	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
-		return null;
-	}
-
+	
 	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
+	public String generateInfo() {
 		return null;
 	}
 
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		modelAndView.setViewName("authorize/formbased_163email_sso_submint");
 		AppsFormBasedDetails details=(AppsFormBasedDetails)app;
-		modelAndView.addObject("username", details.getAppUser().getRelatedUsername().substring(details.getAppUser().getRelatedUsername().indexOf("@")));
-		modelAndView.addObject("email", details.getAppUser().getRelatedUsername());
-		modelAndView.addObject("password",  details.getAppUser().getRelatedPassword());
+		modelAndView.addObject("username", account.getRelatedUsername().substring(account.getRelatedUsername().indexOf("@")));
+		modelAndView.addObject("email", account.getRelatedUsername());
+		modelAndView.addObject("password",  account.getRelatedPassword());
 		
 		if(ConstsBoolean.isTrue(details.getIsExtendAttr())){
 			modelAndView.addObject("extendAttr", details.getExtendAttr());

+ 4 - 23
maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedNeteaseNoteYoudaoAdapter.java

@@ -19,45 +19,26 @@ package org.maxkey.authz.formbased.endpoint.adapter;
 
 import java.util.Date;
 
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.crypto.DigestUtils;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.AppsFormBasedDetails;
 import org.springframework.web.servlet.ModelAndView;
 
 public class FormBasedNeteaseNoteYoudaoAdapter extends AbstractAuthorizeAdapter {
 
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		return null;
 	}
 
-	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return null;
-	}
 
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		modelAndView.setViewName("authorize/formbased_wy_youdao_sso_submint");
 		AppsFormBasedDetails details=(AppsFormBasedDetails)app;
-		modelAndView.addObject("username", details.getAppUser().getRelatedUsername());
-		modelAndView.addObject("password",  DigestUtils.md5Hex(details.getAppUser().getRelatedPassword()));
+		modelAndView.addObject("username", account.getRelatedUsername());
+		modelAndView.addObject("password",  DigestUtils.md5Hex(account.getRelatedPassword()));
 		modelAndView.addObject("currentTime",  (new Date()).getTime());
-		
-		/*
-		if(BOOLEAN.isTrue(details.getIsExtendAttr())){
-			modelAndView.addObject("extendAttr", details.getExtendAttr());
-			modelAndView.addObject("isExtendAttr", true);
-		}else{
-			modelAndView.addObject("isExtendAttr", false);
-		}
-		
-		modelAndView.addObject("action", details.getRedirectUri());
-		modelAndView.addObject("usernameMapping", details.getUsernameMapping());
-		modelAndView.addObject("passwordMapping", details.getPasswordMapping());
-		*/
 		return modelAndView;
 	}
 

+ 6 - 13
maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedRedirectAdapter.java

@@ -19,11 +19,9 @@ package org.maxkey.authz.formbased.endpoint.adapter;
 
 import java.time.Instant;
 
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.constants.ConstsBoolean;
 import org.maxkey.crypto.DigestUtils;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.AppsFormBasedDetails;
 import org.maxkey.web.WebContext;
 import org.springframework.web.servlet.ModelAndView;
@@ -31,26 +29,21 @@ import org.springframework.web.servlet.ModelAndView;
 public class FormBasedRedirectAdapter extends AbstractAuthorizeAdapter {
 
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		return null;
 	}
 
 	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return null;
-	}
-
-	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		modelAndView.setViewName("authorize/formbased_redirect_submint");
 		AppsFormBasedDetails details=(AppsFormBasedDetails)app;
 		
-		String password = details.getAppUser().getRelatedPassword();
+		String password = account.getRelatedPassword();
         if(null==details.getPasswordAlgorithm()||details.getPasswordAlgorithm().equals("")){
         }else if(details.getPasswordAlgorithm().indexOf("HEX")>-1){
-            password = DigestUtils.digestHex(details.getAppUser().getRelatedPassword(),details.getPasswordAlgorithm().substring(0, details.getPasswordAlgorithm().indexOf("HEX")));
+            password = DigestUtils.digestHex(account.getRelatedPassword(),details.getPasswordAlgorithm().substring(0, details.getPasswordAlgorithm().indexOf("HEX")));
         }else{
-            password = DigestUtils.digestBase64(details.getAppUser().getRelatedPassword(),details.getPasswordAlgorithm());
+            password = DigestUtils.digestBase64(account.getRelatedPassword(),details.getPasswordAlgorithm());
         }
         
 		modelAndView.addObject("id", details.getId());
@@ -59,7 +52,7 @@ public class FormBasedRedirectAdapter extends AbstractAuthorizeAdapter {
 		modelAndView.addObject("loginUrl", details.getLoginUrl());
 		modelAndView.addObject("usernameMapping", details.getUsernameMapping());
 		modelAndView.addObject("passwordMapping", details.getPasswordMapping());
-		modelAndView.addObject("username", details.getAppUser().getRelatedUsername());
+		modelAndView.addObject("username", account.getRelatedUsername());
         modelAndView.addObject("password",  password);
         modelAndView.addObject("timestamp",  ""+Instant.now().getEpochSecond());
 		

+ 125 - 55
maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/jwt/endpoint/adapter/JwtAdapter.java

@@ -17,26 +17,31 @@
 
 package org.maxkey.authz.jwt.endpoint.adapter;
 
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.configuration.oidc.OIDCProviderMetadata;
-import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
-import org.maxkey.entity.UserInfo;
-import org.maxkey.entity.apps.Apps;
+import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
+import org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
+import org.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
 import org.maxkey.entity.apps.AppsJwtDetails;
 import org.maxkey.web.WebConstants;
-import org.maxkey.web.WebContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.web.servlet.ModelAndView;
 
+import com.nimbusds.jose.EncryptionMethod;
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWEAlgorithm;
+import com.nimbusds.jose.JWEHeader;
+import com.nimbusds.jose.JWEObject;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.Payload;
 import com.nimbusds.jwt.JWT;
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.PlainJWT;
@@ -44,23 +49,35 @@ import com.nimbusds.jwt.SignedJWT;
 
 public class JwtAdapter extends AbstractAuthorizeAdapter {
 	final static Logger _logger = LoggerFactory.getLogger(JwtAdapter.class);
-	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
-		AppsJwtDetails details=(AppsJwtDetails)app;
+
+	AppsJwtDetails jwtDetails;
 	
-		
-		JwtSigningAndValidationService jwtSignerService= WebContext.getBean("jwtSignerValidationService",JwtSigningAndValidationService.class);
-		OIDCProviderMetadata providerMetadata= WebContext.getBean("oidcProviderMetadata",OIDCProviderMetadata.class);
+	JWT jwtToken;
 	
-		DateTime currentDateTime=DateTime.now();
-		
-		Date expirationTime=currentDateTime.plusMinutes(Integer.parseInt(details.getExpires())).toDate();
-		_logger.debug("expiration Time : "+expirationTime);
-		
-		JWTClaimsSet jwtClaims =new  JWTClaimsSet.Builder()
-				.issuer(providerMetadata.getIssuer())
-				.subject(userInfo.getUsername())
-				.audience(Arrays.asList(details.getId()))
+	JWEObject jweObject;
+	
+	JWTClaimsSet jwtClaims;
+	
+	public JwtAdapter() {
+
+	}
+
+	public JwtAdapter(AppsJwtDetails jwtDetails) {
+		this.jwtDetails = jwtDetails;
+	}
+
+	@Override
+	public Object generateInfo() {
+		DateTime currentDateTime = DateTime.now();
+		Date expirationTime = currentDateTime.plusMinutes(Integer.parseInt(jwtDetails.getExpires())).toDate();
+		_logger.debug("expiration Time : {}" , expirationTime);
+		String subject = getValueByUserAttr(userInfo,jwtDetails.getSubject());
+		_logger.trace("jwt subject : {}" , subject);
+		
+		jwtClaims =new  JWTClaimsSet.Builder()
+				.issuer(jwtDetails.getIssuer())
+				.subject(subject)
+				.audience(Arrays.asList(jwtDetails.getId()))
 				.jwtID(UUID.randomUUID().toString())
 				.issueTime(currentDateTime.toDate())
 				.expirationTime(expirationTime)
@@ -70,58 +87,111 @@ public class JwtAdapter extends AbstractAuthorizeAdapter {
 				.claim("external_id", userInfo.getId())
 				.claim("locale", userInfo.getLocale())
 				.claim(WebConstants.ONLINE_TICKET_NAME, authentication.getOnlineTicket().getTicketId())
-				.claim("kid", jwtSignerService.getDefaultSignerKeyId())
+				.claim("kid", jwtDetails.getId()+ "_sig")
 				.claim("institution", userInfo.getInstId())
 				.build();
 		
-		_logger.debug("jwt Claims : "+jwtClaims);
-		
-		JWT jwtToken = new PlainJWT(jwtClaims);
-		
-		JWSAlgorithm signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
-		
-		//get PublicKey
-		/*Map<String, JWK>  jwkMap=jwtSignerService.getAllPublicKeys();
+		_logger.trace("jwt Claims : {}" , jwtClaims);
 		
-		JWK jwk=jwkMap.get("connsec_rsa1");
-		
-		_logger.debug("isPrivate "+jwk.isPrivate());*/
-		
-		_logger.debug(" signingAlg "+signingAlg);
-		
-		jwtToken = new SignedJWT(new JWSHeader(signingAlg), jwtClaims);
-		// sign it with the server's key
-		jwtSignerService.signJwt((SignedJWT) jwtToken);
-		
-		String tokenString=jwtToken.serialize();
-		_logger.debug("jwt Token : "+tokenString);
-		
-		return tokenString;
+		jwtToken = new PlainJWT(jwtClaims);
+			
+		return jwtToken;
 	}
 
 	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
+	public Object sign(Object data,String signatureKey,String signature) {
+		if(!jwtDetails.getSignature().equalsIgnoreCase("none")) {
+			JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": ["+jwtDetails.getSignatureKey()+"]}");
+			try {
+				DefaultJwtSigningAndValidationService jwtSignerService = 
+							new DefaultJwtSigningAndValidationService(jwkSetKeyStore);
+				jwtSignerService.setDefaultSignerKeyId(jwtDetails.getId() + "_sig");
+				jwtSignerService.setDefaultSigningAlgorithmName(jwtDetails.getSignature());
+				JWSAlgorithm signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
+				_logger.trace(" signingAlg {}" , signingAlg);
+				jwtToken = new SignedJWT(new JWSHeader(signingAlg), jwtClaims);
+				// sign it with the server's key
+				jwtSignerService.signJwt((SignedJWT) jwtToken);
+				return jwtToken;
+			} catch (NoSuchAlgorithmException e) {
+				_logger.error("NoSuchAlgorithmException", e);
+			} catch (InvalidKeySpecException e) {
+				_logger.error("InvalidKeySpecException", e);
+			} catch (JOSEException e) {
+				_logger.error("JOSEException", e);
+			}
+		}
 		return data;
 	}
 
 	@Override
-	public String sign(String data, Apps app) {
-		
+	public Object encrypt(Object data, String algorithmKey, String algorithm) {
+		if(!jwtDetails.getAlgorithm().equalsIgnoreCase("none")) {
+			JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": ["+jwtDetails.getAlgorithmKey()+"]}");
+			try {
+				DefaultJwtEncryptionAndDecryptionService jwtEncryptionService = 
+							new DefaultJwtEncryptionAndDecryptionService(jwkSetKeyStore);
+				jwtEncryptionService.setDefaultEncryptionKeyId(jwtDetails.getId()  + "_enc");
+				jwtEncryptionService.setDefaultAlgorithm(jwtDetails.getAlgorithm());
+				JWEAlgorithm encryptAlgorithm = null;
+				if(jwtDetails.getAlgorithm().startsWith("RSA")) {
+					encryptAlgorithm = jwtEncryptionService.getDefaultAlgorithm();
+				}else {
+					encryptAlgorithm = JWEAlgorithm.DIR;
+				}
+				_logger.trace(" encryptAlgorithm {}" , encryptAlgorithm);
+				EncryptionMethod encryptionMethod = 
+						jwtEncryptionService.parseEncryptionMethod(jwtDetails.getEncryptionMethod());
+				
+				Payload payload;
+				if(jwtToken instanceof SignedJWT) {
+					payload = ((SignedJWT)jwtToken).getPayload();
+				}else {
+					payload = ((PlainJWT)jwtToken).getPayload();
+				}
+				// Example Request JWT encrypted with RSA-OAEP-256 and 128-bit AES/GCM
+				//JWEHeader jweHeader = new JWEHeader(JWEAlgorithm.RSA1_5, EncryptionMethod.A128GCM);
+				
+				jweObject = new JWEObject(
+					    new JWEHeader.Builder(new JWEHeader(encryptAlgorithm,encryptionMethod))
+					        .contentType("JWT") // required to indicate nested JWT
+					        .build(),
+					        payload);
+				
+				jwtEncryptionService.encryptJwt(jweObject);
+				
+			} catch (NoSuchAlgorithmException | InvalidKeySpecException | JOSEException e) {
+				_logger.error("Encrypt Exception", e);
+			}
+		}
 		return data;
 	}
-
+	
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		modelAndView.setViewName("authorize/jwt_sso_submint");
-		AppsJwtDetails details=(AppsJwtDetails)app;
-		modelAndView.addObject("action", details.getRedirectUri());
-		_logger.debug("jwt Token data : "+data);
-		
-		modelAndView.addObject("token",data);
+		modelAndView.addObject("action", jwtDetails.getRedirectUri());
 		
-		//return_to
+		modelAndView.addObject("token",serialize());
+		modelAndView.addObject("jwtName",jwtDetails.getJwtName());
 		
 		return modelAndView;
 	}
 
+	public void setJwtDetails(AppsJwtDetails jwtDetails) {
+		this.jwtDetails = jwtDetails;
+	}
+
+	@Override
+	public String serialize() {
+		String tokenString = "";
+		if(jweObject != null) {
+			tokenString = jweObject.serialize();
+		}else {
+			tokenString = jwtToken.serialize();
+		}
+		_logger.debug("jwt Token : {}" , tokenString);
+		return tokenString;
+	}
+
 }

+ 0 - 115
maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/jwt/endpoint/adapter/JwtDefaultAdapter.java

@@ -1,115 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.authz.jwt.endpoint.adapter;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-import org.maxkey.authn.SigninPrincipal;
-import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.configuration.oidc.OIDCProviderMetadata;
-import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
-import org.maxkey.entity.UserInfo;
-import org.maxkey.entity.apps.AppsJwtDetails;
-import org.maxkey.web.WebConstants;
-import org.maxkey.web.WebContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.nimbusds.jose.JWSAlgorithm;
-import com.nimbusds.jose.JWSHeader;
-import com.nimbusds.jwt.JWT;
-import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.PlainJWT;
-import com.nimbusds.jwt.SignedJWT;
-
-public class JwtDefaultAdapter extends AbstractAuthorizeAdapter {
-	final static Logger _logger = LoggerFactory.getLogger(JwtDefaultAdapter.class);
-	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
-	    AppsJwtDetails details=(AppsJwtDetails)app;
-    
-        
-	    JwtSigningAndValidationService jwtSignerService= WebContext.getBean("jwtSignerValidationService",JwtSigningAndValidationService.class);
-		OIDCProviderMetadata providerMetadata= WebContext.getBean("oidcProviderMetadata",OIDCProviderMetadata.class);
-    
-        DateTime currentDateTime=DateTime.now();
-        
-        Date expirationTime=currentDateTime.plusMinutes(Integer.parseInt(details.getExpires())).toDate();
-        _logger.debug("expiration Time : "+expirationTime);
-        
-        JWTClaimsSet jwtClaims =new  JWTClaimsSet.Builder()
-                .issuer(providerMetadata.getIssuer())
-                .subject(userInfo.getUsername())
-                .audience(Arrays.asList(details.getId()))
-                .jwtID(UUID.randomUUID().toString())
-                .issueTime(currentDateTime.toDate())
-                .expirationTime(expirationTime)
-                .claim("email", userInfo.getWorkEmail())
-                .claim("name", userInfo.getUsername())
-                .claim("user_id", userInfo.getId())
-                .claim("external_id", userInfo.getId())
-                .claim("locale", userInfo.getLocale())
-                .claim(WebConstants.ONLINE_TICKET_NAME, authentication.getOnlineTicket().getTicketId())
-                .claim("kid", jwtSignerService.getDefaultSignerKeyId())
-                .claim("institution", userInfo.getInstId())
-                .build();
-        
-        _logger.debug("jwt Claims : "+jwtClaims);
-        
-        JWT jwtToken = new PlainJWT(jwtClaims);
-        
-        JWSAlgorithm signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
-        
-        //get PublicKey
-        /*Map<String, JWK>  jwkMap=jwtSignerService.getAllPublicKeys();
-        
-        JWK jwk=jwkMap.get("connsec_rsa1");
-        
-        _logger.debug("isPrivate "+jwk.isPrivate());*/
-        
-        _logger.debug(" signingAlg "+signingAlg);
-        
-        jwtToken = new SignedJWT(new JWSHeader(signingAlg), jwtClaims);
-        // sign it with the server's key
-        jwtSignerService.signJwt((SignedJWT) jwtToken);
-        
-        String tokenString=jwtToken.serialize();
-        _logger.debug("jwt Token : "+tokenString);
-        
-        return tokenString;
-	}
-
-	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return super.encrypt(data, algorithmKey, algorithm);
-	}
-
-	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
-		modelAndView.setViewName("authorize/jwt_sso_submint");
-		AppsJwtDetails details=(AppsJwtDetails)app;
-		modelAndView.addObject("action", details.getRedirectUri());
-		
-		modelAndView.addObject("token",data );
-		return modelAndView;
-	}
-}

+ 0 - 124
maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/jwt/endpoint/adapter/JwtHS256Adapter.java

@@ -1,124 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.authz.jwt.endpoint.adapter;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-import org.maxkey.authn.SigninPrincipal;
-import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.configuration.oidc.OIDCProviderMetadata;
-import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
-import org.maxkey.crypto.jwt.signer.service.impl.SymmetricSigningAndValidationServiceBuilder;
-import org.maxkey.crypto.password.PasswordReciprocal;
-import org.maxkey.entity.UserInfo;
-import org.maxkey.entity.apps.Apps;
-import org.maxkey.entity.apps.AppsJwtDetails;
-import org.maxkey.web.WebConstants;
-import org.maxkey.web.WebContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.nimbusds.jose.JWSAlgorithm;
-import com.nimbusds.jose.JWSHeader;
-import com.nimbusds.jwt.JWT;
-import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.PlainJWT;
-import com.nimbusds.jwt.SignedJWT;
-
-public class JwtHS256Adapter extends AbstractAuthorizeAdapter {
-	final static Logger _logger = LoggerFactory.getLogger(JwtHS256Adapter.class);
-	private SymmetricSigningAndValidationServiceBuilder symmetricJwtSignerServiceBuilder=new SymmetricSigningAndValidationServiceBuilder();
-
-	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
-		AppsJwtDetails details=(AppsJwtDetails)app;
-		
-		OIDCProviderMetadata providerMetadata= WebContext.getBean("oidcProviderMetadata",OIDCProviderMetadata.class);
-	
-		DateTime currentDateTime=DateTime.now();
-		
-		Date expirationTime=currentDateTime.plusMinutes(Integer.parseInt(details.getExpires())).toDate();
-		_logger.debug("expiration Time : "+expirationTime);
-		
-		JWTClaimsSet jwtClaims =new  JWTClaimsSet.Builder()
-				.issuer(providerMetadata.getIssuer())
-				.subject(userInfo.getUsername())
-				.audience(Arrays.asList(details.getId()))
-				.jwtID(UUID.randomUUID().toString())
-				.issueTime(currentDateTime.toDate())
-				.expirationTime(expirationTime)
-				.claim("email", userInfo.getWorkEmail())
-				.claim("name", userInfo.getUsername())
-				.claim("user_id", userInfo.getId())
-				.claim(WebConstants.ONLINE_TICKET_NAME, authentication.getOnlineTicket().getTicketId())
-				.claim("external_id", userInfo.getId())
-				.claim("locale", userInfo.getLocale())
-				.claim("kid", "SYMMETRIC-KEY")
-				.claim("institution", userInfo.getInstId())
-				.build();
-		
-		_logger.debug("jwt Claims : "+jwtClaims);
-		
-		JWT jwtToken = new PlainJWT(jwtClaims);
-		
-		String sharedSecret=PasswordReciprocal.getInstance().decoder(details.getAlgorithmKey());
-		
-		_logger.debug("jwt sharedSecret : "+sharedSecret);
-		
-		JwtSigningAndValidationService symmetricJwtSignerService =symmetricJwtSignerServiceBuilder.serviceBuilder(sharedSecret);
-		if(symmetricJwtSignerService!=null){
-			jwtToken = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), jwtClaims);
-			symmetricJwtSignerService.signJwt((SignedJWT) jwtToken);
-		}
-		
-		String tokenString=jwtToken.serialize();
-		_logger.debug("jwt Token : "+tokenString);
-		
-		return tokenString;
-	}
-
-	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return data;
-	}
-
-	@Override
-	public String sign(String data, Apps app) {
-		
-		return data;
-	}
-
-	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
-		modelAndView.setViewName("authorize/jwt_sso_submint");
-		AppsJwtDetails details=(AppsJwtDetails)app;
-		modelAndView.addObject("action", details.getRedirectUri());
-		_logger.debug("jwt Token data : "+data);
-		
-		modelAndView.addObject("token",data);
-		
-		//return_to
-		
-		return modelAndView;
-	}
-
-}

+ 26 - 33
maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/token/endpoint/JwtAuthorizeEndpoint.java

@@ -20,14 +20,17 @@
  */
 package org.maxkey.authz.token.endpoint;
 
+import java.lang.reflect.InvocationTargetException;
+
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.beanutils.BeanUtils;
 import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.AuthorizeBaseEndpoint;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.authz.jwt.endpoint.adapter.JwtDefaultAdapter;
+import org.maxkey.authz.jwt.endpoint.adapter.JwtAdapter;
 import org.maxkey.configuration.ApplicationConfig;
 import org.maxkey.constants.ConstsBoolean;
 import org.maxkey.entity.apps.Apps;
@@ -59,8 +62,6 @@ public class JwtAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 	@Autowired
 	AppsJwtDetailsService jwtDetailsService;
 	
-	JwtDefaultAdapter jwtDefaultAdapter=new JwtDefaultAdapter();
-	
 	@Autowired
 	ApplicationConfig applicationConfig;
 	
@@ -83,44 +84,36 @@ public class JwtAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 		
 		AbstractAuthorizeAdapter adapter;
 		if(ConstsBoolean.isTrue(jwtDetails.getIsAdapter())){
-			adapter =(AbstractAuthorizeAdapter)Instance.newInstance(jwtDetails.getAdapter());
+			Object jwtAdapter = Instance.newInstance(jwtDetails.getAdapter());
+			try {
+				BeanUtils.setProperty(jwtAdapter, "jwtDetails", jwtDetails);
+			} catch (IllegalAccessException | InvocationTargetException e) {
+				_logger.error("setProperty error . ", e);
+			}
+			adapter = (AbstractAuthorizeAdapter)jwtAdapter;
 		}else{
-			adapter =(AbstractAuthorizeAdapter)jwtDefaultAdapter;
+			JwtAdapter jwtAdapter =new JwtAdapter(jwtDetails);
+			adapter = (AbstractAuthorizeAdapter)jwtAdapter;
 		}
 		
-		String tokenData=adapter.generateInfo(
-		        (SigninPrincipal)WebContext.getAuthentication().getPrincipal(),
-				WebContext.getUserInfo(), 
-				jwtDetails);
-		
-		String encryptTokenData=adapter.encrypt(
-				tokenData, 
-				jwtDetails.getAlgorithmKey(), 
-				jwtDetails.getAlgorithm());
+		adapter.setAuthentication((SigninPrincipal)WebContext.getAuthentication().getPrincipal());
+		adapter.setUserInfo(WebContext.getUserInfo());
 		
-		String signTokenData=adapter.sign(
-				encryptTokenData, 
-				jwtDetails);
+		adapter.generateInfo();
+		//sign
+		adapter.sign(null,jwtDetails.getSignatureKey(), jwtDetails.getSignature());
+		//encrypt
+		adapter.encrypt(null, jwtDetails.getAlgorithmKey(), jwtDetails.getAlgorithm());
 		
 		if(jwtDetails.getTokenType().equalsIgnoreCase("POST")) {
-			modelAndView=adapter.authorize(
-					WebContext.getUserInfo(), 
-					jwtDetails, 
-					signTokenData, 
-					modelAndView);
-			
-			return modelAndView;
+			return adapter.authorize(modelAndView);
 		}else {
+			_logger.debug("Cookie Name : {}" , jwtDetails.getJwtName());
 			
-			String cookieValue="";
-			cookieValue=signTokenData;
-			
-			_logger.debug("Cookie Name : "+jwtDetails.getCookieName());
-			
-			Cookie cookie= new Cookie(jwtDetails.getCookieName(),cookieValue);
+			Cookie cookie= new Cookie(jwtDetails.getJwtName(),adapter.serialize());
 			
-			Integer maxAge=Integer.parseInt(jwtDetails.getExpires())*60;
-			_logger.debug("Cookie Max Age :"+maxAge+" seconds.");
+			Integer maxAge = Integer.parseInt(jwtDetails.getExpires()) * 60;
+			_logger.debug("Cookie Max Age : {} seconds." , maxAge);
 			cookie.setMaxAge(maxAge);
 			
 			cookie.setPath("/");
@@ -129,7 +122,7 @@ public class JwtAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 			//tomcat 8.5
 			cookie.setDomain(applicationConfig.getBaseDomainName());
 			
-			_logger.debug("Sub Domain Name : "+"."+applicationConfig.getBaseDomainName());
+			_logger.debug("Sub Domain Name : .{}",applicationConfig.getBaseDomainName());
 			response.addCookie(cookie);
 			
 			if(jwtDetails.getRedirectUri().indexOf(applicationConfig.getBaseDomainName())>-1){

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/ClientDetailsService.java

@@ -32,6 +32,6 @@ public interface ClientDetailsService {
    * @return The client details (never null).
    * @throws ClientRegistrationException If the client account is locked, expired, disabled, or invalid for any other reason.
    */
-  ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException;
+  ClientDetails loadClientByClientId(String clientId,boolean cached) throws ClientRegistrationException;
 
 }

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java

@@ -111,7 +111,7 @@ public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, In
 
 		if (clientDetailsService != null) {
 			try {
-				ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
+				ClientDetails client = clientDetailsService.loadClientByClientId(clientId,true);
 				for (String scope : requestedScopes) {
 					if (client.isAutoApprove(scope) || client.isAutoApprove("all")) {
 						approvedScopes.add(scope);

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/TokenStoreUserApprovalHandler.java

@@ -110,7 +110,7 @@ public class TokenStoreUserApprovalHandler implements UserApprovalHandler, Initi
 		Set<String> scopes = authorizationRequest.getScope();
 		if (clientDetailsService!=null) {
 			try {
-				ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
+				ClientDetails client = clientDetailsService.loadClientByClientId(clientId,true);
 				approved = true;
 				for (String scope : scopes) {
 					if (!client.isAutoApprove(scope)) {

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/endpoint/OAuth20AccessConfirmationEndpoint.java

@@ -83,7 +83,7 @@ public class OAuth20AccessConfirmationEndpoint {
 	        // Map<String, Object> model
 	        AuthorizationRequest clientAuth = 
 	                (AuthorizationRequest) WebContext.getAttribute("authorizationRequest");
-	        ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
+	        ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId(),true);
 	        Apps  app = (Apps)WebContext.getAttribute(WebConstants.AUTHORIZE_SIGN_ON_APP);
 	        WebContext.setAttribute(app.getId(), app.getIcon());
 	       

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/endpoint/OAuth20UserApprovalHandler.java

@@ -75,7 +75,7 @@ public class OAuth20UserApprovalHandler extends ApprovalStoreUserApprovalHandler
 				Collection<String> requestedScopes = authorizationRequest.getScope();
 				try {
 					ClientDetails client = clientDetailsService
-							.loadClientByClientId(authorizationRequest.getClientId());
+							.loadClientByClientId(authorizationRequest.getClientId(),true);
 					for (String scope : requestedScopes) {
 						if (client.isAutoApprove(scope) || client.isAutoApprove("all")) {
 							approved = true;

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/ClientDetailsUserDetailsService.java

@@ -45,7 +45,7 @@ public class ClientDetailsUserDetailsService implements UserDetailsService {
 	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
 		ClientDetails clientDetails;
 		try {
-			clientDetails = clientDetailsService.loadClientByClientId(username);
+			clientDetails = clientDetailsService.loadClientByClientId(username,true);
 		} catch (NoSuchClientException e) {
 			throw new UsernameNotFoundException(e.getMessage(), e);
 		}

+ 25 - 18
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/JdbcClientDetailsService.java

@@ -69,9 +69,8 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg
     private static final String CLIENT_FIELDS_FOR_UPDATE = "RESOURCE_IDS, SCOPE, "
             + "AUTHORIZED_GRANT_TYPES, WEB_SERVER_REDIRECT_URI, AUTHORITIES, ACCESS_TOKEN_VALIDITY, "
             + "REFRESH_TOKEN_VALIDITY, ADDITIONAL_INFORMATION, AUTOAPPROVE, APPROVALPROMPT , "
-            + "IDTOKENSIGNINGALGORITHM, IDTOKENENCRYPTEDALGORITHM, IDTOKENENCRYPTIONMETHOD, "
-            + "USERINFOSIGNINGALGORITHM, USERINFOCRYPTEDALGORITHM, USERINFOENCRYPTIONMETHOD,"
-            +" JWKSURI, PKCE, PROTOCOL , INSTID ";
+            + "ALGORITHM, ALGORITHMKEY, ENCRYPTIONMETHOD, SIGNATURE, SIGNATUREKEY, SUBJECT, "
+            + "USERINFORESPONSE, ISSUER, AUDIENCE, PKCE, PROTOCOL , INSTID ";
 
     private static final String CLIENT_FIELDS = "client_secret, " + CLIENT_FIELDS_FOR_UPDATE;
 
@@ -83,7 +82,7 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg
     private static final String DEFAULT_SELECT_STATEMENT = BASE_FIND_STATEMENT + " where client_id = ?";
 
     private static final String DEFAULT_INSERT_STATEMENT = "insert into mxk_apps_oauth_client_details (" + CLIENT_FIELDS
-            + ", client_id) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+            + ", client_id) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
 
     private static final String DEFAULT_UPDATE_STATEMENT = "update mxk_apps_oauth_client_details " + "set "
             + CLIENT_FIELDS_FOR_UPDATE.replaceAll(", ", "=?, ") + "=? where client_id = ?";
@@ -126,13 +125,18 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg
         this.passwordEncoder = passwordEncoder;
     }
 
-    public ClientDetails loadClientByClientId(String clientId) {
+    public ClientDetails loadClientByClientId(String clientId,boolean cached) {
         // cache in memory
-        ClientDetails details = clientDetailsCache.getIfPresent(clientId);
+        ClientDetails details = null;
+        if(cached) {
+        	details = clientDetailsCache.getIfPresent(clientId);
+        }
         if(details == null) {
             try {
                 details = jdbcTemplate.queryForObject(selectClientDetailsSql, new ClientDetailsRowMapper(), clientId);
-                clientDetailsCache.put(clientId, details);
+                if(cached) {
+                	clientDetailsCache.put(clientId, details);
+                }
             } catch (EmptyResultDataAccessException e) {
                 throw new NoSuchClientException("No client with requested id: " + clientId);
             }
@@ -208,10 +212,11 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg
                         : null,
                 clientDetails.getAccessTokenValiditySeconds(), clientDetails.getRefreshTokenValiditySeconds(), json,
                 getAutoApproveScopes(clientDetails),clientDetails.getApprovalPrompt(),
-                clientDetails.getIdTokenSigningAlgorithm(),
-                clientDetails.getIdTokenEncryptedAlgorithm(), clientDetails.getIdTokenEncryptionMethod(),
-                clientDetails.getUserInfoSigningAlgorithm(), clientDetails.getUserInfoEncryptedAlgorithm(),
-                clientDetails.getUserInfoEncryptionMethod(), clientDetails.getJwksUri(), 
+                clientDetails.getAlgorithm(),
+                clientDetails.getAlgorithmKey(), clientDetails.getEncryptionMethod(),
+                clientDetails.getSignature(), clientDetails.getSignatureKey(),
+                clientDetails.getSubject(),clientDetails.getUserInfoResponse(),
+                clientDetails.getIssuer(), clientDetails.getAudience(), 
                 clientDetails.getPkce(), clientDetails.getProtocol(),clientDetails.getInstId(),
                 
                 clientDetails.getClientId()
@@ -290,14 +295,16 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg
                 details.setRefreshTokenValiditySeconds(rs.getInt(9));
             }
 
-            details.setIdTokenEncryptedAlgorithm(rs.getString("IDTOKENENCRYPTEDALGORITHM"));
-            details.setIdTokenEncryptionMethod(rs.getString("IDTOKENENCRYPTIONMETHOD"));
-            details.setIdTokenSigningAlgorithm(rs.getString("IDTOKENSIGNINGALGORITHM"));
+            details.setAlgorithm(rs.getString("algorithm"));
+            details.setAlgorithmKey(rs.getString("algorithmKey"));
+            details.setEncryptionMethod(rs.getString("encryptionMethod"));
 
-            details.setUserInfoEncryptedAlgorithm(rs.getString("USERINFOCRYPTEDALGORITHM"));
-            details.setUserInfoEncryptionMethod(rs.getString("USERINFOENCRYPTIONMETHOD"));
-            details.setUserInfoSigningAlgorithm(rs.getString("USERINFOSIGNINGALGORITHM"));
-            details.setJwksUri(rs.getString("JWKSURI"));
+            details.setSignature(rs.getString("signature"));
+            details.setSignatureKey(rs.getString("signatureKey"));
+            details.setSubject(rs.getString("subject"));
+            details.setUserInfoResponse(rs.getString("userInfoResponse"));
+            details.setAudience(rs.getString("audience"));
+            details.setIssuer(rs.getString("issuer"));
             details.setApprovalPrompt(rs.getString("APPROVALPROMPT"));
             details.setPkce(rs.getString("PKCE"));
             details.setProtocol(rs.getString("PROTOCOL"));

+ 2 - 2
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AuthorizationEndpoint.java

@@ -117,7 +117,7 @@ public class AuthorizationEndpoint extends AbstractEndpoint {
             HttpServletRequest request,
             HttpServletResponse response,
             @PathVariable("id") String id){
-        ClientDetails  clientDetails =getClientDetailsService().loadClientByClientId(id);
+        ClientDetails  clientDetails =getClientDetailsService().loadClientByClientId(id,true);
         _logger.debug(""+clientDetails);
         String authorizationUrl = "";
         try {
@@ -169,7 +169,7 @@ public class AuthorizationEndpoint extends AbstractEndpoint {
 						"User must be authenticated with Spring Security before authorization can be completed.");
 			}
 
-			ClientDetails client = getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId());
+			ClientDetails client = getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId(),true);
 
 			// The resolved redirect URI is either the redirect_uri from the parameters or the one from
 			// clientDetails. Either way we need to store it on the AuthorizationRequest.

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/TokenEndpoint.java

@@ -122,7 +122,7 @@ public class TokenEndpoint extends AbstractEndpoint {
 			}
 	
 			String clientId = getClientId((Authentication)principal);
-			ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);
+			ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId,true);
 	
 			TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);
 	

+ 2 - 2
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/request/DefaultOAuth2RequestFactory.java

@@ -85,7 +85,7 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory {
 				Collections.<String, String> emptyMap(), clientId, scopes, null, null, false, state, redirectUri,
 				responseTypes,codeChallenge,codeChallengeMethod);
 
-		ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);		
+		ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId,true);		
 		request.setResourceIdsAndAuthoritiesFromClientDetails(clientDetails);
 
 		return request;
@@ -133,7 +133,7 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory {
 
 	private Set<String> extractScopes(Map<String, String> requestParameters, String clientId) {
 		Set<String> scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Constants.PARAMETER.SCOPE));
-		ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
+		ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId,true);
 
 		if ((scopes == null || scopes.isEmpty())) {
 			// If no scopes are specified in the incoming data, use the default values registered with the client

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/AbstractTokenGranter.java

@@ -57,7 +57,7 @@ public abstract class AbstractTokenGranter implements TokenGranter {
 		}
 		
 		String clientId = tokenRequest.getClientId();
-		ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
+		ClientDetails client = clientDetailsService.loadClientByClientId(clientId,true);
 		validateGrantType(grantType, client);
 		
 		logger.debug("Getting access token for: " + clientId);

+ 4 - 4
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/DefaultTokenServices.java

@@ -244,7 +244,7 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
 		if (clientDetailsService != null) {
 			String clientId = result.getOAuth2Request().getClientId();
 			try {
-				clientDetailsService.loadClientByClientId(clientId);
+				clientDetailsService.loadClientByClientId(clientId,true);
 			}
 			catch (ClientRegistrationException e) {
 				throw new InvalidTokenException("Client not valid: " + clientId, e);
@@ -310,7 +310,7 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
 	 */
 	protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) {
 		if (clientDetailsService != null) {
-			ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
+			ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId(),true);
 			Integer validity = client.getAccessTokenValiditySeconds();
 			if (validity != null) {
 				return validity;
@@ -327,7 +327,7 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
 	 */
 	protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) {
 		if (clientDetailsService != null) {
-			ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
+			ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId(),true);
 			Integer validity = client.getRefreshTokenValiditySeconds();
 			if (validity != null) {
 				return validity;
@@ -345,7 +345,7 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
 	 */
 	protected boolean isSupportRefreshToken(OAuth2Request clientAuth) {
 		if (clientDetailsService != null) {
-			ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
+			ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId(),true);
 			return client.getAuthorizedGrantTypes().contains("refresh_token");
 		}
 		return this.supportRefreshToken;

+ 27 - 14
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/userinfo/endpoint/OAuthDefaultUserInfoAdapter.java

@@ -19,24 +19,41 @@ package org.maxkey.authz.oauth2.provider.userinfo.endpoint;
 
 import java.util.HashMap;
 
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.entity.UserInfo;
+import org.maxkey.entity.apps.oauth2.provider.ClientDetails;
 import org.maxkey.util.JsonUtils;
 import org.maxkey.util.StringGenerator;
 import org.maxkey.web.WebConstants;
-import org.springframework.web.servlet.ModelAndView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class OAuthDefaultUserInfoAdapter extends AbstractAuthorizeAdapter {
+	final static Logger _logger = LoggerFactory.getLogger(OAuthDefaultUserInfoAdapter.class);
+	ClientDetails clientDetails;
+	
+	public OAuthDefaultUserInfoAdapter() {}
+
+	public OAuthDefaultUserInfoAdapter(ClientDetails clientDetails) {
+		this.clientDetails = clientDetails;
+	}
 
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
+		 String subject = AbstractAuthorizeAdapter.getValueByUserAttr(userInfo, clientDetails.getSubject());
+		 _logger.debug("userId : {} , username : {} , displayName : {} , subject : {}" , 
+				 userInfo.getId(),
+				 userInfo.getUsername(),
+				 userInfo.getDisplayName(),
+				 subject);
+		 
 		HashMap<String, Object> beanMap = new HashMap<String, Object>();
 		beanMap.put("randomId",(new StringGenerator()).uuidGenerate());
 		beanMap.put("userId", userInfo.getId());
 		//for spring security oauth2
-		beanMap.put("user", userInfo.getUsername());
-		beanMap.put("username", userInfo.getUsername());
+		beanMap.put("user", subject);
+		beanMap.put("username", subject);
+		
+		beanMap.put("displayName", userInfo.getDisplayName());
 		beanMap.put("employeeNumber", userInfo.getEmployeeNumber());
 		beanMap.put("email", userInfo.getEmail());
 		beanMap.put("mobile", userInfo.getMobile());
@@ -56,15 +73,11 @@ public class OAuthDefaultUserInfoAdapter extends AbstractAuthorizeAdapter {
 		return info;
 	}
 
-	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return null;
+	public ClientDetails getClientDetails() {
+		return clientDetails;
 	}
 
-	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
-
-		return null;
+	public void setClientDetails(ClientDetails clientDetails) {
+		this.clientDetails = clientDetails;
 	}
-
 }

+ 21 - 40
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/userinfo/endpoint/UserInfoEndpoint.java

@@ -17,10 +17,14 @@
 
 package org.maxkey.authz.oauth2.provider.userinfo.endpoint;
 
+import java.lang.reflect.InvocationTargetException;
 import java.util.Enumeration;
 import java.util.HashMap;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.beanutils.BeanUtils;
 import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.authz.oauth2.common.OAuth2Constants;
@@ -29,12 +33,9 @@ import org.maxkey.authz.oauth2.provider.ClientDetailsService;
 import org.maxkey.authz.oauth2.provider.OAuth2Authentication;
 import org.maxkey.authz.oauth2.provider.token.DefaultTokenServices;
 import org.maxkey.constants.ConstsBoolean;
-import org.maxkey.crypto.jwt.encryption.service.JwtEncryptionAndDecryptionService;
-import org.maxkey.crypto.jwt.encryption.service.impl.RecipientJwtEncryptionAndDecryptionServiceBuilder;
-import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
-import org.maxkey.crypto.jwt.signer.service.impl.SymmetricSigningAndValidationServiceBuilder;
 import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.Apps;
+import org.maxkey.entity.apps.oauth2.provider.ClientDetails;
 import org.maxkey.persistence.service.AppsService;
 import org.maxkey.persistence.service.UserInfoService;
 import org.maxkey.util.AuthorizationHeaderUtils;
@@ -51,6 +52,7 @@ import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
+
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 
@@ -66,7 +68,6 @@ public class UserInfoEndpoint {
 	@Qualifier("oauth20TokenServices")
 	private DefaultTokenServices oauth20tokenServices;
 	
-	
 	@Autowired
 	@Qualifier("userInfoService")
 	private UserInfoService userInfoService;
@@ -74,25 +75,7 @@ public class UserInfoEndpoint {
 	@Autowired
 	@Qualifier("appsService")
 	protected AppsService appsService;
-	
-	@Autowired
-	@Qualifier("jwtSignerValidationService")
-	private JwtSigningAndValidationService jwtSignerValidationService;
-	
-	@Autowired
-	@Qualifier("jwtEncryptionService")
-	private JwtEncryptionAndDecryptionService jwtEnDecryptionService; 
-	
-	
-	
-	private SymmetricSigningAndValidationServiceBuilder symmetricJwtSignerServiceBuilder
-					=new SymmetricSigningAndValidationServiceBuilder();
 
-	private RecipientJwtEncryptionAndDecryptionServiceBuilder recipientJwtEnDecryptionServiceBuilder
-					=new RecipientJwtEncryptionAndDecryptionServiceBuilder();
-
-	OAuthDefaultUserInfoAdapter defaultOAuthUserInfoAdapter=new OAuthDefaultUserInfoAdapter();
-	
     @Autowired
     protected HttpResponseAdapter httpResponseAdapter;
 	
@@ -128,20 +111,29 @@ public class UserInfoEndpoint {
 				 principal=((SigninPrincipal)oAuth2Authentication.getUserAuthentication().getPrincipal()).getUsername();
 				 
 				 String client_id= oAuth2Authentication.getOAuth2Request().getClientId();
+				 ClientDetails clientDetails = 
+						 clientDetailsService.loadClientByClientId(client_id,true);
+				 
 				 UserInfo userInfo=queryUserInfo(principal);
-				 Apps app=appsService.get(client_id);
+				 Apps app = appsService.get(client_id);
 				 
 				 AbstractAuthorizeAdapter adapter;
 				 if(ConstsBoolean.isTrue(app.getIsAdapter())){
 					adapter =(AbstractAuthorizeAdapter)Instance.newInstance(app.getAdapter());
+					try {
+						BeanUtils.setProperty(adapter, "clientDetails", clientDetails);
+					} catch (IllegalAccessException | InvocationTargetException e) {
+						_logger.error("setProperty error . ", e);
+					}
 				 }else{
-					adapter =(AbstractAuthorizeAdapter)defaultOAuthUserInfoAdapter;
+					adapter =(AbstractAuthorizeAdapter)new OAuthDefaultUserInfoAdapter(clientDetails);
 				 }
+				 adapter.setAuthentication((SigninPrincipal)oAuth2Authentication.getUserAuthentication().getPrincipal());
+				 adapter.setUserInfo(userInfo);
+				 adapter.setApp(app);
 				 
-				String jsonData=adapter.generateInfo(
-				        (SigninPrincipal)oAuth2Authentication.getUserAuthentication().getPrincipal(),
-				        userInfo, app);
-				httpResponseAdapter.write(response,jsonData,"json"); 
+				Object jsonData = adapter.generateInfo();
+				httpResponseAdapter.write(response,jsonData.toString(),"json"); 
 			}catch(OAuth2Exception e){
 				HashMap<String,Object>authzException=new HashMap<String,Object>();
 				authzException.put(OAuth2Exception.ERROR, e.getOAuth2ErrorCode());
@@ -175,15 +167,4 @@ public class UserInfoEndpoint {
 		this.userInfoService = userInfoService;
 	}
 
-//
-//
-//	public void setJwtSignerValidationService(
-//			JwtSigningAndValidationService jwtSignerValidationService) {
-//		this.jwtSignerValidationService = jwtSignerValidationService;
-//	}
-//
-//	public void setJwtEnDecryptionService(
-//			JwtEncryptionAndDecryptionService jwtEnDecryptionService) {
-//		this.jwtEnDecryptionService = jwtEnDecryptionService;
-//	}
 }

+ 106 - 101
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/userinfo/endpoint/OpenIdConnectUserInfoEndpoint.java → maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/userinfo/endpoint/UserInfoOIDCEndpoint.java

@@ -17,6 +17,8 @@
 
 package org.maxkey.authz.oauth2.provider.userinfo.endpoint;
 
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
@@ -24,18 +26,19 @@ import java.util.Set;
 import java.util.UUID;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
 import org.maxkey.authn.SigninPrincipal;
+import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.authz.oauth2.common.OAuth2Constants;
 import org.maxkey.authz.oauth2.common.exceptions.OAuth2Exception;
 import org.maxkey.authz.oauth2.provider.ClientDetailsService;
 import org.maxkey.authz.oauth2.provider.OAuth2Authentication;
 import org.maxkey.authz.oauth2.provider.token.DefaultTokenServices;
 import org.maxkey.constants.ContentType;
-import org.maxkey.crypto.jwt.encryption.service.JwtEncryptionAndDecryptionService;
-import org.maxkey.crypto.jwt.encryption.service.impl.RecipientJwtEncryptionAndDecryptionServiceBuilder;
-import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
-import org.maxkey.crypto.jwt.signer.service.impl.SymmetricSigningAndValidationServiceBuilder;
-import org.maxkey.crypto.password.PasswordReciprocal;
+import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
+import org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
+import org.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
 import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.oauth2.provider.ClientDetails;
 import org.maxkey.persistence.service.AppsService;
@@ -54,14 +57,18 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.ResponseBody;
 import com.nimbusds.jose.EncryptionMethod;
+import com.nimbusds.jose.JOSEException;
 import com.nimbusds.jose.JWEAlgorithm;
 import com.nimbusds.jose.JWEHeader;
+import com.nimbusds.jose.JWEObject;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jose.JWSHeader;
-import com.nimbusds.jwt.EncryptedJWT;
+import com.nimbusds.jose.Payload;
 import com.nimbusds.jwt.JWT;
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.JWTClaimsSet.Builder;
+import com.nimbusds.jwt.PlainJWT;
+
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 
@@ -69,8 +76,8 @@ import com.nimbusds.jwt.SignedJWT;
 
 @Tag(name = "2-1-OAuth v2.0 API文档模块")
 @Controller
-public class OpenIdConnectUserInfoEndpoint {
-	final static Logger _logger = LoggerFactory.getLogger(OpenIdConnectUserInfoEndpoint.class);	
+public class UserInfoOIDCEndpoint {
+	final static Logger _logger = LoggerFactory.getLogger(UserInfoOIDCEndpoint.class);	
 	@Autowired
 	@Qualifier("oauth20JdbcClientDetailsService")
 	private ClientDetailsService clientDetailsService;
@@ -88,22 +95,6 @@ public class OpenIdConnectUserInfoEndpoint {
 	@Qualifier("appsService")
 	protected AppsService appsService;
 	
-	@Autowired
-	@Qualifier("jwtSignerValidationService")
-	private JwtSigningAndValidationService jwtSignerValidationService;
-	
-	@Autowired
-	@Qualifier("jwtEncryptionService")
-	private JwtEncryptionAndDecryptionService jwtEnDecryptionService; 
-	
-	
-	
-	private SymmetricSigningAndValidationServiceBuilder symmetricJwtSignerServiceBuilder
-					=new SymmetricSigningAndValidationServiceBuilder();
-
-	private RecipientJwtEncryptionAndDecryptionServiceBuilder recipientJwtEnDecryptionServiceBuilder
-					=new RecipientJwtEncryptionAndDecryptionServiceBuilder();
-
 	OAuthDefaultUserInfoAdapter defaultOAuthUserInfoAdapter=new OAuthDefaultUserInfoAdapter();
 	
     @Autowired
@@ -127,23 +118,31 @@ public class OpenIdConnectUserInfoEndpoint {
 			 
 			 principal=((SigninPrincipal)oAuth2Authentication.getPrincipal()).getUsername();
 			 
-			 Set<String >scopes=oAuth2Authentication.getOAuth2Request().getScope();
-			 ClientDetails clientDetails = clientDetailsService.loadClientByClientId(oAuth2Authentication.getOAuth2Request().getClientId());
+			 Set<String >scopes = oAuth2Authentication.getOAuth2Request().getScope();
+			 ClientDetails clientDetails = 
+					 clientDetailsService.loadClientByClientId(oAuth2Authentication.getOAuth2Request().getClientId(),true);
 			 
-			 UserInfo userInfo=queryUserInfo(principal);
-			 String userJson="";
+			 UserInfo userInfo = queryUserInfo(principal);
+			 String userJson = "";
 			 Builder jwtClaimsSetBuilder= new JWTClaimsSet.Builder();
 			 
 			 SigninPrincipal authentication = (SigninPrincipal)oAuth2Authentication.getUserAuthentication().getPrincipal();
 			 
-			 jwtClaimsSetBuilder.claim("sub", userInfo.getId());
+			 String subject = AbstractAuthorizeAdapter.getValueByUserAttr(userInfo, clientDetails.getSubject());
+			 _logger.debug("userId : {} , username : {} , displayName : {} , subject : {}" , 
+					 userInfo.getId(),
+					 userInfo.getUsername(),
+					 userInfo.getDisplayName(),
+					 subject);
+			 
+			 jwtClaimsSetBuilder.claim("sub", subject);
 			 jwtClaimsSetBuilder.claim("institution", userInfo.getInstId());
 			 jwtClaimsSetBuilder.claim(WebConstants.ONLINE_TICKET_NAME, authentication.getOnlineTicket().getTicketId());
 			 
 		 	if(scopes.contains("profile")){
 		 		jwtClaimsSetBuilder.claim("userId", userInfo.getId());
 		 		jwtClaimsSetBuilder.claim("user", userInfo.getUsername());
-		 		jwtClaimsSetBuilder.claim("name", userInfo.getUsername());
+		 		jwtClaimsSetBuilder.claim("name", userInfo.getDisplayName());
 		 		jwtClaimsSetBuilder.claim("preferred_username", userInfo.getDisplayName());
 		 		jwtClaimsSetBuilder.claim("given_name", userInfo.getGivenName());
 		 		jwtClaimsSetBuilder.claim("family_name", userInfo.getFamilyName());
@@ -151,7 +150,8 @@ public class OpenIdConnectUserInfoEndpoint {
 		 		jwtClaimsSetBuilder.claim("nickname", userInfo.getNickName());
 		 		jwtClaimsSetBuilder.claim("profile", "profile");
 		 		jwtClaimsSetBuilder.claim("picture", "picture");
-		 		jwtClaimsSetBuilder.claim("website", userInfo.getWebSite());
+		 		//jwtClaimsSetBuilder.claim("website", userInfo.getWebSite());
+		 		jwtClaimsSetBuilder.claim("displayName", userInfo.getDisplayName());
 		 		
 		 		jwtClaimsSetBuilder.claim("departmentId", userInfo.getDepartmentId());
 		 		jwtClaimsSetBuilder.claim("department", userInfo.getDepartment());
@@ -198,69 +198,88 @@ public class OpenIdConnectUserInfoEndpoint {
 					.jwtID(UUID.randomUUID().toString())// set a random NONCE in the middle of it
 					.audience(Arrays.asList(clientDetails.getClientId()))
 					.issueTime(new Date())
-					.expirationTime(new Date(new Date().getTime()+clientDetails.getAccessTokenValiditySeconds()*1000));
+					.expirationTime(new Date(new Date().getTime() + clientDetails.getAccessTokenValiditySeconds() * 1000));
+			
+			//default ContentType
+			response.setContentType(ContentType.APPLICATION_JWT_UTF8);
 			
 			JWTClaimsSet userInfoJWTClaims = jwtClaimsSetBuilder.build();
 			JWT userInfoJWT=null;
-			JWSAlgorithm signingAlg = jwtSignerValidationService.getDefaultSigningAlgorithm();
-			if (clientDetails.getUserInfoEncryptedAlgorithm() != null 
-			        && !clientDetails.getUserInfoEncryptedAlgorithm().equals("none")
-					&& clientDetails.getUserInfoEncryptionMethod() != null 
-					&& !clientDetails.getUserInfoEncryptionMethod().equals("none")
-					&&clientDetails.getJwksUri()!=null&&clientDetails.getJwksUri().length()>4
-					) {
-			    //需要加密
-			    response.setContentType(ContentType.APPLICATION_JWT_UTF8);
-				JwtEncryptionAndDecryptionService recipientJwtEnDecryptionService =
-						recipientJwtEnDecryptionServiceBuilder.serviceBuilder(clientDetails.getJwksUri());
+			
+			if(clientDetails.getUserInfoResponse().equalsIgnoreCase("NORMAL")) {
+				response.setContentType(ContentType.APPLICATION_JSON_UTF8);
+				userJson = userInfoJWTClaims.toString();
+			}else if (StringUtils.isNotBlank(clientDetails.getSignature()) 
+			        && !clientDetails.getSignature().equalsIgnoreCase("none")
+			        && clientDetails.getUserInfoResponse().equalsIgnoreCase("ENCRYPTION")) {
+			    //需要签名  signed ID token
+			    JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": ["+clientDetails.getSignatureKey()+"]}");
+				DefaultJwtSigningAndValidationService jwtSignerService = null;
+				try {
+					jwtSignerService = new DefaultJwtSigningAndValidationService(jwkSetKeyStore);
+				}catch(Exception e) {
+					_logger.error("Couldn't create Jwt Signing Service",e);
+				}
 				
-				if (recipientJwtEnDecryptionService != null) {
-					JWEAlgorithm jweAlgorithm=new JWEAlgorithm(clientDetails.getUserInfoEncryptedAlgorithm());
-					EncryptionMethod encryptionMethod=new EncryptionMethod(clientDetails.getUserInfoEncryptionMethod());
-					EncryptedJWT encryptedJWT = new EncryptedJWT(new JWEHeader(jweAlgorithm, encryptionMethod), userInfoJWTClaims);
-					recipientJwtEnDecryptionService.encryptJwt(encryptedJWT);
-					userJson=encryptedJWT.serialize();
-				}else{
-					_logger.error("Couldn't find encrypter for client: " + clientDetails.getClientId());
-					HashMap<String,Object>authzException=new HashMap<String,Object>();
-					authzException.put(OAuth2Exception.ERROR, "error");
-					authzException.put(OAuth2Exception.DESCRIPTION,"Couldn't find encrypter for client: " + clientDetails.getClientId());
-					return JsonUtils.gson2Json(authzException);
-				}	
-			}else if (clientDetails.getUserInfoSigningAlgorithm()!=null 
-			        && !clientDetails.getUserInfoSigningAlgorithm().equals("none")) {
-			    //需要签名
-			    response.setContentType(ContentType.APPLICATION_JWT_UTF8);
-				// signed ID token
-				if (signingAlg.equals(JWSAlgorithm.HS256)
-						|| signingAlg.equals(JWSAlgorithm.HS384)
-						|| signingAlg.equals(JWSAlgorithm.HS512)) {
-					// sign it with the client's secret
-					String client_secret=PasswordReciprocal.getInstance().decoder(clientDetails.getClientSecret());
-					
-					JwtSigningAndValidationService symmetricJwtSignerService =symmetricJwtSignerServiceBuilder.serviceBuilder(client_secret);
-					if(symmetricJwtSignerService!=null){
-						userInfoJWTClaims = new JWTClaimsSet.Builder(userInfoJWTClaims).claim("kid", "SYMMETRIC-KEY").build();
-						userInfoJWT = new SignedJWT(new JWSHeader(signingAlg), userInfoJWTClaims);
-						symmetricJwtSignerService.signJwt((SignedJWT) userInfoJWT);
-					}else{
-						_logger.error("Couldn't create symmetric validator for client " + clientDetails.getClientId() + " without a client secret");
+				jwtSignerService.setDefaultSignerKeyId(clientDetails.getClientId() + "_sig");
+				jwtSignerService.setDefaultSigningAlgorithmName(clientDetails.getSignature());
+				
+				JWSAlgorithm signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
+				_logger.trace(" signingAlg {}" , signingAlg);
+				userInfoJWTClaims = new JWTClaimsSet
+						.Builder(userInfoJWTClaims)
+						.claim("kid", jwtSignerService.getDefaultSignerKeyId())
+						.build();
+
+				userInfoJWT = new SignedJWT(new JWSHeader(signingAlg), userInfoJWTClaims);
+				// sign it with the server's key
+				jwtSignerService.signJwt((SignedJWT) userInfoJWT);
+				
+				userJson = userInfoJWT.serialize();
+			}else if (StringUtils.isNotBlank(clientDetails.getAlgorithm())
+			        && !clientDetails.getAlgorithm().equalsIgnoreCase("none")
+			        && clientDetails.getUserInfoResponse().equalsIgnoreCase("SIGNING")
+					) {
+			    //TODO: 需要加密
+			    JWKSetKeyStore jwkSetKeyStore_Enc = new JWKSetKeyStore("{\"keys\": ["+clientDetails.getAlgorithmKey()+"]}");
+				try {
+					DefaultJwtEncryptionAndDecryptionService jwtEncryptionService = 
+								new DefaultJwtEncryptionAndDecryptionService(jwkSetKeyStore_Enc);
+					jwtEncryptionService.setDefaultEncryptionKeyId(clientDetails.getClientId()  + "_enc");
+					jwtEncryptionService.setDefaultAlgorithm(clientDetails.getAlgorithm());
+					JWEAlgorithm encryptAlgorithm = null;
+					if(clientDetails.getAlgorithm().startsWith("RSA")) {
+						encryptAlgorithm = jwtEncryptionService.getDefaultAlgorithm();
+					}else {
+						encryptAlgorithm = JWEAlgorithm.DIR;
 					}
-				} else {
-					userInfoJWTClaims = new JWTClaimsSet.Builder(userInfoJWTClaims).claim("kid", jwtSignerValidationService.getDefaultSignerKeyId()).build();
-					userInfoJWT = new SignedJWT(new JWSHeader(signingAlg), userInfoJWTClaims);
-					// sign it with the server's key
-					jwtSignerValidationService.signJwt((SignedJWT) userInfoJWT);
+					_logger.trace(" encryptAlgorithm {}" , encryptAlgorithm);
+					EncryptionMethod encryptionMethod = 
+							jwtEncryptionService.parseEncryptionMethod(clientDetails.getEncryptionMethod());
+					
+					Payload payload = userInfoJWTClaims.toPayload();
+					
+					// Example Request JWT encrypted with RSA-OAEP-256 and 128-bit AES/GCM
+					//JWEHeader jweHeader = new JWEHeader(JWEAlgorithm.RSA1_5, EncryptionMethod.A128GCM);
+					
+					JWEObject jweObject = new JWEObject(
+						    new JWEHeader.Builder(new JWEHeader(encryptAlgorithm,encryptionMethod))
+						        .contentType("JWT") // required to indicate nested JWT
+						        .build(),
+						        payload);
+					
+					jwtEncryptionService.encryptJwt(jweObject);
+					userJson = jweObject.serialize();
+				} catch (NoSuchAlgorithmException | InvalidKeySpecException | JOSEException e) {
+					_logger.error("Couldn't create Jwt Encryption Exception", e);
 				}
-				userJson=userInfoJWT.serialize();
 			}else {
-			    //不需要加密和签名
-                response.setContentType(ContentType.APPLICATION_JSON_UTF8);
-                // unsigned ID token
-                //userInfoJWT = new PlainJWT(userInfoJWTClaims);
-                userJson=JsonUtils.gson2Json(jwtClaimsSetBuilder.getClaims());
+			    //不需要加密和签名  unsigned ID token
+                userInfoJWT = new PlainJWT(userInfoJWTClaims);
+                userJson = userInfoJWT.serialize();
             }
-			 
+			
+			_logger.trace("OpenID Connect Response {}",userJson);
 			return userJson;
 			 
 		}catch(OAuth2Exception e){
@@ -280,9 +299,7 @@ public class OpenIdConnectUserInfoEndpoint {
 	}
 
 	public  UserInfo queryUserInfo(String userId){
-		_logger.debug("userId : "+userId);
-		UserInfo userInfo = (UserInfo) userInfoService.findByUsername(userId);
-		return userInfo;
+		return (UserInfo) userInfoService.findByUsername(userId);
 	}
 
 
@@ -295,16 +312,4 @@ public class OpenIdConnectUserInfoEndpoint {
 	public void setUserInfoService(UserInfoService userInfoService) {
 		this.userInfoService = userInfoService;
 	}
-
-//
-//
-//	public void setJwtSignerValidationService(
-//			JwtSigningAndValidationService jwtSignerValidationService) {
-//		this.jwtSignerValidationService = jwtSignerValidationService;
-//	}
-//
-//	public void setJwtEnDecryptionService(
-//			JwtEncryptionAndDecryptionService jwtEnDecryptionService) {
-//		this.jwtEnDecryptionService = jwtEnDecryptionService;
-//	}
 }

+ 91 - 89
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oidc/idtoken/OIDCIdTokenEnhancer.java

@@ -20,11 +20,14 @@
  */
 package org.maxkey.authz.oidc.idtoken;
 
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.Set;
 import java.util.UUID;
 
+import org.apache.commons.lang3.StringUtils;
 import org.joda.time.DateTime;
 import org.joda.time.format.DateTimeFormat;
 import org.maxkey.authz.oauth2.common.DefaultOAuth2AccessToken;
@@ -34,11 +37,9 @@ import org.maxkey.authz.oauth2.provider.OAuth2Authentication;
 import org.maxkey.authz.oauth2.provider.OAuth2Request;
 import org.maxkey.authz.oauth2.provider.token.TokenEnhancer;
 import org.maxkey.configuration.oidc.OIDCProviderMetadata;
-import org.maxkey.crypto.jwt.encryption.service.JwtEncryptionAndDecryptionService;
-import org.maxkey.crypto.jwt.encryption.service.impl.RecipientJwtEncryptionAndDecryptionServiceBuilder;
-import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
-import org.maxkey.crypto.jwt.signer.service.impl.SymmetricSigningAndValidationServiceBuilder;
-import org.maxkey.crypto.password.PasswordReciprocal;
+import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
+import org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
+import org.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
 import org.maxkey.entity.apps.oauth2.provider.ClientDetails;
 import org.maxkey.web.WebContext;
 
@@ -47,16 +48,16 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Strings;
-import com.nimbusds.jose.Algorithm;
 import com.nimbusds.jose.EncryptionMethod;
+import com.nimbusds.jose.JOSEException;
 import com.nimbusds.jose.JWEAlgorithm;
 import com.nimbusds.jose.JWEHeader;
+import com.nimbusds.jose.JWEObject;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jose.JWSHeader;
-import com.nimbusds.jwt.EncryptedJWT;
+import com.nimbusds.jose.Payload;
 import com.nimbusds.jwt.JWT;
 import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.PlainJWT;
 import com.nimbusds.jwt.SignedJWT;
 
 /**
@@ -64,37 +65,20 @@ import com.nimbusds.jwt.SignedJWT;
  *
  */
 public class OIDCIdTokenEnhancer implements TokenEnhancer {
-	private final static Logger logger = LoggerFactory.getLogger(OIDCIdTokenEnhancer.class);
+	private final static Logger _logger = LoggerFactory.getLogger(OIDCIdTokenEnhancer.class);
 	
 	public  final static String ID_TOKEN_SCOPE="openid";
 
 	private OIDCProviderMetadata providerMetadata;
 	
-	private JwtSigningAndValidationService jwtSignerService;
-	
-	private JwtEncryptionAndDecryptionService jwtEnDecryptionService; 
+
 
 	private ClientDetailsService clientDetailsService;
-	
-	private SymmetricSigningAndValidationServiceBuilder symmetricJwtSignerServiceBuilder
-								=new SymmetricSigningAndValidationServiceBuilder();
-	
-	private RecipientJwtEncryptionAndDecryptionServiceBuilder recipientJwtEnDecryptionServiceBuilder
-					=new RecipientJwtEncryptionAndDecryptionServiceBuilder();
-	
+
 	public void setProviderMetadata(OIDCProviderMetadata providerMetadata) {
 		this.providerMetadata = providerMetadata;
 	}
 
-	public void setJwtSignerService(JwtSigningAndValidationService jwtSignerService) {
-		this.jwtSignerService = jwtSignerService;
-	}
-
-	public void setJwtEnDecryptionService(
-			JwtEncryptionAndDecryptionService jwtEnDecryptionService) {
-		this.jwtEnDecryptionService = jwtEnDecryptionService;
-	}
-
 	public void setClientDetailsService(ClientDetailsService clientDetailsService) {
 		this.clientDetailsService = clientDetailsService;
 	}
@@ -103,12 +87,28 @@ public class OIDCIdTokenEnhancer implements TokenEnhancer {
 	public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
 		OAuth2Request  request=authentication.getOAuth2Request();
 		if (request.getScope().contains(ID_TOKEN_SCOPE)) {//Enhance for OpenID Connect
-			ClientDetails clientDetails = clientDetailsService.loadClientByClientId(authentication.getOAuth2Request().getClientId());
+			ClientDetails clientDetails = 
+					clientDetailsService.loadClientByClientId(authentication.getOAuth2Request().getClientId(),true);
+			
+			DefaultJwtSigningAndValidationService jwtSignerService = null;
+			JWSAlgorithm signingAlg = null;
+			try {//jwtSignerService
+				if (StringUtils.isNotBlank(clientDetails.getSignature()) && !clientDetails.getSignature().equalsIgnoreCase("none")) {
+					JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": ["+clientDetails.getSignatureKey()+"]}");
+					jwtSignerService = new DefaultJwtSigningAndValidationService(jwkSetKeyStore);
+					jwtSignerService.setDefaultSignerKeyId(clientDetails.getClientId() + "_sig");
+					jwtSignerService.setDefaultSigningAlgorithmName(clientDetails.getSignature());
+					signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
+					_logger.trace(" signingAlg {}" , signingAlg);
+				}
+			}catch(Exception e) {
+				_logger.error("Couldn't create Jwt Signing Service",e);
+			}
 			
 			JWTClaimsSet.Builder builder=new JWTClaimsSet.Builder();
 			builder.subject(authentication.getName())
 		      .expirationTime(accessToken.getExpiration())
-		      .claim(providerMetadata.getIssuer(), true)
+		      .issuer(clientDetails.getIssuer())
 		      .issueTime(new Date())
 		      .audience(Arrays.asList(authentication.getOAuth2Request().getClientId()))
 		      .jwtID(UUID.randomUUID().toString());
@@ -118,8 +118,7 @@ public class OIDCIdTokenEnhancer implements TokenEnhancer {
 			 * @see http://openid.net/specs/openid-connect-core-1_0.html#SelfIssuedDiscovery
 			 *     7.  Self-Issued OpenID Provider
 			 */
-			
-			if(providerMetadata.getIssuer().equalsIgnoreCase("https://self-issued.me")){
+			if(providerMetadata.getIssuer().equalsIgnoreCase("https://self-issued.me") && jwtSignerService != null){
 				builder.claim("sub_jwk", jwtSignerService.getAllPublicKeys().get(jwtSignerService.getDefaultSignerKeyId()));
 			}
 			
@@ -127,76 +126,79 @@ public class OIDCIdTokenEnhancer implements TokenEnhancer {
 			if (request.getExtensions().containsKey("max_age")
 					|| (request.getExtensions().containsKey("idtoken")) // parse the ID Token claims (#473) -- for now assume it could be in there
 					) {
-				DateTime loginDate=DateTime.parse(WebContext.getUserInfo().getLastLoginTime(), DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
-				builder.claim("auth_time",  loginDate.getMillis()/ 1000);
+				DateTime loginDate = DateTime.parse(WebContext.getUserInfo().getLastLoginTime(), DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
+				builder.claim("auth_time",  loginDate.getMillis()/1000);
 			}
 			
 			String nonce = (String)request.getExtensions().get("nonce");
 			if (!Strings.isNullOrEmpty(nonce)) {
 				builder.claim("nonce", nonce);
 			}
-			
-			JWSAlgorithm signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
-			SignedJWT signed = new SignedJWT(new JWSHeader(signingAlg), builder.build());
-			Set<String> responseTypes = request.getResponseTypes();
-
-			if (responseTypes.contains("token")) {
-				// calculate the token hash
-				Base64URL at_hash = IdTokenHashUtils.getAccessTokenHash(signingAlg, signed);
-				builder.claim("at_hash", at_hash);
-			}
-			logger.debug("idClaims "+builder.build());
-			
-			JWT idToken=null;
-			if (clientDetails.getIdTokenEncryptedAlgorithm() != null && !clientDetails.getIdTokenEncryptedAlgorithm().equals("none")
-					&& clientDetails.getIdTokenEncryptionMethod() != null && !clientDetails.getIdTokenEncryptionMethod().equals("none")
-					&&clientDetails.getJwksUri()!=null&&clientDetails.getJwksUri().length()>4) {
-
-				JwtEncryptionAndDecryptionService recipientJwtEnDecryptionService =
-						recipientJwtEnDecryptionServiceBuilder.serviceBuilder(clientDetails.getJwksUri());
-				
-				if (recipientJwtEnDecryptionService != null) {
-					JWEAlgorithm jweAlgorithm=new JWEAlgorithm(clientDetails.getIdTokenEncryptedAlgorithm());
-					EncryptionMethod encryptionMethod=new EncryptionMethod(clientDetails.getIdTokenEncryptionMethod());
-					EncryptedJWT encryptedJWT = new EncryptedJWT(new JWEHeader(jweAlgorithm, encryptionMethod), builder.build());
-					recipientJwtEnDecryptionService.encryptJwt(encryptedJWT);
-					idToken=encryptedJWT;
-				}else{
-					logger.error("Couldn't create Jwt Encryption Service");
+			if(jwtSignerService != null) {
+				SignedJWT signed = new SignedJWT(new JWSHeader(signingAlg), builder.build());
+				Set<String> responseTypes = request.getResponseTypes();
+	
+				if (responseTypes.contains("token")) {
+					// calculate the token hash
+					Base64URL at_hash = IdTokenHashUtils.getAccessTokenHash(signingAlg, signed);
+					builder.claim("at_hash", at_hash);
 				}
-			} else {
-				if (signingAlg==null||signingAlg.equals(Algorithm.NONE)) {
-					// unsigned ID token
-					idToken = new PlainJWT(builder.build());
-				} else {
+				_logger.debug("idClaims {}",builder.build());
+			}
+			String idTokenString = "";
+			if (StringUtils.isNotBlank(clientDetails.getSignature()) 
+					&& !clientDetails.getSignature().equalsIgnoreCase("none")) {
+				try {
+					builder.claim("kid", jwtSignerService.getDefaultSignerKeyId());
 					// signed ID token
-					if (signingAlg.equals(JWSAlgorithm.HS256)
-							|| signingAlg.equals(JWSAlgorithm.HS384)
-							|| signingAlg.equals(JWSAlgorithm.HS512)) {
-						// sign it with the client's secret
-						String client_secret=PasswordReciprocal.getInstance().decoder(clientDetails.getClientSecret());
-						
-						JwtSigningAndValidationService symmetricJwtSignerService =symmetricJwtSignerServiceBuilder.serviceBuilder(client_secret);
-						if(symmetricJwtSignerService!=null){
-							builder.claim("kid", "SYMMETRIC-KEY");
-							idToken = new SignedJWT(new JWSHeader(signingAlg), builder.build());
-							symmetricJwtSignerService.signJwt((SignedJWT) idToken);
-						}else {
-							logger.error("Couldn't create symmetric validator for client " + clientDetails.getClientId() + " without a client secret");
-						}
-					} else {
-						builder.claim("kid", jwtSignerService.getDefaultSignerKeyId());
-						idToken = new SignedJWT(new JWSHeader(signingAlg), builder.build());
-						// sign it with the server's key
-						jwtSignerService.signJwt((SignedJWT) idToken);
+					JWT idToken = new SignedJWT(new JWSHeader(signingAlg), builder.build());
+					// sign it with the server's key
+					jwtSignerService.signJwt((SignedJWT) idToken);
+					idTokenString = idToken.serialize();
+					_logger.debug("idToken {}",idTokenString);
+				}catch(Exception e) {
+					_logger.error("Couldn't create Jwt Signing Exception",e);
+				}
+			}else if (StringUtils.isNotBlank(clientDetails.getAlgorithm()) 
+					&& !clientDetails.getAlgorithm().equalsIgnoreCase("none")) {
+				JWKSetKeyStore jwkSetKeyStore_Enc = new JWKSetKeyStore("{\"keys\": ["+clientDetails.getAlgorithmKey()+"]}");
+				try {
+					DefaultJwtEncryptionAndDecryptionService jwtEncryptionService = 
+								new DefaultJwtEncryptionAndDecryptionService(jwkSetKeyStore_Enc);
+					jwtEncryptionService.setDefaultEncryptionKeyId(clientDetails.getClientId()  + "_enc");
+					jwtEncryptionService.setDefaultAlgorithm(clientDetails.getAlgorithm());
+					JWEAlgorithm encryptAlgorithm = null;
+					if(clientDetails.getAlgorithm().startsWith("RSA")) {
+						encryptAlgorithm = jwtEncryptionService.getDefaultAlgorithm();
+					}else {
+						encryptAlgorithm = JWEAlgorithm.DIR;
 					}
+					_logger.trace(" encryptAlgorithm {}" , encryptAlgorithm);
+					EncryptionMethod encryptionMethod = 
+							jwtEncryptionService.parseEncryptionMethod(clientDetails.getEncryptionMethod());
+					
+					Payload payload = builder.build().toPayload();
+					// Example Request JWT encrypted with RSA-OAEP-256 and 128-bit AES/GCM
+					//JWEHeader jweHeader = new JWEHeader(JWEAlgorithm.RSA1_5, EncryptionMethod.A128GCM);
+					JWEObject jweObject = new JWEObject(
+						    new JWEHeader.Builder(new JWEHeader(encryptAlgorithm,encryptionMethod))
+						        .contentType("JWT") // required to indicate nested JWT
+						        .build(),
+						        payload);
+					jwtEncryptionService.encryptJwt(jweObject);
+					idTokenString = jweObject.serialize();
+				} catch (NoSuchAlgorithmException | InvalidKeySpecException | JOSEException e) {
+					_logger.error("Couldn't create Jwt Encryption Exception", e);
 				}
+			}else {
+				//not need a PlainJWT idToken
+				//JWT idToken = new PlainJWT(builder.build());
+				//idTokenString = idToken.serialize();
 			}
-			logger.debug("idToken "+idToken);
 			
 			accessToken = new DefaultOAuth2AccessToken(accessToken);
-			if(idToken!=null){
-				accessToken.getAdditionalInformation().put("id_token", idToken.serialize());
+			if(StringUtils.isNotBlank(idTokenString)){
+				accessToken.getAdditionalInformation().put("id_token", idTokenString);
 			}
 		}
 		return accessToken;

+ 0 - 4
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/autoconfigure/Oauth20AutoConfiguration.java

@@ -166,13 +166,9 @@ public class Oauth20AutoConfiguration implements InitializingBean {
      */
     @Bean(name = "tokenEnhancer")
     public OIDCIdTokenEnhancer tokenEnhancer(
-            DefaultJwtSigningAndValidationService jwtSignerValidationService,
-            DefaultJwtEncryptionAndDecryptionService jwtEncryptionService,
             OIDCProviderMetadataDetails oidcProviderMetadata,
             ClientDetailsService oauth20JdbcClientDetailsService) {
         OIDCIdTokenEnhancer tokenEnhancer = new OIDCIdTokenEnhancer();
-        tokenEnhancer.setJwtSignerService(jwtSignerValidationService);
-        tokenEnhancer.setJwtEnDecryptionService(jwtEncryptionService);
         tokenEnhancer.setClientDetailsService(oauth20JdbcClientDetailsService);
         tokenEnhancer.setProviderMetadata(oidcProviderMetadata);
         _logger.debug("OIDC IdToken Enhancer init.");

+ 14 - 30
maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/TokenBasedAuthorizeEndpoint.java

@@ -57,9 +57,7 @@ public class TokenBasedAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 	final static Logger _logger = LoggerFactory.getLogger(TokenBasedAuthorizeEndpoint.class);
 	@Autowired
 	AppsTokenBasedDetailsService tokenBasedDetailsService;
-	
-	TokenBasedDefaultAdapter defaultTokenBasedAdapter=new TokenBasedDefaultAdapter();
-	
+
 	@Autowired
 	ApplicationConfig applicationConfig;
 	
@@ -84,42 +82,28 @@ public class TokenBasedAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 		if(ConstsBoolean.isTrue(tokenBasedDetails.getIsAdapter())){
 			adapter =(AbstractAuthorizeAdapter)Instance.newInstance(tokenBasedDetails.getAdapter());
 		}else{
-			adapter =(AbstractAuthorizeAdapter)defaultTokenBasedAdapter;
+			adapter =(AbstractAuthorizeAdapter)new TokenBasedDefaultAdapter();
 		}
+		adapter.setAuthentication((SigninPrincipal)WebContext.getAuthentication().getPrincipal());
+		adapter.setUserInfo(WebContext.getUserInfo());
+		adapter.setApp(tokenBasedDetails);
 		
-		String tokenData=adapter.generateInfo(
-		        (SigninPrincipal)WebContext.getAuthentication().getPrincipal(),
-				WebContext.getUserInfo(), 
-				tokenBasedDetails);
+		adapter.generateInfo();
 		
-		String encryptTokenData=adapter.encrypt(
-				tokenData, 
+		adapter.encrypt(
+				null, 
 				tokenBasedDetails.getAlgorithmKey(), 
 				tokenBasedDetails.getAlgorithm());
 		
-		String signTokenData=adapter.sign(
-				encryptTokenData, 
-				tokenBasedDetails);
-		
 		if(tokenBasedDetails.getTokenType().equalsIgnoreCase("POST")) {
-			modelAndView=adapter.authorize(
-					WebContext.getUserInfo(), 
-					tokenBasedDetails, 
-					signTokenData, 
-					modelAndView);
-			
-			return modelAndView;
+			return adapter.authorize(modelAndView);
 		}else {
+			_logger.debug("Cookie Name : {}" ,tokenBasedDetails.getCookieName());
 			
-			String cookieValue="";
-			cookieValue=signTokenData;
-			
-			_logger.debug("Cookie Name : "+tokenBasedDetails.getCookieName());
-			
-			Cookie cookie= new Cookie(tokenBasedDetails.getCookieName(),cookieValue);
+			Cookie cookie= new Cookie(tokenBasedDetails.getCookieName(),adapter.serialize());
 			
-			Integer maxAge=Integer.parseInt(tokenBasedDetails.getExpires())*60;
-			_logger.debug("Cookie Max Age :"+maxAge+" seconds.");
+			Integer maxAge=Integer.parseInt(tokenBasedDetails.getExpires()) * 60;
+			_logger.debug("Cookie Max Age : {} seconds.",maxAge);
 			cookie.setMaxAge(maxAge);
 			
 			cookie.setPath("/");
@@ -128,7 +112,7 @@ public class TokenBasedAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 			//tomcat 8.5
 			cookie.setDomain(applicationConfig.getBaseDomainName());
 			
-			_logger.debug("Sub Domain Name : "+"."+applicationConfig.getBaseDomainName());
+			_logger.debug("Sub Domain Name : .{}",applicationConfig.getBaseDomainName());
 			response.addCookie(cookie);
 			
 			if(tokenBasedDetails.getRedirectUri().indexOf(applicationConfig.getBaseDomainName())>-1){

+ 17 - 10
maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/adapter/TokenBasedDefaultAdapter.java

@@ -20,9 +20,7 @@ package org.maxkey.authz.token.endpoint.adapter;
 import java.util.Date;
 import java.util.HashMap;
 
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.AppsTokenBasedDetails;
 import org.maxkey.util.DateUtils;
 import org.maxkey.util.JsonUtils;
@@ -34,8 +32,10 @@ import org.springframework.web.servlet.ModelAndView;
 
 public class TokenBasedDefaultAdapter extends AbstractAuthorizeAdapter {
 	final static Logger _logger = LoggerFactory.getLogger(TokenBasedDefaultAdapter.class);
+	String token = "";
+	
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		AppsTokenBasedDetails details=(AppsTokenBasedDetails)app;
 		HashMap<String,String> beanMap=new HashMap<String,String>();
 		
@@ -90,24 +90,31 @@ public class TokenBasedDefaultAdapter extends AbstractAuthorizeAdapter {
 		
 		beanMap.put("expires", expiresString);
 		
-		String jsonString=JsonUtils.object2Json(beanMap);
-		_logger.debug("Token : "+jsonString);
+		token = JsonUtils.object2Json(beanMap);
+		_logger.debug("Token : {}",token);
 		
-		return jsonString;
+		return token;
 	}
 
 	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return super.encrypt(data, algorithmKey, algorithm);
+	public Object encrypt(Object data, String algorithmKey, String algorithm) {
+		token = super.encrypt(token, algorithmKey, algorithm).toString();
+		return token;
 	}
 
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		modelAndView.setViewName("authorize/tokenbased_sso_submint");
 		AppsTokenBasedDetails details=(AppsTokenBasedDetails)app;
 		modelAndView.addObject("action", details.getRedirectUri());
 		
-		modelAndView.addObject("token",data );
+		modelAndView.addObject("token",token );
 		return modelAndView;
 	}
+
+	@Override
+	public String serialize() {
+		return token;
+	}
+	
 }

+ 15 - 10
maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/adapter/TokenBasedSimpleAdapter.java

@@ -19,9 +19,7 @@ package org.maxkey.authz.token.endpoint.adapter;
 
 import java.util.Date;
 
-import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.AppsTokenBasedDetails;
 import org.maxkey.util.DateUtils;
 import org.slf4j.Logger;
@@ -30,8 +28,10 @@ import org.springframework.web.servlet.ModelAndView;
 
 public class TokenBasedSimpleAdapter extends AbstractAuthorizeAdapter {
 	final static Logger _logger = LoggerFactory.getLogger(TokenBasedSimpleAdapter.class);
+	String token = "";
+	
 	@Override
-	public String generateInfo(SigninPrincipal authentication,UserInfo userInfo,Object app) {
+	public Object generateInfo() {
 		AppsTokenBasedDetails details=(AppsTokenBasedDetails)app;
 	
 		String tokenUsername = userInfo.getUsername();
@@ -62,26 +62,31 @@ public class TokenBasedSimpleAdapter extends AbstractAuthorizeAdapter {
 		_logger.debug("UTC  current Date : "+DateUtils.toUtc(currentDate));
 		
 		
-		String tokenString=tokenUsername+"@@"+DateUtils.toUtc(currentDate);
-		_logger.debug("Token : "+tokenString);
+		token = tokenUsername+"@@"+DateUtils.toUtc(currentDate);
+		_logger.debug("Token : {}",token);
 		
-		return tokenString;
+		return token;
 	}
 
 	@Override
-	public String encrypt(String data, String algorithmKey, String algorithm) {
-		return super.encrypt(data, algorithmKey, algorithm);
+	public Object encrypt(Object data, String algorithmKey, String algorithm) {
+		token = super.encrypt(token, algorithmKey, algorithm).toString();
+		return token;
 	}
 
 	@Override
-	public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
+	public ModelAndView authorize(ModelAndView modelAndView) {
 		modelAndView.setViewName("authorize/tokenbased_sso_submint");
 		AppsTokenBasedDetails details=(AppsTokenBasedDetails)app;
 		modelAndView.addObject("action", details.getRedirectUri());
 		
-		modelAndView.addObject("token",data);
+		modelAndView.addObject("token",token);
 		
 		return modelAndView;
 	}
 
+	@Override
+	public String serialize() {
+		return token;
+	}
 }

+ 1 - 1
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/authorize/jwt_sso_submint.ftl

@@ -11,7 +11,7 @@
 		<table style="width:100%">
 			<tr>
 				<td>token</td>
-				<td><input type="text" id="tokenbased_token" name="jwt" value="${token}" /></td>
+				<td><input type="text" id="tokenbased_token" name="${jwtName}" value="${token}" /></td>
 			</tr>
 			
 			<tr>

+ 51 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/ApplicationsController.java

@@ -37,6 +37,16 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.ModelAndView;
 
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWEAlgorithm;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.Requirement;
+import com.nimbusds.jose.jwk.KeyUse;
+import com.nimbusds.jose.jwk.OctetSequenceKey;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.jose.jwk.gen.OctetSequenceKeyGenerator;
+import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
+
 
 @Controller
 @RequestMapping(value={"/apps"})
@@ -177,7 +187,7 @@ public class ApplicationsController extends BaseAppContorller {
 	
 	@ResponseBody
 	@RequestMapping(value = { "/generate/secret/{type}" })
-	public String generateSecret(@PathVariable("type") String type) {
+	public String generateSecret(@PathVariable("type") String type,@RequestParam(name="id",required=false) String id) throws JOSEException {
 		String secret="";
 		type=type.toLowerCase();
 		if(type.equals("des")){
@@ -188,6 +198,46 @@ public class ApplicationsController extends BaseAppContorller {
 			secret=ReciprocalUtils.generateKey(ReciprocalUtils.Algorithm.AES);
 		}else if(type.equals("blowfish")){
 			secret=ReciprocalUtils.generateKey(ReciprocalUtils.Algorithm.Blowfish);
+		}else if(type.equalsIgnoreCase("RS256")
+				||type.equalsIgnoreCase("RS384")
+				||type.equalsIgnoreCase("RS512")) {
+			RSAKey rsaJWK = new RSAKeyGenerator(2048)
+				    .keyID(id + "_sig")
+				    .keyUse(KeyUse.SIGNATURE)
+				    .algorithm(new JWSAlgorithm(type.toUpperCase(), Requirement.OPTIONAL))
+				    .generate();
+			secret = rsaJWK.toJSONString();
+		}else if(type.equalsIgnoreCase("HS256")
+				||type.equalsIgnoreCase("HS384")
+				||type.equalsIgnoreCase("HS512")) {
+			OctetSequenceKey octKey=  new OctetSequenceKeyGenerator(2048)
+					.keyID(id + "_sig")
+					.keyUse(KeyUse.SIGNATURE)
+					.algorithm(new JWSAlgorithm(type.toUpperCase(), Requirement.OPTIONAL))
+					.generate();
+			secret = octKey.toJSONString();
+		}else if(type.equalsIgnoreCase("RSA1_5")
+				||type.equalsIgnoreCase("RSA_OAEP")
+				||type.equalsIgnoreCase("RSA-OAEP-256")) {
+			RSAKey rsaJWK = new RSAKeyGenerator(2048)
+				    .keyID(id + "_enc")
+				    .keyUse(KeyUse.ENCRYPTION)
+				    .algorithm(new JWEAlgorithm(type.toUpperCase(), Requirement.OPTIONAL))
+				    .generate();
+			secret = rsaJWK.toJSONString();
+		}else if(type.equalsIgnoreCase("A128KW")
+				||type.equalsIgnoreCase("A192KW")
+				||type.equalsIgnoreCase("A256KW")
+				||type.equalsIgnoreCase("A128GCMKW")
+				||type.equalsIgnoreCase("A192GCMKW")
+				||type.equalsIgnoreCase("A256GCMKW")) {
+			int keyLength = Integer.parseInt(type.substring(1, 4));
+			OctetSequenceKey octKey=  new OctetSequenceKeyGenerator(keyLength)
+					.keyID(id + "_enc")
+					.keyUse(KeyUse.ENCRYPTION)
+					.algorithm(new JWEAlgorithm(type.toUpperCase(), Requirement.OPTIONAL))
+					.generate();
+			secret = octKey.toJSONString();
 		}else{
 			secret=ReciprocalUtils.generateKey("");
 		}

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/BasicDetailsController.java

@@ -46,7 +46,7 @@ public class BasicDetailsController  extends BaseAppContorller {
 		Apps appDetails =new Apps();
 		appDetails.setId(appDetails.generateId());
 		appDetails.setProtocol(ConstsProtocols.BASIC);
-		appDetails.setSecret(ReciprocalUtils.generateKey(ReciprocalUtils.Algorithm.DES));
+		appDetails.setSecret(ReciprocalUtils.generateKey(""));
 		modelAndView.addObject("model",appDetails);
 		return modelAndView;
 	}

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/CasDetailsController.java

@@ -50,7 +50,7 @@ public class CasDetailsController  extends BaseAppContorller {
 		AppsCasDetails casDetails =new AppsCasDetails();
 		casDetails.setId(casDetails.generateId());
 		casDetails.setProtocol(ConstsProtocols.CAS);
-		casDetails.setSecret(ReciprocalUtils.generateKey(ReciprocalUtils.Algorithm.DES));
+		casDetails.setSecret(ReciprocalUtils.generateKey(""));
 		modelAndView.addObject("model",casDetails);
 		return modelAndView;
 	}

+ 0 - 5
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/JwtDetailsController.java

@@ -52,7 +52,6 @@ public class JwtDetailsController  extends BaseAppContorller {
 		jwtDetails.setId(jwtDetails.generateId());
 		jwtDetails.setProtocol(ConstsProtocols.JWT);
 		jwtDetails.setSecret(ReciprocalUtils.generateKey(ReciprocalUtils.Algorithm.AES));
-		jwtDetails.setAlgorithmKey(jwtDetails.getSecret());
 		jwtDetails.setUserPropertys("userPropertys");
 		modelAndView.addObject("model",jwtDetails);
 		return modelAndView;
@@ -65,7 +64,6 @@ public class JwtDetailsController  extends BaseAppContorller {
 		
 		transform(jwtDetails);
 		
-		jwtDetails.setAlgorithmKey(jwtDetails.getSecret());
 		jwtDetails.setInstId(WebContext.getUserInfo().getInstId());
 		if (jwtDetailsService.insert(jwtDetails)&&appsService.insertApp(jwtDetails)) {
 			  new Message(WebContext.getI18nValue(ConstsOperateMessage.INSERT_SUCCESS),MessageType.success);
@@ -81,8 +79,6 @@ public class JwtDetailsController  extends BaseAppContorller {
 		ModelAndView modelAndView=new ModelAndView("apps/jwt/appUpdate");
 		AppsJwtDetails jwtDetails=jwtDetailsService.getAppDetails(id);
 		decoderSecret(jwtDetails);
-		String algorithmKey=passwordReciprocal.decoder(jwtDetails.getAlgorithmKey());
-		jwtDetails.setAlgorithmKey(algorithmKey);
 		WebContext.setAttribute(jwtDetails.getId(), jwtDetails.getIcon());
 
 		modelAndView.addObject("model",jwtDetails);
@@ -98,7 +94,6 @@ public class JwtDetailsController  extends BaseAppContorller {
 		//
 		_logger.debug("-update  application :" + jwtDetails);
 		transform(jwtDetails);
-		jwtDetails.setAlgorithmKey(jwtDetails.getSecret());
 		jwtDetails.setInstId(WebContext.getUserInfo().getInstId());
 		if (jwtDetailsService.update(jwtDetails)&&appsService.updateApp(jwtDetails)) {
 			  new Message(WebContext.getI18nValue(ConstsOperateMessage.UPDATE_SUCCESS),MessageType.success);

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/OAuth20DetailsController.java

@@ -87,7 +87,7 @@ public class OAuth20DetailsController  extends BaseAppContorller {
 	@RequestMapping(value = { "/forwardUpdate/{id}" })
 	public ModelAndView forwardUpdate(@PathVariable("id") String id) {
 		ModelAndView modelAndView=new ModelAndView("apps/oauth20/appUpdate");
-		BaseClientDetails baseClientDetails=(BaseClientDetails)oauth20JdbcClientDetailsService.loadClientByClientId(id);
+		BaseClientDetails baseClientDetails=(BaseClientDetails)oauth20JdbcClientDetailsService.loadClientByClientId(id,false);
 		Apps application=appsService.get(id);//
 		decoderSecret(application);
 		AppsOAuth20Details oauth20Details=new AppsOAuth20Details(application,baseClientDetails);

+ 18 - 8
maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message.properties

@@ -333,6 +333,7 @@ apps.formbased.parameter.value=\u53C2\u6570\u503C
 apps.cas.info=CAS\u8BA4\u8BC1
 apps.cas.service=\u670D\u52A1
 apps.cas.callbackUrl=\u56DE\u8C03\u5730\u5740
+apps.cas.casUser=\u8FD4\u56DE\u8D26\u53F7
 apps.cas.expires=\u8FC7\u671F\u65F6\u95F4
 #tokenbased
 apps.tokenbased.info=\u4EE4\u724C\u8BA4\u8BC1
@@ -346,10 +347,16 @@ apps.tokenbased.expires=\u8FC7\u671F\u65F6\u95F4
 #JWT
 apps.jwt.info=JWT\u8BA4\u8BC1
 apps.jwt.redirectUri=\u8BA4\u8BC1\u5730\u5740
+apps.jwt.subject=\u4E3B\u9898(Subject)
+apps.jwt.audience=\u53D7\u4F17(Audience)
+apps.jwt.issuer=\u7B7E\u53D1\u4EBA(Issuer)
 apps.jwt.tokenType=\u4EE4\u724C\u7C7B\u578B
-apps.jwt.cookieName=Cookie\u540D\u79F0
+apps.jwt.jwtName=\u540D\u79F0
 apps.jwt.algorithm=\u52A0\u5BC6\u7B97\u6CD5
 apps.jwt.algorithmKey=\u79D8\u94A5
+apps.jwt.encryptionMethod=\u52A0\u5BC6\u65B9\u6CD5
+apps.jwt.signature=\u7B7E\u540D\u7B97\u6CD5
+apps.jwt.signatureKey=\u7B7E\u540D\u5BC6\u94A5
 apps.jwt.content=\u4EE4\u724C\u5185\u5BB9
 apps.jwt.expires=\u8FC7\u671F\u65F6\u95F4
 #SAML
@@ -404,14 +411,17 @@ apps.oauth.approvalPrompt=\u8BB8\u53EF\u786E\u8BA4
 apps.oauth.v2.0.info=OAuth 2.0 \u8BA4\u8BC1\u914D\u7F6E
 apps.oauth.GrantTypes=\u6388\u6743\u65B9\u5F0F
 apps.oauth.v2.0.clientId=Client Id
+apps.oauth.subject=\u4E3B\u9898(Subject)
 apps.oauth.connect.info=OpenID Connect \u8BA4\u8BC1\u914D\u7F6E
-apps.oauth.connect.idTokenSigningAlgorithm=idToken\u7B7E\u540D\u7B97\u6CD5
-apps.oauth.connect.userInfoSigningAlgorithm=\u7528\u6237\u7B7E\u540D\u7B97\u6CD5
-apps.oauth.connect.jwksUri=JWKS\u5730\u5740
-apps.oauth.connect.idTokenEncryptedAlgorithm=idToken\u52A0\u5BC6\u7B97\u6CD5
-apps.oauth.connect.userInfoEncryptedAlgorithm=\u7528\u6237\u52A0\u5BC6\u7B97\u6CD5
-apps.oauth.connect.idTokenEncryptionMethod=idToken\u52A0\u5BC6\u65B9\u6CD5
-apps.oauth.connect.userInfoEncryptionMethod=\u7528\u6237\u52A0\u5BC6\u65B9\u6CD5
+apps.oauth.connect.algorithm=\u52A0\u5BC6\u7B97\u6CD5
+apps.oauth.connect.algorithmKey=\u79D8\u94A5
+apps.oauth.connect.encryptionMethod=\u52A0\u5BC6\u65B9\u6CD5
+apps.oauth.connect.signature=\u7B7E\u540D\u7B97\u6CD5
+apps.oauth.connect.signatureKey=\u7B7E\u540D\u5BC6\u94A5
+apps.oauth.connect.audience=\u53D7\u4F17(Audience)
+apps.oauth.connect.issuer=\u7B7E\u53D1\u4EBA(Issuer)
+apps.oauth.connect.userInfoResponse=\u7528\u6237\u63A5\u53E3\u7C7B\u578B
+
 #group
 group.id=\u7EC4\u7F16\u7801
 group.name=\u7528\u6237\u7EC4

+ 17 - 8
maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message_en.properties

@@ -338,6 +338,7 @@ apps.formbased.parameter.value=value
 apps.cas.info=CAS Info
 apps.cas.service=Service
 apps.cas.callbackUrl=CallbackUrl
+apps.cas.casUser=CasUser
 apps.cas.expires=Expires
 #tokenbased
 apps.tokenbased.info=tokenbased Info
@@ -351,10 +352,16 @@ apps.tokenbased.expires=expires
 #jwt
 apps.jwt.info=JWT Info
 apps.jwt.redirectUri=redirectUri
+apps.jwt.subject=subject
+apps.jwt.audience=audience
+apps.jwt.issuer=issuer
 apps.jwt.tokenType=tokenType
-apps.jwt.cookieName=Cookie Name
+apps.jwt.jwtName=jwtName
 apps.jwt.algorithm=algorithm
+apps.jwt.encryptionMethod=encryptionMethod
 apps.jwt.algorithmKey=algorithmKey
+apps.jwt.signature=signature
+apps.jwt.signatureKey=signatureKey
 apps.jwt.content=content
 apps.jwt.expires=expires
 #SAML
@@ -409,14 +416,16 @@ apps.oauth.approvalPrompt=approvalPrompt
 apps.oauth.v2.0.info=OAuth 2.0 Info
 apps.oauth.GrantTypes=GrantTypes
 apps.oauth.v2.0.clientId=Client Id
+apps.oauth.subject=Subject
 apps.oauth.connect.info=OpenID Connect Info
-apps.oauth.connect.idTokenSigningAlgorithm=idTokenSigningAlgorithm
-apps.oauth.connect.userInfoSigningAlgorithm=userInfoSigningAlgorithm
-apps.oauth.connect.jwksUri=jwksUri
-apps.oauth.connect.idTokenEncryptedAlgorithm=idTokenEncryptedAlgorithm
-apps.oauth.connect.userInfoEncryptedAlgorithm=userInfoEncryptedAlgorithm
-apps.oauth.connect.idTokenEncryptionMethod=idTokenEncryptionMethod
-apps.oauth.connect.userInfoEncryptionMethod=idTokenEncryptionMethod
+apps.oauth.connect.algorithm=Algorithm
+apps.oauth.connect.algorithmKey=AlgorithmKey
+apps.oauth.connect.encryptionMethod=EncryptionMethod
+apps.oauth.connect.signature=Signature
+apps.oauth.connect.signatureKey=SignatureKey
+apps.oauth.connect.audience=Audience
+apps.oauth.connect.issuer=Issuer
+apps.oauth.connect.userInfoResponse=UserInfoResponse
 
 #group
 group.id=id

+ 18 - 9
maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message_zh_CN.properties

@@ -333,6 +333,7 @@ apps.formbased.parameter.value=\u53C2\u6570\u503C
 apps.cas.info=CAS\u8BA4\u8BC1
 apps.cas.service=\u670D\u52A1
 apps.cas.callbackUrl=\u56DE\u8C03\u5730\u5740
+apps.cas.casUser=\u8FD4\u56DE\u8D26\u53F7
 apps.cas.expires=\u8FC7\u671F\u65F6\u95F4
 #tokenbased
 apps.tokenbased.info=\u4EE4\u724C\u8BA4\u8BC1
@@ -346,10 +347,16 @@ apps.tokenbased.expires=\u8FC7\u671F\u65F6\u95F4
 #JWT
 apps.jwt.info=JWT\u8BA4\u8BC1
 apps.jwt.redirectUri=\u8BA4\u8BC1\u5730\u5740
+apps.jwt.subject=\u4E3B\u9898(Subject)
+apps.jwt.audience=\u53D7\u4F17(Audience)
+apps.jwt.issuer=\u7B7E\u53D1\u4EBA(Issuer)
 apps.jwt.tokenType=\u4EE4\u724C\u7C7B\u578B
-apps.jwt.cookieName=Cookie\u540D\u79F0
+apps.jwt.jwtName=\u540D\u79F0
 apps.jwt.algorithm=\u52A0\u5BC6\u7B97\u6CD5
-apps.jwt.algorithmKey=\u79D8\u94A5
+apps.jwt.encryptionMethod=\u52A0\u5BC6\u65B9\u6CD5
+apps.jwt.algorithmKey=\u52A0\u5BC6\u79D8\u94A5
+apps.jwt.signature=\u7B7E\u540D\u7B97\u6CD5
+apps.jwt.signatureKey=\u7B7E\u540D\u5BC6\u94A5
 apps.jwt.content=\u4EE4\u724C\u5185\u5BB9
 apps.jwt.expires=\u8FC7\u671F\u65F6\u95F4
 #SAML
@@ -404,14 +411,16 @@ apps.oauth.approvalPrompt=\u8BB8\u53EF\u786E\u8BA4
 apps.oauth.v2.0.info=OAuth 2.0 \u8BA4\u8BC1\u914D\u7F6E
 apps.oauth.GrantTypes=\u6388\u6743\u65B9\u5F0F
 apps.oauth.v2.0.clientId=Client Id
+apps.oauth.subject=\u4E3B\u9898(Subject)
 apps.oauth.connect.info=OpenID Connect \u8BA4\u8BC1\u914D\u7F6E
-apps.oauth.connect.idTokenSigningAlgorithm=idToken\u7B7E\u540D\u7B97\u6CD5
-apps.oauth.connect.userInfoSigningAlgorithm=\u7528\u6237\u7B7E\u540D\u7B97\u6CD5
-apps.oauth.connect.jwksUri=JWKS\u5730\u5740
-apps.oauth.connect.idTokenEncryptedAlgorithm=idToken\u52A0\u5BC6\u7B97\u6CD5
-apps.oauth.connect.userInfoEncryptedAlgorithm=\u7528\u6237\u52A0\u5BC6\u7B97\u6CD5
-apps.oauth.connect.idTokenEncryptionMethod=idToken\u52A0\u5BC6\u65B9\u6CD5
-apps.oauth.connect.userInfoEncryptionMethod=\u7528\u6237\u52A0\u5BC6\u65B9\u6CD5
+apps.oauth.connect.algorithm=\u52A0\u5BC6\u7B97\u6CD5
+apps.oauth.connect.algorithmKey=\u79D8\u94A5
+apps.oauth.connect.encryptionMethod=\u52A0\u5BC6\u65B9\u6CD5
+apps.oauth.connect.signature=\u7B7E\u540D\u7B97\u6CD5
+apps.oauth.connect.signatureKey=\u7B7E\u540D\u5BC6\u94A5
+apps.oauth.connect.audience=\u53D7\u4F17(Audience)
+apps.oauth.connect.issuer=\u7B7E\u53D1\u4EBA(Issuer)
+apps.oauth.connect.userInfoResponse=\u7528\u6237\u63A5\u53E3\u7C7B\u578B
 #group
 group.id=\u7EC4\u7F16\u7801
 group.name=\u7528\u6237\u7EC4

+ 2 - 2
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/appAddCommon.ftl

@@ -24,13 +24,13 @@
          </td>
       </tr>
       <tr>
-         <th></th>
+         <th><@locale code="apps.loginUrl"/></th>
          <td colspan="3">
             <input type="text" class="form-control"  id="loginUrl" name="loginUrl" size="100"  title="" value=""  required=""   />
          </td>
       </tr>
       <tr>
-         <th><@locale code="apps.loginUrl"/></th>
+         <th><@locale code="apps.logoutUrl"/></th>
          <td>
          	<input type="text" class="form-control"  id="logoutUrl" name="logoutUrl" size="100"  title="" value=""   />
          </td>

+ 18 - 9
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/appCommonHead.ftl

@@ -8,18 +8,27 @@
 <!--
 $(function(){	
 	$("#algorithm").change(function(){
-		$.post("<@base/>/apps/generate/secret/"+$(this).val(), {_method:"post",currTime:(new Date()).getTime()}, function(data) {
-			$("#algorithmKey").val(data+"");
-			$("#algorithmKey_text").html(data+"");
-			$("#secret").val(data+"");
-			$("#secret_text").html(data+"");
-		});
+	   if($(this).val()=="NONE"){
+	       $("#algorithmKey").html("");
+	   }else{
+		  $.post("<@base/>/apps/generate/secret/"+$(this).val(), {id:$("#id").val(),_method:"post",currTime:(new Date()).getTime()}, function(data) {
+		      $("#algorithmKey").html(data+"");
+		  });
+	   }
 	}); 
 	
+	$("#signature").change(function(){
+	   if($(this).val()=="NONE"){
+           $("#signatureKey").html("");
+       }else{
+            $.post("<@base/>/apps/generate/secret/"+$(this).val(), {id:$("#id").val(),_method:"post",currTime:(new Date()).getTime()}, function(data) {
+                $("#signatureKey").html(data+"");
+            });
+        }
+    }); 
+	
 	$("#generateSecret").on("click",function(){
-		$.post("<@base/>/apps/generate/secret/"+$("#algorithm").val(), {_method:"post",currTime:(new Date()).getTime()}, function(data) {
-			$("#algorithmKey").val(data+"");
-			$("#algorithmKey_text").html(data+"");
+		$.post("<@base/>/apps/generate/secret/random", {id:$("#id").val(),_method:"post",currTime:(new Date()).getTime()}, function(data) {
 			$("#secret").val(data+"");
 			$("#secret_text").html(data+"");
 		}); 

+ 22 - 2
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/cas/appAdd.ftl

@@ -55,9 +55,29 @@ $(function(){
 								</td>
 							</tr>
 							<tr>
+							    <th style="width:15%;"><@locale code="apps.cas.casUser" /></th>
+                                <td style="width:35%;">
+                                    <select id="casUser" name="casUser"  class="form-control  form-select">
+                                        <option value="userId">
+                                            <@locale code="userinfo.id"/></option>
+                                        <option value="employeeNumber">
+                                            <@locale code="userinfo.employeeNumber"/></option>
+                                        <option value="username"  selected>
+                                            <@locale code="userinfo.username"/></option>
+                                        <option value="email">
+                                            <@locale code="userinfo.email"/></option>
+                                        <option value="mobile">
+                                            <@locale code="userinfo.mobile"/></option>
+                                        <option value="windowsaccount">
+                                            <@locale code="userinfo.windowsAccount"/></option>
+                                    </select>
+                                </td>
 								<th style="width:15%;"><@locale code="apps.cas.expires"/></th>
-								<td  colspan=3>
-									<input type="text" class="form-control" id="expires" name="expires"  title="" value=""  required="30"  />
+								<td style="width:35%;">
+								    <div class="input-group">
+									    <input type="text" class="form-control" id="expires" name="expires"  title="" value="3"  required=""  />
+								        <span class="input-group-text">Minutes</span>
+                                    </div>
 								</td>
 							</tr>
 							

+ 23 - 14
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/cas/appUpdate.ftl

@@ -14,20 +14,9 @@
 <script type="text/javascript">
 <!--
 $(function(){	
-
-	$("#algorithm").change(function(){
-		$.post("<@base/>/apps/generate/secret/"+$(this).val(), {_method:"post",currTime:(new Date()).getTime()}, function(data) {
-			$("#algorithmKey").val(data+"");
-			$("#algorithmKey_text").html(data+"");
-			$("#secret").val(data+"");
-			$("#secret_text").html(data+"");
-		});
-	}); 
 	
 	$("#generateSecret").on("click",function(){
-		$.post("<@base/>/apps/generate/secret/"+$("#algorithm").val(), {_method:"post",currTime:(new Date()).getTime()}, function(data) {
-			$("#algorithmKey").val(data+"");
-			$("#algorithmKey_text").html(data+"");
+		$.post("<@base/>/apps/generate/secret/secret", {_method:"post",currTime:(new Date()).getTime()}, function(data) {
 			$("#secret").val(data+"");
 			$("#secret_text").html(data+"");
 		}); 
@@ -73,9 +62,29 @@ $(function(){
 									</td>
 								</tr>
 								<tr>
+								    <th style="width:15%;"><@locale code="apps.cas.casUser" /></th>
+                                    <td  style="width:35%;">
+                                        <select id="casUser" name="casUser"  class="form-control  form-select">
+                                            <option value="userId"   <#if 'userId'==model.casUser>selected</#if> >
+                                                <@locale code="userinfo.id"/></option>
+                                            <option value="employeeNumber" <#if 'employeeNumber'==model.casUser>selected</#if> >
+                                                <@locale code="userinfo.employeeNumber"/></option>
+                                            <option value="username" <#if 'username'==model.casUser>selected</#if> >
+                                                <@locale code="userinfo.username"/></option>
+                                            <option value="email" <#if 'email'==model.casUser>selected</#if> >
+                                                <@locale code="userinfo.email"/></option>
+                                            <option value="mobile" <#if 'mobile'==model.casUser>selected</#if> >
+                                                <@locale code="userinfo.mobile"/></option>
+                                            <option value="windowsaccount" <#if 'windowsaccount'==model.casUser>selected</#if> >
+                                                <@locale code="userinfo.windowsAccount"/></option>
+                                        </select>
+                                    </td>
 									<th style="width:15%;"><@locale code="apps.cas.expires"/></th>
-									<td  colspan=3>
-										<input type="text" class="form-control" id="expires" name="expires"  title="" value="${model.expires}"  required="30"  />
+									<td style="width:35%;">
+									   <div class="input-group">
+									       <input type="text" class="form-control" id="expires" name="expires"  title="" value="${model.expires}"  required="30"  />
+									       <span class="input-group-text">Minutes</span>
+									   </div>
 									</td>
 								</tr>
 								<tr>

+ 12 - 8
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/extendapi/appAdd.ftl

@@ -8,7 +8,7 @@
 <!--
 $(function(){		
 
-	$(".credential").on("click",function(){
+	$("#credential").on("click",function(){
 		if($(this).val()=="3"){
 			$("#sharedconfigure").hide();
 			$("#systemconfigure").hide();
@@ -58,13 +58,17 @@ $(function(){
 				<tr>
 					<th  style="width:15%;"><@locale code="apps.credential"/></th>
 					<td  style="width:35%;">
-						<input type="radio" id="credential-user-defined" name="credential" class="credential" value="3"  checked />
-						<@locale code="apps.credential.user-defined"/>
-						<input type="radio" id="credential-shared" name="credential" class="credential"  value="2" />
-						<@locale code="apps.credential.shared"/>
-						<input type="radio" id="credential-system" name="credential" class="credential"  value="1"  />
-						<@locale code="apps.credential.system"/>
-						
+						<select id="credential" name="credential"  class="form-control  form-select" >
+                            <option value="3"   selected >
+                                <@locale code="apps.credential.user-defined"/>
+                            </option>
+                            <option value="2"   >
+                                <@locale code="apps.credential.shared"/>
+                            </option>
+                            <option value="1"   >
+                                <@locale code="apps.credential.system"/>
+                            </option>
+                        </select> 
 					</td>
 					<th  style="width:15%;"></th>
 					<td  style="width:35%;">

+ 36 - 26
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/formbased/appAdd.ftl

@@ -8,7 +8,7 @@
 <script type="text/javascript">
 <!--
 $(function(){		
-	$(".credential").on("click",function(){
+	$("#credential").on("click",function(){
 		if($(this).val()=="3"){
 			$("#sharedconfigure").hide();
 			$("#systemconfigure").hide();
@@ -54,9 +54,14 @@ $(function(){
 					<td colspan="3">
 						<input type="text"  class="form-control"  id="redirectUri" name="redirectUri"  title="" value=""  required="" />
 					</td>
-					
 				</tr>
 				<tr>
+                    <th><@locale code="apps.formbased.authorizeView"/></th>
+                    <td colspan =3>
+                        <input type="text"  class="form-control"  id="authorizeView" name="authorizeView"  title="" value=""/>
+                    </td>
+                </tr>
+				<tr>
 					<th style="width:15%;"><@locale code="apps.formbased.usernameMapping"/></th>
 					<td style="width:35%;">
 						<input type="text"  class="form-control"  id="usernameMapping" name="usernameMapping"  title="" value="username"  required="" />
@@ -71,24 +76,38 @@ $(function(){
 				<tr>
 					<th width="140px"><@locale code="apps.credential"/></th>
 					<td>
-						<input type="radio" id="credential-user-defined" name="credential" class="credential" value="3"  checked />
-						<@locale code="apps.credential.user-defined"/>
-						<input type="radio" id="credential-shared" name="credential" class="credential"  value="2" />
-						<@locale code="apps.credential.shared"/>
-						<input type="radio" id="credential-system" name="credential" class="credential"  value="1"  />
-						<@locale code="apps.credential.system"/>
+						<select id="credential" name="credential"  class="form-control  form-select" >
+                            <option value="3"   selected >
+                                <@locale code="apps.credential.user-defined"/>
+                            </option>
+                            <option value="2"   >
+                                <@locale code="apps.credential.shared"/>
+                            </option>
+                            <option value="1"   >
+                                <@locale code="apps.credential.system"/>
+                            </option>
+                        </select>   
 					</td>
 					<th><@locale code="apps.formbased.passwordAlgorithm"/></th>
                     <td>
-                       <input type="text" class="form-control" id="passwordAlgorithm" name="passwordAlgorithm"  title="" value=""/>
+                       <select id="passwordAlgorithm" name="passwordAlgorithm"  class="form-control  form-select" >
+                            <option value="NONE"  selected      >NONE</option>
+                            <option value="MD5"                 >MD5</option>
+                            <option value="SHA"                 >SHA</option>
+                            <option value="SHA-1"               >SHA-1</option>
+                            <option value="SHA-256"             >SHA-256</option>
+                            <option value="SHA-384"             >SHA-384</option>
+                            <option value="SHA-512"             >SHA-512</option>
+                            <option value="MD5-HEX"             >MD5-HEX</option>
+                            <option value="SHA-HEX"             >SHA-HEX</option>
+                            <option value="SHA-1-HEX"           >SHA-1-HEX</option>
+                            <option value="SHA-256-HEX"         >SHA-256-HEX</option>
+                            <option value="SHA-384-HEX"         >SHA-384-HEX</option>
+                            <option value="SHA-512-HEX"         >SHA-512-HEX</option>
+                        </select>
                     </td>
 				</tr>
-				<tr>
-					<th><@locale code="apps.formbased.authorizeView"/></th>
-					<td colspan =3>
-						<input type="text"  class="form-control"  id="authorizeView" name="authorizeView"  title="" value=""/>
-					</td>
-				</tr>
+				
 				<tr id="systemconfigure"  style="display:none">
 					<th><@locale code="apps.systemUserAttr"/></th>
 					<td colspan="3">
@@ -101,10 +120,11 @@ $(function(){
 								<@locale code="userinfo.username"/></option>
 							<option value="email">
 								<@locale code="userinfo.email"/></option>
+							<option value="mobile">
+                                 <@locale code="userinfo.mobile"/></option>
 							<option value="windowsaccount">
 								<@locale code="userinfo.windowsAccount"/></option>
 						</select>
-						<b class="orange">*</b><label for="systemUserAttr"></label>
 					</td>
 				</tr>
 				<tr id="sharedconfigure"  style="display:none">
@@ -119,16 +139,6 @@ $(function(){
 
 					</td>
 				</tr>
-				<tr>
-					<th><@locale code="apps.extendAttr"/></th>
-					<td colspan="3">
-						<input type="checkbox" id="isExtendAttr" name="isExtendAttr" value="1"/>
-						<@locale code="apps.isExtendAttr"/>
-						<span  id="showExtendAttr" style="display:none">
-							<input  class="button"  type="button"  value='<@locale code="button.text.add"/>' id="addExtendAttr"/>
-						</span>
-					</td>
-				</tr>
 				</tbody>
 				<tbody >
 					<tr>

+ 25 - 9
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/formbased/appUpdate.ftl

@@ -52,11 +52,16 @@ $(function(){
 				<tr>
 					<th><@locale code="apps.formbased.redirectUri"/></th>
 					<td colspan="3">
-						<input type="text" class="form-control" id="redirectUri" name="redirectUri"  title="" value="${model.redirectUri}"  required=""   />
+						<input type="text" class="form-control" id="redirectUri" name="redirectUri"  title="" value="${model.redirectUri!}"  required=""   />
 					</td>
 					
 				</tr> 
-				
+				<tr>
+                    <th><@locale code="apps.formbased.authorizeView"/></th>
+                    <td colspan =3>
+                        <input type="text" class="form-control" id="authorizeView" name="authorizeView"  title="" value="${model.authorizeView!}"/>
+                    </td>
+                </tr>
 				<tr>
 					<th style="width:15%;"><@locale code="apps.formbased.usernameMapping"/></th>
 					<td style="width:35%;">
@@ -86,15 +91,24 @@ $(function(){
 					</td>
 					<th><@locale code="apps.formbased.passwordAlgorithm"/></th>
 					<td>
-					   <input type="text" class="form-control" id="passwordAlgorithm" name="passwordAlgorithm"  title="" value="${model.passwordAlgorithm!}"/>
-					</td>
-				</tr>
-				<tr>
-					<th><@locale code="apps.formbased.authorizeView"/></th>
-					<td colspan =3>
-						<input type="text" class="form-control" id="authorizeView" name="authorizeView"  title="" value="${model.authorizeView!}"/>
+					   <select id="passwordAlgorithm" name="passwordAlgorithm"  class="form-control  form-select" >
+					        <option value="NONE"     <#if  'NONE'==model.passwordAlgorithm >selected</#if> >NONE</option>
+                            <option value="MD5"      <#if  'MD5'==model.passwordAlgorithm >selected</#if> >MD5</option>
+                            <option value="SHA"      <#if  'SHA'==model.passwordAlgorithm >selected</#if> >SHA</option>
+                            <option value="SHA-1"    <#if  'SHA-1'==model.passwordAlgorithm >selected</#if>   >SHA-1</option>
+                            <option value="SHA-256"   <#if 'SHA-256'==model.passwordAlgorithm >selected</#if> >SHA-256</option>
+                            <option value="SHA-384"   <#if 'SHA-384'==model.passwordAlgorithm >selected</#if> >SHA-384</option>
+                            <option value="SHA-512"   <#if 'SHA-512'==model.passwordAlgorithm >selected</#if> >SHA-512</option>
+                            <option value="MD5-HEX"      <#if  'MD5-HEX'==model.passwordAlgorithm >selected</#if> >MD5-HEX</option>
+                            <option value="SHA-HEX"      <#if  'SHA-HEX'==model.passwordAlgorithm >selected</#if> >SHA-HEX</option>
+                            <option value="SHA-1-HEX"    <#if  'SHA-1-HEX'==model.passwordAlgorithm >selected</#if>  >SHA-1-HEX</option>
+                            <option value="SHA-256-HEX"  <#if 'SHA-256-HEX'==model.passwordAlgorithm >selected</#if> >SHA-256-HEX</option>
+                            <option value="SHA-384-HEX"  <#if 'SHA-384-HEX'==model.passwordAlgorithm >selected</#if> >SHA-384-HEX</option>
+                            <option value="SHA-512-HEX"  <#if 'SHA-512'==model.passwordAlgorithm >selected</#if> >SHA-512-HEX</option>
+                        </select>
 					</td>
 				</tr>
+				
 				<tr id="systemconfigure"  <#if 1!=model.credential> style="display:none"</#if> >
 					<th><@locale code="apps.systemUserAttr"/></th>
 					<td colspan="3">
@@ -107,6 +121,8 @@ $(function(){
 								<@locale code="userinfo.username"/></option>
 							<option value="email" <#if 'email'==model.systemUserAttr>selected</#if> >
 								<@locale code="userinfo.email"/></option>
+							<option value="mobile" <#if 'mobile'==model.systemUserAttr>selected</#if> >
+                                <@locale code="userinfo.mobile"/></option>
 							<option value="windowsaccount" <#if 'windowsaccount'==model.systemUserAttr>selected</#if> >
 								<@locale code="userinfo.windowsAccount"/></option>
 						</select>

+ 92 - 16
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/jwt/appAdd.ftl

@@ -42,39 +42,115 @@
 											<option value="LTPA">轻量级认证(LTPA COOKIE)</option>
 										</select>
 									</td>
-									<th ><@locale code="apps.jwt.cookieName" /></th>
+									<th ><@locale code="apps.jwt.jwtName" /></th>
 									<td >
-										<input type="text" class="form-control" id="cookieName" name="cookieName"  title="" value=""/>
+										<input type="text" class="form-control" id="jwtName" name="jwtName"  title="" value="jwt"/>
 									</td>
-								</tr>
+							</tr>
+							<tr>
+                                    <th ><@locale code="apps.jwt.subject" /></th>
+                                    <td >
+                                        <select id="subject" name="subject"  class="form-control  form-select">
+                                            <option value="userId">
+                                                <@locale code="userinfo.id"/></option>
+                                            <option value="employeeNumber">
+                                                <@locale code="userinfo.employeeNumber"/></option>
+                                            <option value="username"  selected>
+                                                <@locale code="userinfo.username"/></option>
+                                            <option value="email">
+                                                <@locale code="userinfo.email"/></option>
+                                            <option value="mobile">
+                                                <@locale code="userinfo.mobile"/></option>
+                                            <option value="windowsaccount">
+                                                <@locale code="userinfo.windowsAccount"/></option>
+                                        </select>
+                                    </td>
+                                    <th ><@locale code="apps.jwt.issuer" /></th>
+                                    <td >
+                                        <input type="text" class="form-control" id="issuer" name="issuer"  title="" value="" required=""/>
+                                    </td>
+                            </tr>
+                            <tr>
+                                    <th ><@locale code="apps.jwt.audience" /></th>
+                                    <td >
+                                         <input type="text" class="form-control" id="audience" name="audience"  title="" value="" required=""/>
+                                    </td>
+                                    <th ><@locale code="apps.jwt.expires" /></th>
+                                    <td >
+                                        <div class="input-group">
+                                            <input type="text" class="form-control" id="expires" name="expires"  title="" value="1"  required="" />
+                                            <span class="input-group-text">Minutes</span>
+                                        </div>
+                                    </td>
+                            </tr>
+                            <tr>
+                                <th style="width:15%;"><@locale code="apps.jwt.signature" /></th>
+                                <td style="width:35%;">
+                                    <select id="signature" name="signature"   class="form-control  form-select">
+                                        <option value="NONE" selected >NONE</option>
+                                        <option value="RS256"         >RS256</option>
+                                        <option value="RS384"         >RS384</option>
+                                        <option value="RS512"         >RS512</option>
+                                        <option value="HS256"         >HS256</option>
+                                        <option value="HS384"         >HS384</option>
+                                        <option value="HS512"         >HS512</option>
+                                    </select>
+                                </td>
+                                <th></th>
+                                <td>
+                                </td>
+                            </tr>
+                            <tr>
+                                    <th ><@locale code="apps.jwt.signatureKey" /></th>
+                                    <td colspan ="3">
+                                        <textarea class="form-control" id="signatureKey" name="signatureKey"></textarea>
+                                    </td>
+                            </tr>
 							<tr>
 								<th style="width:15%;"><@locale code="apps.jwt.algorithm" /></th>
 								<td style="width:35%;">
 									<select id="algorithm" name="algorithm"   class="form-control  form-select">
-										<option value="DES">DES</option>
-										<option value="DESede">DESede</option>
-										<option value="Blowfish">Blowfish</option>
-										<option value="AES"  selected>AES</option>
-										<option value="HS256"  >HMAC SHA-256</option>
-										<option value="RS256"  >RSA SHA-256</option>
+									    <option value="NONE" selected >NONE</option>
+										<option value="RSA1_5"       >RSA1_5</option>
+										<option value="RSA_OAEP"     >RSA_OAEP</option>
+										<option value="RSA-OAEP-256" >RSA-OAEP-256</option>
+										<option value="A128KW"       >A128KW</option>
+										<option value="A192KW"       >A192KW</option>
+										<option value="A256KW"       >A256KW</option>
+										<option value="A128GCMKW"    >A128GCMKW</option>
+										<option value="A192GCMKW"    >A192GCMKW</option>
+										<option value="A256GCMKW"    >A256GCMKW</option>
 									</select>
-									<b class="orange">*</b><label for="algorithm"></label>
 								</td>
-								<th width="140px"><@locale code="apps.jwt.algorithmKey" /></th>
+								<th width="140px"><@locale code="apps.jwt.encryptionMethod" /></th>
 								<td width="340px">
-									<span id="algorithmKey_text">${model.algorithmKey!}</span>
-									<input type="hidden" class="form-control" id="algorithmKey" name="algorithmKey"  title="" value="${model.algorithmKey!}"/>
-								
+									<select id="encryptionMethod" name="encryptionMethod"   class="form-control  form-select">
+                                        <option value="A128GCM"   selected      >A128GCM</option>
+                                        <option value="A192GCM"                 >A192GCM</option>
+                                        <option value="A256GCM"                 >A256GCM</option>
+                                        
+                                        <option value="A128CBC-HS256"           >A128CBC-HS256</option>
+                                        <option value="A192CBC-HS384"           >A192CBC-HS384</option>
+                                        <option value="A256CBC-HS512"           >A256CBC-HS512</option>
+                                        
+                                        <option value="XC20P"                   >XC20P</option>
+                                    </select>
 								</td>
 							</tr>
 							<tr>
+                                    <th ><@locale code="apps.jwt.algorithmKey" /></th>
+                                    <td colspan ="3">
+                                        <textarea class="form-control" id="algorithmKey" name="algorithmKey"></textarea>
+                                    </td>
+                            </tr>
+							<tr>
 								<th><@locale code="apps.jwt.content" /></th>
 								<td>
 									<#include  "../userPropertys.ftl"/>
 								</td>
-								<th><@locale code="apps.jwt.expires" /></th>
+								<th></th>
 								<td>
-									<input type="text" class="form-control" id="expires" name="expires"  title="" value="1"  required="" />
+									
 								</td>
 							</tr>
 							<tr>

+ 101 - 25
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/jwt/appUpdate.ftl

@@ -44,41 +44,117 @@
 											<option value="LTPA" <#if 'LTPA'==model.tokenType>selected</#if> >轻量级认证(LTPA COOKIE)</option>
 										</select>
 									</td>
-									<th ><@locale code="apps.jwt.cookieName" /></th>
+									<th ><@locale code="apps.jwt.jwtName" /></th>
 									<td >
-										<input type="text" class="form-control" id="cookieName" name="cookieName"  title="" value="${model.cookieName!}"/>
+										<input type="text" class="form-control" id="jwtName" name="jwtName"  title="" value="${model.jwtName!}"/>
 										
 									</td>
 								</tr>
 								<tr>
-									<th style="width:15%;"><@locale code="apps.jwt.algorithm" /></th>
-									<td style="width:35%;">
-										<select id="algorithm" name="algorithm" class="form-control  form-select" >
-											<option value="DES"  <#if 'DES'==model.algorithm>selected</#if> >DES</option>
-											<option value="DESede" <#if 'DESede'==model.algorithm>selected</#if>>DESede</option>
-											<option value="Blowfish" <#if 'Blowfish'==model.algorithm>selected</#if>>Blowfish</option>
-											<option value="AES" <#if 'AES'==model.algorithm>selected</#if>>AES</option>
-											<option value="HS256" <#if 'HS256'==model.algorithm>selected</#if>>HMAC SHA-256</option>
-											<option value="RS256" <#if 'RS256'==model.algorithm>selected</#if>>RSA SHA-256</option>
-											
-										</select>
-									</td>
-									<th style="width:15%;"><@locale code="apps.jwt.algorithmKey" /></th>
-									<td style="width:35%;">
-										<span id="algorithmKey_text">${model.algorithmKey}</span>
-										<input type="hidden" id="algorithmKey" name="algorithmKey"  title="" value="${model.algorithmKey}"/>
-
-									</td>
-								</tr>
+                                    <th ><@locale code="apps.jwt.subject" /></th>
+                                    <td >
+                                        <select id="subject" name="subject"  class="form-control  form-select">
+                                            <option value="userId"   <#if 'userId'==model.subject>selected</#if> >
+                                                <@locale code="userinfo.id"/></option>
+                                            <option value="employeeNumber" <#if 'employeeNumber'==model.subject>selected</#if> >
+                                                <@locale code="userinfo.employeeNumber"/></option>
+                                            <option value="username" <#if 'username'==model.subject>selected</#if> >
+                                                <@locale code="userinfo.username"/></option>
+                                            <option value="email" <#if 'email'==model.subject>selected</#if> >
+                                                <@locale code="userinfo.email"/></option>
+                                             <option value="mobile" <#if 'mobile'==model.subject>selected</#if> >
+                                                <@locale code="userinfo.mobile"/></option>
+                                            <option value="windowsaccount" <#if 'windowsaccount'==model.subject>selected</#if> >
+                                                <@locale code="userinfo.windowsAccount"/></option>
+                                        </select>
+                                    </td>
+                                    <th ><@locale code="apps.jwt.issuer" /></th>
+                                    <td >
+                                        <input type="text" class="form-control" id="issuer" name="issuer"  title="" value="${model.issuer!}" required=""/>
+                                    </td>
+                            </tr>
+                            <tr>
+                                    <th ><@locale code="apps.jwt.audience" /></th>
+                                    <td >
+                                         <input type="text" class="form-control" id="audience" name="audience"  title="" value="${model.audience!}" required=""/>
+                                    </td>
+                                    <th ><@locale code="apps.jwt.expires" /></th>
+                                    <td >
+                                        <div class="input-group">
+                                            <input type="text" class="form-control" id="expires" name="expires"  title="" value="${model.expires!}"  required="" />
+                                            <span class="input-group-text">Minutes</span>
+                                        </div>
+                                    </td>
+                            </tr>
+								
+								<tr>
+                                <th ><@locale code="apps.jwt.signature" /></th>
+                                <td >
+                                    <select id="signature" name="signature"   class="form-control  form-select">
+                                        <option value="NONE"  <#if 'NONE'==model.signature> selected</#if>         >NONE</option>
+                                        <option value="RS256" <#if 'RS256'==model.signature>selected</#if>        >RS256</option>
+                                        <option value="RS384" <#if 'RS384'==model.signature>selected</#if>        >RS384</option>
+                                        <option value="RS512" <#if 'RS512'==model.signature>selected</#if>        >RS512</option>
+                                        <option value="HS256" <#if 'HS256'==model.signature>selected</#if>        >HS256</option>
+                                        <option value="HS384" <#if 'HS384'==model.signature>selected</#if>        >HS384</option>
+                                        <option value="HS512" <#if 'HS512'==model.signature>selected</#if>        >HS512</option>
+                                    </select>
+                                </td>
+                                <th ></th>
+                                <td >
+                                    
+                                </td>
+                                </tr>
+                                <tr>
+                                    <th ><@locale code="apps.jwt.signatureKey" /></th>
+                                    <td colspan ="3">
+                                        <textarea class="form-control" id="signatureKey" name="signatureKey">${model.signatureKey!}</textarea>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <th style="width:15%;"><@locale code="apps.jwt.algorithm" /></th>
+                                    <td style="width:35%;">
+                                        <select id="algorithm" name="algorithm" class="form-control  form-select" >
+                                            <option value="NONE"         <#if 'NONE'==model.algorithm>selected</#if> >NONE</option>
+                                            <option value="RSA1_5"       <#if 'RSA1_5'==model.algorithm>selected</#if> >RSA1_5</option>
+                                            <option value="RSA_OAEP"     <#if 'RSA_OAEP'==model.algorithm>selected</#if>>RSA_OAEP</option>
+                                            <option value="RSA-OAEP-256" <#if 'RSA-OAEP-256'==model.algorithm>selected</#if>>RSA-OAEP-256</option>
+                                            <option value="A128KW"       <#if 'A128KW'==model.algorithm>selected</#if>>A128KW</option>
+                                            <option value="A192KW"       <#if 'A192KW'==model.algorithm>selected</#if>>A192KW</option>
+                                            <option value="A256KW"       <#if 'A256KW'==model.algorithm>selected</#if>>A256KW</option>
+                                            <option value="A128GCMKW"    <#if 'A128GCMKW'==model.algorithm>selected</#if>>A128GCMKW</option>
+                                            <option value="A192GCMKW"    <#if 'A192GCMKW'==model.algorithm>selected</#if>>A192GCMKW</option>
+                                            <option value="A256GCMKW"    <#if 'A256GCMKW'==model.algorithm>selected</#if>>A256GCMKW</option>
+                                        </select>
+                                    </td>
+                                    <th width="140px"><@locale code="apps.jwt.encryptionMethod" /></th>
+                                    <td width="340px">
+                                        <select id="encryptionMethod" name="encryptionMethod"   class="form-control  form-select">
+                                            <option value="A128GCM"        <#if 'A128GCM'==model.encryptionMethod>selected</#if>       >A128GCM</option>
+                                            <option value="A192GCM"        <#if 'A192GCM'==model.encryptionMethod>selected</#if>       >A192GCM</option>
+                                            <option value="A256GCM"        <#if 'A256GCM'==model.encryptionMethod>selected</#if>       >A256GCM</option>
+                                            
+                                            <option value="A128CBC-HS256"  <#if 'A128CBC-HS256'==model.encryptionMethod>selected</#if> >A128CBC-HS256</option>
+                                            <option value="A192CBC-HS384"  <#if 'A192CBC-HS384'==model.encryptionMethod>selected</#if> >A192CBC-HS384</option>
+                                            <option value="A256CBC-HS512"  <#if 'A256CBC-HS512'==model.encryptionMethod>selected</#if> >A256CBC-HS512</option>
+                                            
+                                            <option value="XC20P"          <#if 'XC20P'==model.encryptionMethod>selected</#if>         >XC20P</option>
+                                        </select>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <th ><@locale code="apps.jwt.algorithmKey" /></th>
+                                    <td colspan ="3">
+                                        <textarea class="form-control" id="algorithmKey" name="algorithmKey">${model.algorithmKey!}</textarea>
+                                    </td>
+                                </tr>
 								<tr>
 									<th><@locale code="apps.jwt.content" /></th>
 									<td >
 										<#include  "../userPropertys.ftl"/>
 									</td>
-									<th><@locale code="apps.jwt.expires" /></th>
-									<td>
-										<input type="text" class="form-control" id="expires" name="expires"  title="" value="${model.expires}"  required="" />
-									</td>
+									<th></th>
+									<td></td>
 								</tr>
 								
 								<tr>

+ 113 - 108
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/oauth20/appAdd.ftl

@@ -58,8 +58,25 @@
 					</td>
 				</tr>
 				<tr>
+				    <th ><@locale code="apps.oauth.subject" /></th>
+                    <td >
+                        <select id="subject" name="subject"  class="form-control  form-select">
+                            <option value="userId">
+                                <@locale code="userinfo.id"/></option>
+                            <option value="employeeNumber">
+                                <@locale code="userinfo.employeeNumber"/></option>
+                            <option value="username"  selected>
+                                <@locale code="userinfo.username"/></option>
+                            <option value="email">
+                                <@locale code="userinfo.email"/></option>
+                            <option value="mobile">
+                                <@locale code="userinfo.mobile"/></option>
+                            <option value="windowsaccount">
+                                <@locale code="userinfo.windowsAccount"/></option>
+                        </select>
+                    </td>
 					<th><@locale code="apps.oauth.scope" /></th>
-					<td  colspan="3">
+					<td >
 						<table class="hidetable"  style="width:100%;">
 							<tr>
 								<td>read<input type="checkbox" id="scope_trust" name="scope" value="read"  checked /></td>
@@ -100,21 +117,10 @@
 						
 					</td>
 				</tr>
+				
 				<tr>
-					<th><@locale code="apps.oauth.accessTokenValiditySeconds" /></th>
-					<td >
-						<input type="text"  class="form-control" id="accessTokenValiditySeconds" name="accessTokenValiditySeconds"  title="" value="1800"/>
-						
-					</td>
-					<th><@locale code="apps.oauth.refreshTokenValiditySeconds" /></th>
-					<td>
-						<input type="text" class="form-control"  id="refreshTokenValiditySeconds" name="refreshTokenValiditySeconds"  title="" value="1800"/>
-						
-					</td>
-				</tr>
-				<tr>
-                    <th>PKCE</th>
-                    <td >
+                    <th  style="width:15%;">PKCE</th>
+                    <td  style="width:35%;">
                         <select  id="pkce" name="pkce" class="form-control  form-select">
                             <option value="yes"  >
                                 <@locale code="common.text.yes" /></option>
@@ -122,8 +128,8 @@
                                 <@locale code="common.text.no" /></option>
                         </select>
                     </td>
-                    <th><@locale code="apps.oauth.approvalPrompt" /></th>
-                    <td >
+                    <th  style="width:15%;"><@locale code="apps.oauth.approvalPrompt" /></th>
+                    <td  style="width:35%;">
                         <select  id="approvalPrompt" name="approvalPrompt"  class="form-control  form-select" >
                             <option value="force" selected>
                                 <@locale code="apps.oauth.approvalPrompt.force" /></option>
@@ -133,102 +139,101 @@
                     </td>
                     
                 </tr>
+                <tr>
+                    <th><@locale code="apps.oauth.accessTokenValiditySeconds" /></th>
+                    <td >
+                       <div class="input-group">
+                          <input type="text"  class="form-control" id="accessTokenValiditySeconds" name="accessTokenValiditySeconds"  title="" value="1800"/>
+                          <span class="input-group-text">Seconds</span>
+                        </div>
+                    </td>
+                    <th><@locale code="apps.oauth.refreshTokenValiditySeconds" /></th>
+                    <td>
+                       <div class="input-group">
+                          <input type="text" class="form-control"  id="refreshTokenValiditySeconds" name="refreshTokenValiditySeconds"  title="" value="1800"/>
+                          <span class="input-group-text">Seconds</span>
+                        </div>
+                    </td>
+                </tr>
 				<tr>
 					<td colspan=4><h5><@locale code="apps.oauth.connect.info" /></h5></td>
 				</tr>
 				<tr>
-					<th><@locale code="apps.oauth.connect.idTokenSigningAlgorithm" /></th>
-					<td >
-						<select  id="idTokenSigningAlgorithm" name="idTokenSigningAlgorithm"   class="form-control  form-select" >
-							<option value="none"    selected>No digital signature</option>
-							<option value="HS256"  >HMAC using SHA-256 hash algorithm</option>
-							<option value="HS384"  >HMAC using SHA-384 hash algorithm</option>
-							<option value="HS512"  >HMAC using SHA-512 hash algorithm</option>
-							<option value="RS256"  >RSASSA using SHA-256 hash algorithm</option>
-							<option value="RS384"  >RSASSA using SHA-384 hash algorithm</option>
-							<option value="RS512"  >RSASSA using SHA-512 hash algorithm</option>
-							<option value="ES256"  >ECDSA using P-256 curve and SHA-256 hash algorithm</option>
-							<option value="ES384"  >ECDSA using P-384 curve and SHA-384 hash algorithm</option>
-							<option value="ES512"  >ECDSA using P-512 curve and SHA-512 hash algorithm</option>
-						</select>
-					</td>
-					<th><@locale code="apps.oauth.connect.userInfoSigningAlgorithm" /></th>
-					<td >
-						<select  id="userInfoSigningAlgorithm" name="userInfoSigningAlgorithm"  class="form-control  form-select" >
-							<option value="none"    selected>No digital signature</option>
-							<option value="HS256"  >HMAC using SHA-256 hash algorithm</option>
-							<option value="HS384"  >HMAC using SHA-384 hash algorithm</option>
-							<option value="HS512"  >HMAC using SHA-512 hash algorithm</option>
-							<option value="RS256"  >RSASSA using SHA-256 hash algorithm</option>
-							<option value="RS384"  >RSASSA using SHA-384 hash algorithm</option>
-							<option value="RS512"  >RSASSA using SHA-512 hash algorithm</option>
-							<option value="ES256"  >ECDSA using P-256 curve and SHA-256 hash algorithm</option>
-							<option value="ES384"  >ECDSA using P-384 curve and SHA-384 hash algorithm</option>
-							<option value="ES512"  >ECDSA using P-512 curve and SHA-512 hash algorithm</option>
-						</select>
-					</td>
-				</tr>
-				<tr>
-					<th><@locale code="apps.oauth.connect.jwksUri" /></th>
-					<td colspan =3>
-						<input type="text" class="form-control"  id="jwksUri" name="jwksUri"  title="" value="${model.jwksUri!}"/>
-					</td>
-				</tr>
-				<tr>
-					<th><@locale code="apps.oauth.connect.idTokenEncryptedAlgorithm" /></th>
-					<td >
-						<select  id="idTokenEncryptedAlgorithm" name="idTokenEncryptedAlgorithm"  class="form-control  form-select" >
-							<option value="none" selected >No encryption</option>
-							<option value="RSA1_5" >RSAES-PKCS1-V1_5</option>
-							<option value="RSA-OAEP" >RSAES using Optimal Asymmetric Encryption Padding (OAEP)</option>
-							<option value="A128KW">AES Key Wrap Algorithm using 128 bit keys </option>
-							<option value="A256KW">AES Key Wrap Algorithm using 256 bit keys</option>
-							<option value="dir" >Direct use of a shared symmetric key as the Content Master Key (CMK) for the block encryption step</option>
-							<option value="ECDH-ES">Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using the Concat KDF, with the agreed-upon key being used directly as the Content Master Key (CMK)</option>
-							<option value="ECDH-ES+A128KW">Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A128KW function</option>
-							<option value="ECDH-ES+A256KW">Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A256KW function</option>
-						
-						</select>
-					</td>
-					<th><@locale code="apps.oauth.connect.userInfoEncryptedAlgorithm" /></th>
-					<td >
-						<select  id="userInfoEncryptedAlgorithm" name="userInfoEncryptedAlgorithm" class="form-control  form-select"  >
-							<option value="none" selected >No encryption</option>
-							<option value="RSA1_5" >RSAES-PKCS1-V1_5</option>
-							<option value="RSA-OAEP" >RSAES using Optimal Asymmetric Encryption Padding (OAEP)</option>
-							<option value="A128KW">AES Key Wrap Algorithm using 128 bit keys </option>
-							<option value="A256KW">AES Key Wrap Algorithm using 256 bit keys</option>
-							<option value="dir" >Direct use of a shared symmetric key as the Content Master Key (CMK) for the block encryption step</option>
-							<option value="ECDH-ES">Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using the Concat KDF, with the agreed-upon key being used directly as the Content Master Key (CMK)</option>
-							<option value="ECDH-ES+A128KW">Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A128KW function</option>
-							<option value="ECDH-ES+A256KW">Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A256KW function</option>
-						
-						</select>
-					</td>
-				</tr>
-				
+                    <th ><@locale code="apps.oauth.connect.issuer" /></th>
+                    <td >
+                        <input type="text" class="form-control" id="issuer" name="issuer"  title="" value="" />
+                    </td>
+                    <th ><@locale code="apps.oauth.connect.audience" /></th>
+                    <td >
+                         <input type="text" class="form-control" id="audience" name="audience"  title="" value="" />
+                    </td>
+                </tr>
 				<tr>
-					<th><@locale code="apps.oauth.connect.idTokenEncryptionMethod" /></th>
-					<td >
-						<select  id="idTokenEncryptionMethod" name="idTokenEncryptionMethod"  class="form-control  form-select" >
-							<option value="none" selected>No encryption</option>
-							<option value="A128CBC+HS256" >Composite Authenticated Encryption algorithm using AES in Cipher Block Chaining (CBC) mode with PKCS #5 padding with an integrity calculation using HMAC SHA-256, using a 256 bit CMK (and 128 bit CEK)</option>
-							<option value="A256CBC+HS512" >Composite Authenticated Encryption algorithm using AES in CBC mode with PKCS #5 padding with an integrity calculation using HMAC SHA-512, using a 512 bit CMK (and 256 bit CEK)</option>
-							<option value="A128GCM" >AES GCM using 128 bit keys</option>
-							<option value="A256GCM" >AES GCM using 256 bit keys</option>
-					</select>
-					</td>
-					<th><@locale code="apps.oauth.connect.userInfoEncryptionMethod" /></th>
-					<td >
-						<select  id="userInfoEncryptionMethod" name="userInfoEncryptionMethod"  class="form-control  form-select" >
-							<option value="none" selected>No encryption</option>
-							<option value="A128CBC+HS256" >Composite Authenticated Encryption algorithm using AES in Cipher Block Chaining (CBC) mode with PKCS #5 padding with an integrity calculation using HMAC SHA-256, using a 256 bit CMK (and 128 bit CEK)</option>
-							<option value="A256CBC+HS512" >Composite Authenticated Encryption algorithm using AES in CBC mode with PKCS #5 padding with an integrity calculation using HMAC SHA-512, using a 512 bit CMK (and 256 bit CEK)</option>
-							<option value="A128GCM" >AES GCM using 128 bit keys</option>
-							<option value="A256GCM" >AES GCM using 256 bit keys</option>
-						</select>
-					</td>
-				</tr>
+                    <th style="width:15%;"><@locale code="apps.oauth.connect.signature" /></th>
+                    <td style="width:35%;">
+                        <select id="signature" name="signature"   class="form-control  form-select">
+                            <option value="NONE" selected >NONE</option>
+                            <option value="RS256"         >RS256</option>
+                            <option value="RS384"         >RS384</option>
+                            <option value="RS512"         >RS512</option>
+                            <option value="HS256"         >HS256</option>
+                            <option value="HS384"         >HS384</option>
+                            <option value="HS512"         >HS512</option>
+                        </select>
+                    </td>
+                    <th><@locale code="apps.oauth.connect.userInfoResponse" /></th>
+                    <td>
+                        <select id="userInfoResponse" name="userInfoResponse"   class="form-control  form-select">
+                            <option value="NORMAL" selected     >NORMAL</option>
+                            <option value="SIGNING"             >SIGNING</option>
+                            <option value="ENCRYPTION"          >ENCRYPTION</option>
+                            <option value="SIGNING_ENCRYPTION"  >SIGNING_ENCRYPTION</option>
+                        </select>
+                    </td>
+                </tr>
+                <tr>
+                        <th ><@locale code="apps.oauth.connect.signatureKey" /></th>
+                        <td colspan ="3">
+                            <textarea class="form-control" id="signatureKey" name="signatureKey"></textarea>
+                        </td>
+                </tr>
+                <tr>
+                    <th style="width:15%;"><@locale code="apps.oauth.connect.algorithm" /></th>
+                    <td style="width:35%;">
+                        <select id="algorithm" name="algorithm"   class="form-control  form-select">
+                            <option value="NONE" selected >NONE</option>
+                            <option value="RSA1_5"       >RSA1_5</option>
+                            <option value="RSA_OAEP"     >RSA_OAEP</option>
+                            <option value="RSA-OAEP-256" >RSA-OAEP-256</option>
+                            <option value="A128KW"       >A128KW</option>
+                            <option value="A192KW"       >A192KW</option>
+                            <option value="A256KW"       >A256KW</option>
+                            <option value="A128GCMKW"    >A128GCMKW</option>
+                            <option value="A192GCMKW"    >A192GCMKW</option>
+                            <option value="A256GCMKW"    >A256GCMKW</option>
+                        </select>
+                    </td>
+                    <th width="140px"><@locale code="apps.oauth.connect.encryptionMethod" /></th>
+                    <td width="340px">
+                        <select id="encryptionMethod" name="encryptionMethod"   class="form-control  form-select">
+                            <option value="A128GCM"   selected      >A128GCM</option>
+                            <option value="A192GCM"                 >A192GCM</option>
+                            <option value="A256GCM"                 >A256GCM</option>
+                            
+                            <option value="A128CBC-HS256"           >A128CBC-HS256</option>
+                            <option value="A192CBC-HS384"           >A192CBC-HS384</option>
+                            <option value="A256CBC-HS512"           >A256CBC-HS512</option>
+                            
+                            <option value="XC20P"                   >XC20P</option>
+                        </select>
+                    </td>
+                </tr>
+                <tr>
+                        <th ><@locale code="apps.oauth.connect.algorithmKey" /></th>
+                        <td colspan ="3">
+                            <textarea class="form-control" id="algorithmKey" name="algorithmKey"></textarea>
+                        </td>
+                </tr>
 				
 				<tr>
 					<td colspan =4>

+ 118 - 110
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/oauth20/appUpdate.ftl

@@ -45,8 +45,25 @@
 					</td>
 				</tr>
 				<tr>
-					<th><@locale code="apps.oauth.scope" /></th>
-					<td  colspan="3">
+				    <th ><@locale code="apps.oauth.subject" /></th>
+                    <td >
+                        <select id="subject" name="subject"  class="form-control  form-select">
+                            <option value="userId"   <#if 'userId'==model.subject>selected</#if> >
+                                <@locale code="userinfo.id"/></option>
+                            <option value="employeeNumber" <#if 'employeeNumber'==model.subject>selected</#if> >
+                                <@locale code="userinfo.employeeNumber"/></option>
+                            <option value="username" <#if 'username'==model.subject>selected</#if> >
+                                <@locale code="userinfo.username"/></option>
+                            <option value="email" <#if 'email'==model.subject>selected</#if> >
+                                <@locale code="userinfo.email"/></option>
+                             <option value="mobile" <#if 'mobile'==model.subject>selected</#if> >
+                                <@locale code="userinfo.mobile"/></option>
+                            <option value="windowsaccount" <#if 'windowsaccount'==model.subject>selected</#if> >
+                                <@locale code="userinfo.windowsAccount"/></option>
+                        </select>
+                    </td>
+					<th  style="width:15%;"><@locale code="apps.oauth.scope" /></th>
+					<td  >
 						<table  class="hidetable"  style="width:100%;">
 							<tr>
 								<td>read<input type="checkbox" id="scope_trust" name="scope" value="read"  <#if   model.scope?contains("read") >checked</#if> /></td>
@@ -87,21 +104,10 @@
 
 					</td>
 				</tr>
+				
 				<tr>
-					<th><@locale code="apps.oauth.accessTokenValiditySeconds" /></th>
-					<td >
-						<input type="text" class="form-control" id="accessTokenValiditySeconds" name="accessTokenValiditySeconds"  title="" value="${model.accessTokenValiditySeconds}"/>
-			
-					</td>
-					<th><@locale code="apps.oauth.refreshTokenValiditySeconds" /></th>
-					<td>
-						<input type="text" class="form-control" id="refreshTokenValiditySeconds" name="refreshTokenValiditySeconds"  title="" value="${model.refreshTokenValiditySeconds}"/>
-					
-					</td>
-				</tr>
-				<tr>
-                    <th>PKCE</th>
-                    <td >
+                    <th  style="width:15%;">PKCE</th>
+                    <td  style="width:35%;">
                         <select  id="pkce" name="pkce" class="form-control  form-select">
                             <option value="yes"  <#if   "yes"==model.pkce?default("yes") >selected</#if>>
                                 <@locale code="common.text.yes" /></option>
@@ -109,8 +115,8 @@
                                 <@locale code="common.text.no" /></option>
                         </select>
                     </td>
-                    <th><@locale code="apps.oauth.approvalPrompt" /></th>
-                    <td >
+                    <th  style="width:15%;"><@locale code="apps.oauth.approvalPrompt" /></th>
+                    <td  style="width:35%;">
                         <select  id="approvalPrompt" name="approvalPrompt" class="form-control  form-select">
                             <option value="force"  <#if   ""==model.approvalPrompt?default("") >selected</#if>>
                                 <@locale code="apps.oauth.approvalPrompt.force" /></option>
@@ -119,99 +125,101 @@
                         </select>
                     </td>
                 </tr>
+                <tr>
+                    <th><@locale code="apps.oauth.accessTokenValiditySeconds" /></th>
+                    <td >
+                        <div class="input-group">
+                          <input type="text" class="form-control" id="accessTokenValiditySeconds" name="accessTokenValiditySeconds"  title="" value="${model.accessTokenValiditySeconds}"/>
+                          <span class="input-group-text">Seconds</span>
+                        </div>
+                    </td>
+                    <th><@locale code="apps.oauth.refreshTokenValiditySeconds" /></th>
+                    <td>
+                       <div class="input-group">
+                          <input type="text" class="form-control" id="refreshTokenValiditySeconds" name="refreshTokenValiditySeconds"  title="" value="${model.refreshTokenValiditySeconds}"/>
+                           <span class="input-group-text">Seconds</span>
+                       </div>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan=4><h5><@locale code="apps.oauth.connect.info" /></h5></td>
+                </tr>
+                <tr>
+                    <th ><@locale code="apps.oauth.connect.issuer" /></th>
+                    <td >
+                        <input type="text" class="form-control" id="issuer" name="issuer"  title="" value="${model.issuer!}" />
+                    </td>
+                    <th ><@locale code="apps.oauth.connect.audience" /></th>
+                    <td >
+                         <input type="text" class="form-control" id="audience" name="audience"  title="" value="${model.audience!}" />
+                    </td>
+                </tr>
+                <tr>
+                    <th ><@locale code="apps.oauth.connect.signature" /></th>
+                    <td >
+                        <select id="signature" name="signature"   class="form-control  form-select">
+                            <option value="NONE"  <#if 'NONE'==model.signature> selected</#if>         >NONE</option>
+                            <option value="RS256" <#if 'RS256'==model.signature>selected</#if>        >RS256</option>
+                            <option value="RS384" <#if 'RS384'==model.signature>selected</#if>        >RS384</option>
+                            <option value="RS512" <#if 'RS512'==model.signature>selected</#if>        >RS512</option>
+                            <option value="HS256" <#if 'HS256'==model.signature>selected</#if>        >HS256</option>
+                            <option value="HS384" <#if 'HS384'==model.signature>selected</#if>        >HS384</option>
+                            <option value="HS512" <#if 'HS512'==model.signature>selected</#if>        >HS512</option>
+                        </select>
+                    </td>
+                    <th><@locale code="apps.oauth.connect.userInfoResponse" /></th>
+                    <td>
+                        <select id="userInfoResponse" name="userInfoResponse"   class="form-control  form-select">
+                            <option value="NORMAL"              <#if 'NORMAL'==model.userInfoResponse> selected</#if>      >NORMAL</option>
+                            <option value="SIGNING"             <#if 'SIGNING'==model.userInfoResponse> selected</#if>    >SIGNING</option>
+                            <option value="ENCRYPTION"          <#if 'ENCRYPTION'==model.userInfoResponse> selected</#if>   >ENCRYPTION</option>
+                            <option value="SIGNING_ENCRYPTION"  <#if 'SIGNING_ENCRYPTION'==model.userInfoResponse> selected</#if>  >SIGNING_ENCRYPTION</option>
+                        </select>
+                    </td>
+                </tr>
 				<tr>
-					<th><@locale code="apps.oauth.connect.idTokenSigningAlgorithm" /></th>
-					<td >
-						<select  id="idTokenSigningAlgorithm" name="idTokenSigningAlgorithm" class="form-control  form-select">
-							<option value="none"   <#if   'none' ==model.idTokenSigningAlgorithm >selected</#if>>No digital signature</option>
-							<option value="HS256"  <#if   'HS256'==model.idTokenSigningAlgorithm >selected</#if>>HMAC using SHA-256 hash algorithm</option>
-							<option value="HS384"  <#if   'HS384'==model.idTokenSigningAlgorithm >selected</#if>>HMAC using SHA-384 hash algorithm</option>
-							<option value="HS512"  <#if   'HS512'==model.idTokenSigningAlgorithm >selected</#if>>HMAC using SHA-512 hash algorithm</option>
-							<option value="RS256"  <#if   'RS256'==model.idTokenSigningAlgorithm >selected</#if>>RSASSA using SHA-256 hash algorithm</option>
-							<option value="RS384"  <#if   'RS384'==model.idTokenSigningAlgorithm >selected</#if>>RSASSA using SHA-384 hash algorithm</option>
-							<option value="RS512"  <#if   'RS256'==model.idTokenSigningAlgorithm >selected</#if>>RSASSA using SHA-512 hash algorithm</option>
-							<option value="ES256"  <#if   'ES256'==model.idTokenSigningAlgorithm >selected</#if>>ECDSA using P-256 curve and SHA-256 hash algorithm</option>
-							<option value="ES384"  <#if   'ES384'==model.idTokenSigningAlgorithm >selected</#if>>ECDSA using P-384 curve and SHA-384 hash algorithm</option>
-							<option value="ES512"  <#if   'ES512'==model.idTokenSigningAlgorithm >selected</#if>>ECDSA using P-512 curve and SHA-512 hash algorithm</option>
-						</select>
-					</td>
-					<th><@locale code="apps.oauth.connect.userInfoSigningAlgorithm" /></th>
-					<td >
-						<select  id="userInfoSigningAlgorithm" name="userInfoSigningAlgorithm"  class="form-control  form-select">
-							<option value="none"   <#if   'none' ==model.userInfoSigningAlgorithm >selected</#if>>No digital signature</option>
-							<option value="HS256"  <#if   'HS256'==model.userInfoSigningAlgorithm >selected</#if>>HMAC using SHA-256 hash algorithm</option>
-							<option value="HS384"  <#if   'HS384'==model.userInfoSigningAlgorithm >selected</#if>>HMAC using SHA-384 hash algorithm</option>
-							<option value="HS512"  <#if   'HS512'==model.userInfoSigningAlgorithm >selected</#if>>HMAC using SHA-512 hash algorithm</option>
-							<option value="RS256"  <#if   'RS256'==model.userInfoSigningAlgorithm >selected</#if>>RSASSA using SHA-256 hash algorithm</option>
-							<option value="RS384"  <#if   'RS384'==model.userInfoSigningAlgorithm >selected</#if>>RSASSA using SHA-384 hash algorithm</option>
-							<option value="RS512"  <#if   'RS256'==model.userInfoSigningAlgorithm >selected</#if>>RSASSA using SHA-512 hash algorithm</option>
-							<option value="ES256"  <#if   'ES256'==model.userInfoSigningAlgorithm >selected</#if>>ECDSA using P-256 curve and SHA-256 hash algorithm</option>
-							<option value="ES384"  <#if   'ES384'==model.userInfoSigningAlgorithm >selected</#if>>ECDSA using P-384 curve and SHA-384 hash algorithm</option>
-							<option value="ES512"  <#if   'ES512'==model.userInfoSigningAlgorithm >selected</#if>>ECDSA using P-512 curve and SHA-512 hash algorithm</option>
-						</select>
-					</td>
-				</tr>
-				<tr>
-					<th><@locale code="apps.oauth.connect.jwksUri" /></th>
-					<td colspan =3>
-						<input type="text" class="form-control" id="jwksUri" name="jwksUri"  title="" value="${model.jwksUri!}"/>
-					</td>
-				</tr>
-				<tr>
-					<th><@locale code="apps.oauth.connect.idTokenEncryptedAlgorithm" /></th>
-					<td >
-						<select  id="idTokenEncryptedAlgorithm" name="idTokenEncryptedAlgorithm" class="form-control  form-select">
-							<option value="none" <#if   'none'==model.idTokenEncryptedAlgorithm >selected</#if> >No encryption</option>
-							<option value="RSA1_5" <#if   'RSA1_5'==model.idTokenEncryptedAlgorithm >selected</#if> >RSAES-PKCS1-V1_5</option>
-							<option value="RSA-OAEP" <#if   'RSA-OAEP'==model.idTokenEncryptedAlgorithm >selected</#if>>RSAES using Optimal Asymmetric Encryption Padding (OAEP)</option>
-							<option value="A128KW" <#if   'A128KW'==model.idTokenEncryptedAlgorithm >selected</#if>>AES Key Wrap Algorithm using 128 bit keys </option>
-							<option value="A256KW" <#if   'A256KW'==model.idTokenEncryptedAlgorithm >selected</#if>>AES Key Wrap Algorithm using 256 bit keys</option>
-							<option value="dir" <#if   'dir'==model.idTokenEncryptedAlgorithm >selected</#if>>Direct use of a shared symmetric key as the Content Master Key (CMK) for the block encryption step</option>
-							<option value="ECDH-ES" <#if   'ECDH-ES'==model.idTokenEncryptedAlgorithm >selected</#if>>Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using the Concat KDF, with the agreed-upon key being used directly as the Content Master Key (CMK)</option>
-							<option value="ECDH-ES+A128KW" <#if   'ECDH-ES+A128KW'==model.idTokenEncryptedAlgorithm >selected</#if>>Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A128KW function</option>
-							<option value="ECDH-ES+A256KW" <#if   'ECDH-ES+A256KW'==model.idTokenEncryptedAlgorithm >selected</#if>>Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A256KW function</option>
-						
-						</select>
-					</td>
-					<th><@locale code="apps.oauth.connect.userInfoEncryptedAlgorithm" /></th>
-					<td >
-						<select  id="userInfoEncryptedAlgorithm" name="userInfoEncryptedAlgorithm" class="form-control  form-select">
-							<option value="none" <#if   'none'==model.userInfoEncryptedAlgorithm >selected</#if> >No encryption</option>
-							<option value="RSA1_5" <#if   'RSA1_5'==model.userInfoEncryptedAlgorithm >selected</#if> >RSAES-PKCS1-V1_5</option>
-							<option value="RSA-OAEP" <#if   'RSA-OAEP'==model.userInfoEncryptedAlgorithm >selected</#if>>RSAES using Optimal Asymmetric Encryption Padding (OAEP)</option>
-							<option value="A128KW" <#if   'A128KW'==model.userInfoEncryptedAlgorithm >selected</#if>>AES Key Wrap Algorithm using 128 bit keys </option>
-							<option value="A256KW" <#if   'A256KW'==model.userInfoEncryptedAlgorithm >selected</#if>>AES Key Wrap Algorithm using 256 bit keys</option>
-							<option value="dir" <#if   'dir'==model.userInfoEncryptedAlgorithm >selected</#if>>Direct use of a shared symmetric key as the Content Master Key (CMK) for the block encryption step</option>
-							<option value="ECDH-ES" <#if   'ECDH-ES'==model.userInfoEncryptedAlgorithm >selected</#if>>Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using the Concat KDF, with the agreed-upon key being used directly as the Content Master Key (CMK)</option>
-							<option value="ECDH-ES+A128KW" <#if   'ECDH-ES+A128KW'==model.userInfoEncryptedAlgorithm >selected</#if>>Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A128KW function</option>
-							<option value="ECDH-ES+A256KW" <#if   'ECDH-ES+A256KW'==model.userInfoEncryptedAlgorithm >selected</#if>>Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A256KW function</option>
-						
-						</select>
-					</td>
-				</tr>
-				
-				<tr>
-					<th><@locale code="apps.oauth.connect.idTokenEncryptionMethod" /></th>
-					<td >
-						<select  id="idTokenEncryptionMethod" name="idTokenEncryptionMethod" class="form-control  form-select">
-							<option value="none" <#if   'none'==model.idTokenEncryptionMethod >selected</#if>>No encryption</option>
-							<option value="A128CBC+HS256" <#if   'A128CBC+HS256'==model.idTokenEncryptionMethod >selected</#if>>Composite Authenticated Encryption algorithm using AES in Cipher Block Chaining (CBC) mode with PKCS #5 padding with an integrity calculation using HMAC SHA-256, using a 256 bit CMK (and 128 bit CEK)</option>
-							<option value="A256CBC+HS512" <#if   'A256CBC+HS512'==model.idTokenEncryptionMethod >selected</#if>>Composite Authenticated Encryption algorithm using AES in CBC mode with PKCS #5 padding with an integrity calculation using HMAC SHA-512, using a 512 bit CMK (and 256 bit CEK)</option>
-							<option value="A128GCM" <#if   'A128GCM'==model.idTokenEncryptionMethod >selected</#if>>AES GCM using 128 bit keys</option>
-							<option value="A256GCM" <#if   'A256GCM'==model.idTokenEncryptionMethod >selected</#if>>AES GCM using 256 bit keys</option>
-					</select>
-					</td>
-					<th><@locale code="apps.oauth.connect.userInfoEncryptionMethod" /></th>
-					<td >
-						<select  id="userInfoEncryptionMethod" name="userInfoEncryptionMethod" class="form-control  form-select">
-							<option value="none" <#if   'none'==model.userInfoEncryptionMethod >selected</#if>>No encryption</option>
-							<option value="A128CBC+HS256" <#if   'A128CBC+HS256'==model.userInfoEncryptionMethod >selected</#if>>Composite Authenticated Encryption algorithm using AES in Cipher Block Chaining (CBC) mode with PKCS #5 padding with an integrity calculation using HMAC SHA-256, using a 256 bit CMK (and 128 bit CEK)</option>
-							<option value="A256CBC+HS512" <#if   'A256CBC+HS512'==model.userInfoEncryptionMethod >selected</#if>>Composite Authenticated Encryption algorithm using AES in CBC mode with PKCS #5 padding with an integrity calculation using HMAC SHA-512, using a 512 bit CMK (and 256 bit CEK)</option>
-							<option value="A128GCM" <#if   'A128GCM'==model.userInfoEncryptionMethod >selected</#if>>AES GCM using 128 bit keys</option>
-							<option value="A256GCM" <#if   'A256GCM'==model.userInfoEncryptionMethod >selected</#if>>AES GCM using 256 bit keys</option>
-						</select>
-					</td>
-				</tr>
+                    <th ><@locale code="apps.oauth.connect.signatureKey" /></th>
+                    <td colspan ="3">
+                        <textarea class="form-control" id="signatureKey" name="signatureKey">${model.signatureKey!}</textarea>
+                    </td>
+                </tr>
+                <tr>
+                    <th style="width:15%;"><@locale code="apps.oauth.connect.algorithm" /></th>
+                    <td style="width:35%;">
+                        <select id="algorithm" name="algorithm" class="form-control  form-select" >
+                            <option value="NONE"         <#if 'NONE'==model.algorithm>selected</#if> >NONE</option>
+                            <option value="RSA1_5"       <#if 'RSA1_5'==model.algorithm>selected</#if> >RSA1_5</option>
+                            <option value="RSA_OAEP"     <#if 'RSA_OAEP'==model.algorithm>selected</#if>>RSA_OAEP</option>
+                            <option value="RSA-OAEP-256" <#if 'RSA-OAEP-256'==model.algorithm>selected</#if>>RSA-OAEP-256</option>
+                            <option value="A128KW"       <#if 'A128KW'==model.algorithm>selected</#if>>A128KW</option>
+                            <option value="A192KW"       <#if 'A192KW'==model.algorithm>selected</#if>>A192KW</option>
+                            <option value="A256KW"       <#if 'A256KW'==model.algorithm>selected</#if>>A256KW</option>
+                            <option value="A128GCMKW"    <#if 'A128GCMKW'==model.algorithm>selected</#if>>A128GCMKW</option>
+                            <option value="A192GCMKW"    <#if 'A192GCMKW'==model.algorithm>selected</#if>>A192GCMKW</option>
+                            <option value="A256GCMKW"    <#if 'A256GCMKW'==model.algorithm>selected</#if>>A256GCMKW</option>
+                        </select>
+                    </td>
+                    <th width="140px"><@locale code="apps.oauth.connect.encryptionMethod" /></th>
+                    <td width="340px">
+                        <select id="encryptionMethod" name="encryptionMethod"   class="form-control  form-select">
+                            <option value="A128GCM"        <#if 'A128GCM'==model.encryptionMethod>selected</#if>       >A128GCM</option>
+                            <option value="A192GCM"        <#if 'A192GCM'==model.encryptionMethod>selected</#if>       >A192GCM</option>
+                            <option value="A256GCM"        <#if 'A256GCM'==model.encryptionMethod>selected</#if>       >A256GCM</option>
+                            
+                            <option value="A128CBC-HS256"  <#if 'A128CBC-HS256'==model.encryptionMethod>selected</#if> >A128CBC-HS256</option>
+                            <option value="A192CBC-HS384"  <#if 'A192CBC-HS384'==model.encryptionMethod>selected</#if> >A192CBC-HS384</option>
+                            <option value="A256CBC-HS512"  <#if 'A256CBC-HS512'==model.encryptionMethod>selected</#if> >A256CBC-HS512</option>
+                            
+                            <option value="XC20P"          <#if 'XC20P'==model.encryptionMethod>selected</#if>         >XC20P</option>
+                        </select>
+                    </td>
+                </tr>
+                <tr>
+                    <th ><@locale code="apps.oauth.connect.algorithmKey" /></th>
+                    <td colspan ="3">
+                        <textarea class="form-control" id="algorithmKey" name="algorithmKey">${model.algorithmKey!}</textarea>
+                    </td>
+                </tr>
 				
 				</tbody>
 			  </table>

+ 0 - 2
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/tokenbased/appAdd.ftl

@@ -55,8 +55,6 @@
 										<option value="DESede">DESede</option>
 										<option value="Blowfish">Blowfish</option>
 										<option value="AES"  selected>AES</option>
-										<option value="HS256"  >HMAC SHA-256</option>
-										<option value="RS256"  >RSA SHA-256</option>
 									</select>
 									<b class="orange">*</b><label for="algorithm"></label>
 								</td>

+ 0 - 3
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/tokenbased/appUpdate.ftl

@@ -58,9 +58,6 @@
 											<option value="DESede" <#if 'DESede'==model.algorithm>selected</#if>>DESede</option>
 											<option value="Blowfish" <#if 'Blowfish'==model.algorithm>selected</#if>>Blowfish</option>
 											<option value="AES" <#if 'AES'==model.algorithm>selected</#if>>AES</option>
-											<option value="HS256" <#if 'HS256'==model.algorithm>selected</#if>>HMAC SHA-256</option>
-											<option value="RS256" <#if 'RS256'==model.algorithm>selected</#if>>RSA SHA-256</option>
-											
 										</select>
 									</td>
 									<th style="width:15%;"><@locale code="apps.tokenbased.algorithmKey" /></th>