shjung 1 year ago
parent
commit
9b35c8f874

+ 5 - 0
pom.xml

@@ -132,6 +132,11 @@
             <artifactId>aspectjweaver</artifactId>
             <version>1.9.22</version>
         </dependency>
+        <dependency>
+            <groupId>com.azure</groupId>
+            <artifactId>azure-core</artifactId>
+            <version>1.49.0</version>
+        </dependency>
 
     </dependencies>
 

+ 174 - 40
src/main/java/com/aip/gateway/api/aip/AuthDelegateImpl.java

@@ -18,7 +18,6 @@ import java.util.Date;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 
-
 @Slf4j
 @Getter
 @Setter
@@ -28,20 +27,34 @@ public class AuthDelegateImpl implements IAuthDelegate {
     private String lastErrMsg;
     private AipConfig aipConfig;
     private String refreshToken;
-    private ConfidentialClientApplication confidentialApp;
+    private ConfidentialClientApplication confidentialApp = null;
     private IAuthenticationResult authenticationResult = null;
+
+    private Date expiredDate = new Date();
+    private String accessToken = "x";
+
     private final String instance = "https://login.microsoftonline.com/";
     private final String authority = "https://login.windows.net/";
     private final String scope = "https://graph.microsoft.com/.default";
 
+    private static int LOGIN_TYPE = 0;
+    private static String CLIENT_ID = "";
+    private static String TENANT_ID = "";
+    private static String AUTHORITY = "";
+    private static Set<String> SCOPE = Collections.singleton("");
+
     public AuthDelegateImpl(AipConfig aipConfig) throws Exception {
         this.aipConfig = aipConfig;
         resetError();
 
         String cacheKey = aipConfig.getClientId() + "_" + aipConfig.getTenantId() + "_AppTokenCache";
         MemoryTokenCacheWithEviction memoryTokenCacheWithEviction = new MemoryTokenCacheWithEviction(cacheKey);
+        //TokenCacheAspect tokenCacheAspect = new TokenCacheAspect("token_cache.json");
 
+        CLIENT_ID = aipConfig.getClientId();
+        TENANT_ID = aipConfig.getTenantId();
         if (aipConfig.getLoginType() == AipConfig.authLoginPassword) {
+            LOGIN_TYPE = 0;
             confidentialApp = ConfidentialClientApplication.builder(
                             aipConfig.getClientId(),
                             ClientCredentialFactory.createFromSecret(aipConfig.getSecretValue()))
@@ -50,6 +63,7 @@ public class AuthDelegateImpl implements IAuthDelegate {
                     .build();
         }
         else if (aipConfig.getLoginType() == AipConfig.authLoginCert) {
+            LOGIN_TYPE = 1;
             InputStream certStream = new ByteArrayInputStream(Files.readAllBytes(Paths.get(aipConfig.getCertThumbPrint())));
 
             String password = "hanteinfo1234!";
@@ -63,73 +77,193 @@ public class AuthDelegateImpl implements IAuthDelegate {
         else {
             throw new Exception("지원하지 않는 AIP 인증 방법 입니다.");
         }
-    }
-    public void resetError() {
-        lastErrNo = 0;
-        lastErrMsg = "";
-    }
-    public void setError(int errNo, String errMsg1, String errMsg2) {
-        lastErrNo = errNo;
-        if (errMsg2 == null || errMsg2.isEmpty()) {
-            lastErrMsg = errMsg1;
+        if (confidentialApp != null) {
+            log.info("AuthDelegateImpl: Refresh token provider setting.");
+            //confidentialApp.appTokenProvider();
         }
-        else {
-            lastErrMsg = errMsg1 + "\r\n" + errMsg2;
-        }
-        log.error("AuthDelegateImpl:setError, {}, {}, {}", lastErrNo, errMsg1, errMsg2);
     }
     @Override
     public String acquireToken(Identity identity, String authority, String resource, String claim) {
-        //log.error("acquireToken--------------------------------");
         if (authenticationResult != null) {
             if (authenticationResult.expiresOnDate().before(new Date())) {
                 log.error("Access token expired #################################################################################################");
             }
         }
         return AcquireTokenByCertificate(identity, authority, resource, claim);
-        //return authenticationResult.accessToken();
     }
+    private static IAuthenticationResult acquireTokenInteractive() throws Exception {
+
+        // Load token cache from file and initialize token cache aspect. The token cache will have
+        // dummy data, so the acquireTokenSilently call will fail.
+        //TokenCacheAspect tokenCacheAspect = new TokenCacheAspect("sample_cache.json");
+        String cacheKey = CLIENT_ID + "_" + TENANT_ID + "_AppTokenCache";
+        MemoryTokenCacheWithEviction memoryTokenCacheWithEviction = new MemoryTokenCacheWithEviction(cacheKey);
+
+        ConfidentialClientApplication pca = ConfidentialClientApplication.builder(
+                        CLIENT_ID,
+                            ClientCredentialFactory.createFromSecret("CvW8Q~0iANtLN1Y2EXR_nVyYb_tQTDwjW-Z7Ndg3"))
+                    .authority("https://login.microsoftonline.com/" + TENANT_ID)
+                    .setTokenCacheAccessAspect(memoryTokenCacheWithEviction)
+                    .build();
+
+        Set<IAccount> accountsInCache = pca.getAccounts().join();
+        // Take first account in the cache. In a production application, you would filter
+        // accountsInCache to get the right account for the user authenticating.
+        IAccount account = accountsInCache.iterator().next();
+
+        IAuthenticationResult result;
+        try {
+            SilentParameters silentParameters =
+                    SilentParameters
+                            .builder(SCOPE, account)
+                            .build();
+
+            // try to acquire token silently. This call will fail since the token cache
+            // does not have any data for the user you are trying to acquire a token for
+            result = pca.acquireTokenSilently(silentParameters).join();
+        } catch (Exception ex) {
+            if (ex.getCause() instanceof MsalException) {
+
+                ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(SCOPE).build();
+                result = pca.acquireToken(clientCredentialParam).get();
+            } else {
+                // Handle other exceptions accordingly
+                throw ex;
+            }
+        }
+        return result;
+    }
+
     private String AcquireTokenByCertificate(Identity identity, String authority, String resource, String claims)
     {
-        // AuthenticationResult result;
-        // var authorityUri = new Uri(authority);
-        // authority = $"https://{authorityUri.Host}/{_aipConfig.TenantId}";
-        Set<String> scope;
+        Set<String> scope = null;
         if (resource.endsWith("/")){
             scope = Collections.singleton(resource + ".default");
         }
         else {
             scope = Collections.singleton(resource + "/.default");
         }
-        try
-        {
-            ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
-                            scope
-                    )
-                    .build();
-
-//            RefreshTokenParameters refreshTokenParameters = RefreshTokenParameters
-//                    .builder(
-//                            scope,
-//                            refreshToken)
-//                    .build();
+        // authority                            scope
+        // https://login.windows.net/common     https://syncservice.o365syncservice.com/.default
+        // https://login.windows.net/common     https://syncservice.o365syncservice.com/.default
+        // https://login.windows.net/common     https://syncservice.o365syncservice.com/.default
+        // https://login.windows.net/common     https://aadrm.com/.default
+        // https://login.windows.net/common     https://aadrm.com/.default
+        // https://login.windows.net/common     https://aadrm.com/.default
+        // Wed Jun 05 10:41:59 KST 2024
+        // https://login.windows.net/2e58414a-c6ae-43ff-aaf5-45ab8b78a404     https://aadrm.com/.default
 
-            //RefreshTokenParameters refreshTokenParam = RefreshTokenParameters.builder().build();
-            //confidentialApp.acquireTokenSilently(clientCredentialParam);
-            //log.error("AcquireTokenByCertificate--------------------------------Before");
+        log.info("acquireToken: identity = {}, authority = {}, scope = {}", identity.getEmail(), authority, scope);
+        try {
+            ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(scope).build();
             CompletableFuture<IAuthenticationResult> future = confidentialApp.acquireToken(clientCredentialParam);
             authenticationResult = future.get();
-            //log.error("AcquireTokenByCertificate---------------------------------After");
+            if (!expiredDate.equals(authenticationResult.expiresOnDate())) {
+                log.info("acquireToken: expiredDate = {}, expiresOnDate = {}", expiredDate, authenticationResult.expiresOnDate());
+                expiredDate = authenticationResult.expiresOnDate();
+            }
+            if (!accessToken.equals(authenticationResult.accessToken())) {
+                log.info("acquireToken: accessToken: OLD = {}", accessToken);
+                log.info("acquireToken: accessToken: NEW = {}", authenticationResult.accessToken());
+                accessToken = authenticationResult.accessToken();
+            }
             return authenticationResult.accessToken();
         }
         catch (Exception ex) {
             if (ex.getCause() instanceof MsalException) {
-                setError(1, "AcquireTokenByCertificate::AcquireTokenByCertificate, Scope provided is not supported.", ex.getMessage());
+                setError(1, "AuthDelegateImpl:acquireToken, Scope provided is not supported.", ex.getMessage());
             } else {
-                setError(1, "AcquireTokenByCertificate::AcquireTokenByCertificate Failed.", ex.getMessage());
+                setError(1, "AuthDelegateImpl:acquireToken Failed.", ex.getMessage());
             }
         }
-
         return null;
     }
+    private String AcquireTokenByCertificate2(Identity identity, String authority, String resource, String claims)
+    {
+        Set<String> scope = null;
+        if (resource.endsWith("/")){
+            scope = Collections.singleton(resource + ".default");
+        }
+        else {
+            scope = Collections.singleton(resource + "/.default");
+        }
+        // authority                            scope
+        // https://login.windows.net/common     https://syncservice.o365syncservice.com/.default
+        // https://login.windows.net/common     https://syncservice.o365syncservice.com/.default
+        // https://login.windows.net/common     https://syncservice.o365syncservice.com/.default
+        // https://login.windows.net/common     https://aadrm.com/.default
+        // https://login.windows.net/common     https://aadrm.com/.default
+        // https://login.windows.net/common     https://aadrm.com/.default
+        // Wed Jun 05 10:41:59 KST 2024
+        // https://login.windows.net/2e58414a-c6ae-43ff-aaf5-45ab8b78a404     https://aadrm.com/.default
+
+        log.info("acquireToken: identity = {}, authority = {}, scope = {}", identity.getEmail(), authority, scope);
+        try {
+            Set<IAccount> accountsInCache = confidentialApp.getAccounts().get();
+            // Take first account in the cache. In a production application, you would filter accountsInCache to get the right account for the user authenticating.
+            IAccount account = accountsInCache.iterator().next();
+            SilentParameters silentParameters = SilentParameters .builder(scope, account) .build();
+            CompletableFuture<IAuthenticationResult> future = confidentialApp.acquireTokenSilently(silentParameters);
+            authenticationResult = future.get();
+        }
+        catch (Exception ex) {
+            try {
+                if (ex.getCause() instanceof MsalException) {
+                    log.error("AuthDelegateImpl:acquireToken refresh");
+                    ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(scope).build();
+                    CompletableFuture<IAuthenticationResult> future = confidentialApp.acquireToken(clientCredentialParam);
+                    authenticationResult = future.get();
+                }
+                else {
+                    setError(1, "AuthDelegateImpl:acquireToken acquireTokenSilently Exception.", ex.getMessage());
+                }
+            }
+            catch (Exception e) {
+                setError(2, "AuthDelegateImpl:acquireToken MsalException acquireToken Exception Failed.", ex.getMessage());
+            }
+        }
+        if (!accessToken.equals(authenticationResult.accessToken())) {
+            log.info("acquireToken: accessToken: OLD = {}", accessToken);
+            log.info("acquireToken: accessToken: NEW = {}", authenticationResult.accessToken());
+            accessToken = authenticationResult.accessToken();
+        }
+        return authenticationResult.accessToken();
+
+//        try {
+//            ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(scope).build();
+//            CompletableFuture<IAuthenticationResult> future = confidentialApp.acquireToken(clientCredentialParam);
+//            authenticationResult = future.get();
+//            if (!expiredDate.equals(authenticationResult.expiresOnDate())) {
+//                log.info("acquireToken: expiredDate = {}, expiresOnDate = {}", expiredDate, authenticationResult.expiresOnDate());
+//                expiredDate = authenticationResult.expiresOnDate();
+//            }
+//            if (!accessToken.equals(authenticationResult.accessToken())) {
+//                log.info("acquireToken: accessToken: OLD = {}", accessToken);
+//                log.info("acquireToken: accessToken: NEW = {}", authenticationResult.accessToken());
+//                accessToken = authenticationResult.accessToken();
+//            }
+//            return authenticationResult.accessToken();
+//        }
+//        catch (Exception ex) {
+//            if (ex.getCause() instanceof MsalException) {
+//                setError(1, "AuthDelegateImpl:acquireToken, Scope provided is not supported.", ex.getMessage());
+//            } else {
+//                setError(1, "AuthDelegateImpl:acquireToken Failed.", ex.getMessage());
+//            }
+//        }
+    }
+    public void resetError() {
+        lastErrNo = 0;
+        lastErrMsg = "";
+    }
+    public void setError(int errNo, String errMsg1, String errMsg2) {
+        lastErrNo = errNo;
+        if (errMsg2 == null || errMsg2.isEmpty()) {
+            lastErrMsg = errMsg1;
+        }
+        else {
+            lastErrMsg = errMsg1 + "\r\n" + errMsg2;
+        }
+        log.error("AuthDelegateImpl:setError, {}, {}, {}", lastErrNo, errMsg1, errMsg2);
+    }
 }

+ 7 - 5
src/main/java/com/aip/gateway/api/aip/manager/FileManager.java

@@ -185,7 +185,7 @@ public class FileManager extends AbstractManager {
                     .owner(protection.getOwner())
                     .issuedTo(protection.getIssuedTo())
                     .isIssuedToOwner(protection.getIsIssuedToOwner())
-                    .contentId(protection.getContentId())
+                    .contentId(protection.getContentId())                           // TODO: commitAsync 이후 handler 를 바로 사용하면 여기서 오류 발생.
                     .auditedExtractAllowed(protection.getAuditedExtractAllowed())
                     .blockSize(protection.getBlockSize())
                     .protectionDescriptor(null)
@@ -314,6 +314,7 @@ public class FileManager extends AbstractManager {
             }
         }
         catch (Exception ex) {
+            log.error("setLabel: setLabel Exception Error: {}", ex.getMessage());
             result.errorNo = 203;
             result.errorMsg = ex.getMessage();
             setError(53, "FileManager::SetLabel Failed.", ex.getMessage());
@@ -331,9 +332,10 @@ public class FileManager extends AbstractManager {
         }
         else {
             result.errorNo = 204;
-            result.errorMsg = "AIP File CommitAsync Failed.";
+            result.errorMsg = "AIP File CommitAsync(setLabel) Failed.";
             setError(53, "FileManager::SetLabel Failed.", "Label Id: " + labelId + ", SetLabel Failed.");
         }
+
         getActionFileInfo(actualFileName, result);
         return result;
     }
@@ -392,7 +394,7 @@ public class FileManager extends AbstractManager {
         }
         else {
             result.errorNo = 204;
-            result.errorMsg = "AIP File CommitAsync Failed.";
+            result.errorMsg = "AIP File CommitAsync(deleteLabel) Failed.";
             setError(54, "FileManager::DeleteLabel Failed.", "DeleteLabel Failed by " + ownerEmail);
         }
         getActionFileInfo(actualFileName, result);
@@ -445,7 +447,7 @@ public class FileManager extends AbstractManager {
         }
         else {
             result.errorNo = 206;
-            result.errorMsg = "AIP File CommitAsync Failed.";
+            result.errorMsg = "AIP File CommitAsync(setProtection) Failed.";
             setError(56, "FileManager::SetProtect Failed.", "Template Id: " + templateId + ", SetProtect Failed.");
         }
         getActionFileInfo(actualFileName, result);
@@ -509,7 +511,7 @@ public class FileManager extends AbstractManager {
         }
         else {
             result.errorNo = 204;
-            result.errorMsg = "AIP File CommitAsync Failed.";
+            result.errorMsg = "AIP File CommitAsync(removeProtection) Failed.";
             setError(53, "FileManager::RemoveProtection Failed.", "RemoveProtection Failed by " + ownerEmail);
         }
         getActionFileInfo(actualFileName, result);

+ 0 - 1
src/main/java/com/aip/gateway/api/aip/utils/MsalAbstractTokenCacheProvider.java

@@ -9,7 +9,6 @@ import java.util.concurrent.ExecutionException;
 public abstract class MsalAbstractTokenCacheProvider implements ITokenCacheAccessAspect {
 
     private final String cacheKey;
-
     /**
      * Constructor.
      * @param cacheKey - currently the app dev needs to configure the cache key. In the future, MSAL will suggest this.

+ 42 - 0
src/main/java/com/aip/gateway/api/aip/utils/TokenCacheAspect.java

@@ -0,0 +1,42 @@
+package com.aip.gateway.api.aip.utils;
+
+import com.microsoft.aad.msal4j.ITokenCacheAccessAspect;
+import com.microsoft.aad.msal4j.ITokenCacheAccessContext;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+@Slf4j
+public class TokenCacheAspect implements ITokenCacheAccessAspect {
+
+    private String data;
+
+    public TokenCacheAspect(String fileName) {
+        this.data = readDataFromFile(fileName);
+    }
+
+    @Override
+    public void beforeCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) {
+        iTokenCacheAccessContext.tokenCache().deserialize(data);
+    }
+
+    @Override
+    public void afterCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) {
+        data = iTokenCacheAccessContext.tokenCache().serialize();
+        // you could implement logic here to write changes to file
+    }
+
+    private static String readDataFromFile(String resource) {
+        try {
+            URL path = TokenCacheAspect.class.getResource(resource);
+            return new String(
+                    Files.readAllBytes(
+                            Paths.get(path.toURI())));
+        } catch (Exception ex){
+            log.error("Error reading data from file: " + ex.getMessage());
+            throw new RuntimeException(ex);
+        }
+    }
+}

+ 0 - 22
src/main/resources/logback-spring-appender.xml

@@ -7,28 +7,6 @@
         </encoder>
     </appender>
 
-    <appender name="FILE_AIP" class="ch.qos.logback.classic.sift.SiftingAppender">
-        <discriminator>
-            <key>id</key>
-            <defaultValue>${LOG_FILE_NAME_PACKET}</defaultValue>
-        </discriminator>
-        <sift>
-            <appender name="FILE-${id}" class="ch.qos.logback.core.rolling.RollingFileAppender">
-                <file>${LOG_PATH}packet/${id}.log</file>
-                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
-                    <charset>${LOG_CHARSET}</charset>
-                    <Pattern>${LOG_PATTERN_PACKET}</Pattern>
-                </encoder>
-
-                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-                    <FileNamePattern>${LOG_BACKUP_PATH}packet/${id}.${LOG_FILE_NAME_PATTERN}</FileNamePattern>
-                    <maxFileSize>${MAX_FILESIZE}</maxFileSize>
-                    <maxHistory>${MAX_HISTORY}</maxHistory>
-                </rollingPolicy>
-            </appender>
-        </sift>
-    </appender>
-
     <appender name="FILE_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <file>${LOG_PATH}${LOG_FILE_NAME}</file>
         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

+ 0 - 8
src/main/resources/logback-spring.xmlx → src/main/resources/logback-spring.xml

@@ -16,14 +16,12 @@
     <property name="LOG_FILE_NAME"             value="${PROJECT_NAME}.log"/>
     <property name="LOG_FILE_NAME_ERROR"       value="${PROJECT_NAME}.err.log"/>
     <property name="LOG_FILE_NAME_PATTERN"     value="%d{yyyyMMdd}_%i.log.gz"/>
-    <property name="LOG_FILE_NAME_AIP"         value="${PROJECT_PREFIX}-aip"/>
     <property name="LOG_FILE_NAME_SCHEDULE"    value="${PROJECT_PREFIX}-schedule.log"/>
 
     <property name="MAX_FILESIZE" value="10MB"/>
     <property name="MAX_HISTORY"  value="30"/>
     <property name="LOG_PATTERN_FILE"        value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
     <property name="LOG_PATTERN_ERROR"       value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%30t] [%5level] %42logger{35}.%-20M ${PID:-} %n%msg%n"/>
-    <property name="LOG_PATTERN_AIP"         value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
     <property name="LOG_PATTERN_SCHEDULE"    value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
     <property name="LOG_PATTERN_CONSOLE"     value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%5level] %msg %n"/>
 
@@ -42,12 +40,6 @@
         <appender-ref ref="FILE_ERROR"/>
     </logger>
 
-    <logger name="${APP_CLASS_PATH}.aip" level="INFO" additivity="false">
-        <appender-ref ref="CONSOLE"/>
-        <appender-ref ref="FILE_AIP"/>
-        <appender-ref ref="FILE_ERROR"/>
-    </logger>
-
     <logger name="${APP_CLASS_PATH}.scheduler" level="INFO" additivity="false">
         <appender-ref ref="CONSOLE"/>
         <appender-ref ref="FILE_SCHEDULE"/>