diff --git a/packages/java/auth.provider/pom.xml b/packages/java/auth.provider/pom.xml
index df13241ee..0185b73f6 100644
--- a/packages/java/auth.provider/pom.xml
+++ b/packages/java/auth.provider/pom.xml
@@ -31,48 +31,59 @@
1.8
${java.version}
${java.version}
+ 5.4.1
+ 5.11.0
+ 2.2.0
+ 3.1.7
+ 1.0
+ 0.12.6
+ 3.12.4
org.junit.jupiter
- junit-jupiter-api
- 5.11.0
+ junit-jupiter-api
+ ${junit-version}
test
org.junit.jupiter
junit-jupiter-engine
- 5.11.0
+ ${junit-version}
test
io.github.cdimascio
dotenv-java
- 2.2.0
+ ${cdimascio-version}
org.glassfish.jersey.core
jersey-common
- 3.1.7
+ ${jersey-version}
org.mockito
mockito-core
- 3.12.4
+ ${mockito-version}
test
com.affinidi.tdk
common
- 1.0
+ ${affinidi-common-version}
io.jsonwebtoken
jjwt-api
- 0.12.6
+ ${jsonwebtoken-version}
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+ ${apache-http-version}
-
diff --git a/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/AuthProvider.java b/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/AuthProvider.java
index 93e3ddb13..aba3326b3 100644
--- a/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/AuthProvider.java
+++ b/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/AuthProvider.java
@@ -1,7 +1,12 @@
package com.affinidi.tdk.authProvider;
+import java.util.UUID;
+
+import com.affinidi.tdk.authProvider.helper.JwtUtil;
+import com.affinidi.tdk.authProvider.type.IotaJwtOutput;
import com.affinidi.tdk.common.EnvironmentUtil;
+
public class AuthProvider {
private final String projectId;
@@ -25,13 +30,16 @@ public class AuthProvider {
this.tokenEndPoint = eUtil.getElementAuthTokenUrlForEnvironment();
}
- public boolean shouldRefreshToken(){
- // TODO Implement shouldRefreshToken
- return false;
+ public boolean shouldRefreshToken() {
+ if(this.projectScopeToken == null){
+ return true;
+ }
+ return !(JwtUtil.validProjectTokenPresent(this.projectScopeToken, this.apiGatewayUrl));
}
public String fetchProjectScopedToken(){
boolean tokenFetchRequired = shouldRefreshToken();
+
if(tokenFetchRequired){
this.projectScopeToken = fetchProjectScopedToken(apiGatewayUrl, projectId, tokenId, apiGatewayUrl, privateKey, passphrase, keyId);
}
@@ -50,6 +58,16 @@ private String fetchProjectScopedToken(String apiGatewayUrl, String projectId, S
return null;
}
+ public IotaJwtOutput signIotaJwt(String iotaConfigId, String did, String iotaSessionId) throws Exception {
+
+ String iotaTokenId = "token/"+tokenId;
+ String iotaSessionID = (iotaSessionId != null) ? iotaSessionId : UUID.randomUUID().toString();
+
+ String iotaJwt = JwtUtil.signIotaPayload(iotaTokenId, did, privateKey, passphrase, keyId, projectId, iotaConfigId, iotaSessionID);
+
+ return new IotaJwtOutput(iotaSessionID, iotaJwt);
+ }
+
public static class Configurations{
private String projectId;
private String tokenId;
@@ -84,7 +102,6 @@ public AuthProvider build() throws Exception{
}
return new AuthProvider(this);
}
-
}
public String getProjectId() {
@@ -107,7 +124,6 @@ public String getPassphrase() {
return passphrase;
}
-
public String getApiGatewayUrl() {
return apiGatewayUrl;
}
diff --git a/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/helper/JwtUtil.java b/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/helper/JwtUtil.java
index b9a0dcb92..1a7fc8319 100644
--- a/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/helper/JwtUtil.java
+++ b/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/helper/JwtUtil.java
@@ -1,21 +1,140 @@
package com.affinidi.tdk.authProvider.helper;
+import java.security.AlgorithmParameters;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.logging.Logger;
+import javax.crypto.Cipher;
+import javax.crypto.EncryptedPrivateKeyInfo;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.MalformedJwtException;
public class JwtUtil {
+ private static Logger logger = Logger.getLogger(JwtUtil.class.getName());
- public String signPayload(String tokenId, String audience, String privateKey, String passphrase, String keyId){
-
- return null;
+ public static String signPayload(String tokenId, String audience, String privateKeyString, String passphrase, String keyId) throws Exception{
+
+ long issueTimeInSeconds = System.currentTimeMillis() / 1000;
+
+ Map claims = new HashMap<>();
+ claims.put("iss", tokenId);
+ claims.put("sub", tokenId);
+ claims.put("aud", audience);
+ claims.put("jti", UUID.randomUUID().toString());
+ claims.put("exp", issueTimeInSeconds + (5 * 60));
+ claims.put("iat", issueTimeInSeconds);
+
+ return generateJwt(derivePrivateKey(privateKeyString, passphrase), claims);
+ }
+ public static String signIotaPayload(String tokenId, String audience, String privateKeyString, String passphrase,
+ String keyId, String projectId, String iotaConfigId, String iotaSessionId) throws Exception{
+ long issueTimeInSeconds = System.currentTimeMillis() / 1000;
+
+ Map claims = new HashMap<>();
+ claims.put("iss", tokenId);
+ claims.put("sub", tokenId);
+ claims.put("kid", tokenId);
+ claims.put("aud", audience);
+ claims.put("jti", UUID.randomUUID().toString());
+ claims.put("exp", issueTimeInSeconds + (5 * 60));
+ claims.put("iat", issueTimeInSeconds);
+ claims.put("project_id", projectId);
+ claims.put("iota_configuration_id", iotaConfigId);
+ claims.put("iota_session_id", iotaSessionId);
+ claims.put("scope", "iota_channel");
+
+ return generateJwt(derivePrivateKey(privateKeyString, passphrase), claims);
}
- public static String fetchPublicKey(String apiGatewayUrl){
+ public static PublicKey fetchPublicKey(String apiGatewayUrl){
+ // TODO Implement fetchPublicKey to call the apiGateway
+ // and extract public key from the received jwk
+
return null;
}
- public static boolean validateToken(String token, String publicKey){
+ public static boolean validProjectTokenPresent(String token, String apiGatewayUrl){
+ PublicKey publicKey = fetchPublicKey(apiGatewayUrl);
+ try{
+ Jwts.parser().verifyWith(publicKey).build().parse(token);
+ }catch(ExpiredJwtException ejException){
+ return true;
+ }catch(MalformedJwtException mjException){
+ return true;
+ }catch(Exception eException){
+ return true;
+ }
return false;
}
+ private static PrivateKey derivePrivateKey(String privateKeyString, String passphrase) throws Exception{
+
+ PrivateKey privateKey = null;
+ try{
+ if (!passphrase.isEmpty()) {
+ privateKey = getPrivateKeyFromString(privateKeyString);
+ } else {
+ privateKey = getEncryptedPrivateKeyFromString(privateKeyString, passphrase);
+ }
+ }catch(Exception exception){
+ logger.severe("extractPrivateKey : Issue in retrieving private key from the string passed");
+ throw new Exception("Could not derive private key out of the configurations. Exception : "+exception.toString());
+ }
+
+ return privateKey;
+ }
+
+ private static String generateJwt(PrivateKey privateKey, Map claims){
+ return Jwts.builder()
+ .claims(claims)
+ .signWith(privateKey, Jwts.SIG.RS256)
+ .compact();
+ }
+
+ private static PrivateKey getPrivateKeyFromString(String privateKeyPEM) throws Exception {
+ String privateKeyContent = privateKeyPEM
+ .replace("-----BEGIN PRIVATE KEY-----", "")
+ .replace("-----END PRIVATE KEY-----", "")
+ .replaceAll("\\s", "");
+
+ byte[] encoded = Base64.getDecoder().decode(privateKeyContent);
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
+ return keyFactory.generatePrivate(keySpec);
+ }
+
+ private static PrivateKey getEncryptedPrivateKeyFromString(String encryptedPrivateKeyPEM, String password)
+ throws Exception {
+ String privateKeyContent = encryptedPrivateKeyPEM
+ .replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "")
+ .replace("-----END ENCRYPTED PRIVATE KEY-----", "");
+
+ byte[] encodedKey = Base64.getDecoder().decode(privateKeyContent);
+ EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(encodedKey);
+ Cipher cipher = Cipher.getInstance(encryptedPrivateKeyInfo.getAlgName());
+ PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
+ SecretKeyFactory secFac = SecretKeyFactory.getInstance(encryptedPrivateKeyInfo.getAlgName());
+ Key pbeKey = secFac.generateSecret(pbeKeySpec);
+ AlgorithmParameters algParams = encryptedPrivateKeyInfo.getAlgParameters();
+ cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
+ PKCS8EncodedKeySpec pkcs8KeySpec = encryptedPrivateKeyInfo.getKeySpec(cipher);
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+
+ return keyFactory.generatePrivate(pkcs8KeySpec);
+ }
+
+
+
}
diff --git a/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/type/IotaJwtOutput.java b/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/type/IotaJwtOutput.java
new file mode 100644
index 000000000..da31b2092
--- /dev/null
+++ b/packages/java/auth.provider/src/main/java/com/affinidi/tdk/authProvider/type/IotaJwtOutput.java
@@ -0,0 +1,20 @@
+package com.affinidi.tdk.authProvider.type;
+
+public class IotaJwtOutput {
+ private final String iotaSessionId;
+ private final String iotaJwt;
+
+ public IotaJwtOutput(String iotaSessionId, String iotaJwt){
+ this.iotaJwt = iotaJwt;
+ this.iotaSessionId = iotaSessionId;
+ }
+
+ public String getIotaSessionId() {
+ return iotaSessionId;
+ }
+ public String getIotaJwt() {
+ return iotaJwt;
+ }
+
+
+}
diff --git a/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/AuthProviderTest.java b/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/AuthProviderTest.java
new file mode 100644
index 000000000..b0d721ead
--- /dev/null
+++ b/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/AuthProviderTest.java
@@ -0,0 +1,27 @@
+package com.affinidi.tdk.authProvider;
+
+import org.junit.jupiter.api.Test;
+
+public class AuthProviderTest {
+
+ @Test
+ void testFetchProjectScopedToken() {
+
+ }
+
+ @Test
+ void testGetUserAccessToken() {
+
+ }
+
+ @Test
+ void testShouldRefreshToken() {
+
+ }
+
+ @Test
+ void testSignIotaJwt() {
+
+ }
+
+}
diff --git a/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/helper/JwtUtilTest.java b/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/helper/JwtUtilTest.java
new file mode 100644
index 000000000..736c10d2d
--- /dev/null
+++ b/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/helper/JwtUtilTest.java
@@ -0,0 +1,39 @@
+package com.affinidi.tdk.authProvider.helper;
+
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class JwtUtilTest {
+
+
+
+ @BeforeEach
+ void setUp() {
+
+ }
+
+ @Test
+ void testFetchPublicKey() {
+
+ }
+
+ @Test
+ void testSignIotaPayload() {
+
+ }
+
+ @Test
+ void testSignPayload() {
+
+ }
+
+ @Test
+ void testValidProjectTokenPresent() {
+
+ }
+
+
+
+
+}
diff --git a/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/helper/ProjectTokenUtilTest.java b/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/helper/ProjectTokenUtilTest.java
deleted file mode 100644
index 176e66f5e..000000000
--- a/packages/java/auth.provider/src/test/java/com/affinidi/tdk/authProvider/helper/ProjectTokenUtilTest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.affinidi.tdk.authProvider.helper;
-
-
-import org.junit.jupiter.api.BeforeEach;
-
-public class ProjectTokenUtilTest {
-
-
-
- @BeforeEach
- void setUp() {
-
- }
-
-
-
-
-}
diff --git a/packages/java/auth.provider/target/classes/com/affinidi/tdk/authProvider/AuthProvider$Configurations.class b/packages/java/auth.provider/target/classes/com/affinidi/tdk/authProvider/AuthProvider$Configurations.class
deleted file mode 100644
index 582b949c8..000000000
Binary files a/packages/java/auth.provider/target/classes/com/affinidi/tdk/authProvider/AuthProvider$Configurations.class and /dev/null differ
diff --git a/packages/java/auth.provider/target/classes/com/affinidi/tdk/authProvider/AuthProvider.class b/packages/java/auth.provider/target/classes/com/affinidi/tdk/authProvider/AuthProvider.class
deleted file mode 100644
index f6d52cdbc..000000000
Binary files a/packages/java/auth.provider/target/classes/com/affinidi/tdk/authProvider/AuthProvider.class and /dev/null differ