This is an automated email from the ASF dual-hosted git repository.

aicam pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/main by this push:
     new 1c3284534a chore: change jwt token expiration as a configurable 
variable (#3693)
1c3284534a is described below

commit 1c3284534ad48d32cbaed940aa9dffb1b66c08a1
Author: Jaeyun Kim <[email protected]>
AuthorDate: Wed Aug 27 10:41:02 2025 -0700

    chore: change jwt token expiration as a configurable variable (#3693)
    
    ### Summary
    In effort to make jwt token's expiration time configurable, we added the
    expiration time in minutes to `auth.conf` so that users can change the
    token's expiration time easily.
    
    Variables that were related to expiration time (ex:
    `TOKEN_EXPIRE_TIME_IN_MINUTES`) are now assigned to the value that is
    read from `auth.conf`. To make sure `auth.service.ts` also uses the
    value from `auth.conf`, a new attribute is added to `GuiConfig` as
    `expirationTimeInMinutes`. After discussion with @aicam and
    @aglinxinyuan, we decided not to add a separate config interface for
    `auth.conf` since in near future all the configs will be combined into
    one interface.
    
    ---------
    
    Co-authored-by: ali risheh <[email protected]>
    Co-authored-by: Xinyuan Lin <[email protected]>
---
 .../auth/src/main/scala/edu/uci/ics/texera/auth/JwtAuth.scala |  2 +-
 .../edu/uci/ics/texera/service/resource/ConfigResource.scala  |  6 ++++--
 core/config/src/main/resources/auth.conf                      |  3 +++
 .../src/main/scala/edu/uci/ics/texera/config/AuthConfig.scala |  3 +++
 core/gui/src/app/common/service/gui-config.service.mock.ts    |  1 +
 core/gui/src/app/common/service/user/auth.service.ts          |  3 ++-
 core/gui/src/app/common/type/gui-config.ts                    |  1 +
 .../dashboard/component/admin/user/admin-user.component.ts    | 11 ++++++-----
 8 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/core/auth/src/main/scala/edu/uci/ics/texera/auth/JwtAuth.scala 
b/core/auth/src/main/scala/edu/uci/ics/texera/auth/JwtAuth.scala
index 7ede2e981a..78bd374eb6 100644
--- a/core/auth/src/main/scala/edu/uci/ics/texera/auth/JwtAuth.scala
+++ b/core/auth/src/main/scala/edu/uci/ics/texera/auth/JwtAuth.scala
@@ -33,7 +33,7 @@ import java.nio.charset.StandardCharsets
 object JwtAuth {
 
   final val TOKEN_SECRET: String = AuthConfig.jwtSecretKey
-  final val TOKEN_EXPIRE_TIME_IN_MINUTES: Int = 15
+  final val TOKEN_EXPIRE_TIME_IN_MINUTES: Int = AuthConfig.jwtExpirationMinutes
 
   val jwtConsumer: JwtConsumer = new JwtConsumerBuilder()
     .setAllowedClockSkewInSeconds(30)
diff --git 
a/core/config-service/src/main/scala/edu/uci/ics/texera/service/resource/ConfigResource.scala
 
b/core/config-service/src/main/scala/edu/uci/ics/texera/service/resource/ConfigResource.scala
index 23880f3c08..bdd560a4f6 100644
--- 
a/core/config-service/src/main/scala/edu/uci/ics/texera/service/resource/ConfigResource.scala
+++ 
b/core/config-service/src/main/scala/edu/uci/ics/texera/service/resource/ConfigResource.scala
@@ -19,7 +19,7 @@
 
 package edu.uci.ics.texera.service.resource
 
-import edu.uci.ics.texera.config.{ComputingUnitConfig, GuiConfig, 
UserSystemConfig}
+import edu.uci.ics.texera.config.{ComputingUnitConfig, GuiConfig, 
UserSystemConfig, AuthConfig}
 import jakarta.annotation.security.RolesAllowed
 import jakarta.ws.rs.{GET, Path, Produces}
 import jakarta.ws.rs.core.MediaType
@@ -53,7 +53,9 @@ class ConfigResource {
       "defaultLocalUser" -> Map(
         "username" -> GuiConfig.guiLoginDefaultLocalUserUsername,
         "password" -> GuiConfig.guiLoginDefaultLocalUserPassword
-      )
+      ),
+      // flags from the auth.conf if needed
+      "expirationTimeInMinutes" -> AuthConfig.jwtExpirationMinutes
     )
 
   @GET
diff --git a/core/config/src/main/resources/auth.conf 
b/core/config/src/main/resources/auth.conf
index ecc6ba71cc..ecff350c65 100644
--- a/core/config/src/main/resources/auth.conf
+++ b/core/config/src/main/resources/auth.conf
@@ -19,6 +19,9 @@
 # Configuration for JWT Authentication. Currently it is used by the 
FileService to parse the given JWT Token
 auth {
     jwt {
+        expiration-in-minutes = 15
+        expiration-in-minutes = ${?AUTH_JWT_EXPIRATION_IN_MINUTES}
+
         256-bit-secret = "8a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d"
         256-bit-secret = ${?AUTH_JWT_SECRET}
     }
diff --git 
a/core/config/src/main/scala/edu/uci/ics/texera/config/AuthConfig.scala 
b/core/config/src/main/scala/edu/uci/ics/texera/config/AuthConfig.scala
index 53bbe4becd..559938e51d 100644
--- a/core/config/src/main/scala/edu/uci/ics/texera/config/AuthConfig.scala
+++ b/core/config/src/main/scala/edu/uci/ics/texera/config/AuthConfig.scala
@@ -26,6 +26,9 @@ object AuthConfig {
   // Load configuration
   private val conf: Config = 
ConfigFactory.parseResources("auth.conf").resolve()
 
+  // Read jwt Expiration time in minutes
+  final val jwtExpirationMinutes: Int = 
conf.getInt("auth.jwt.expiration-in-minutes")
+
   // For storing the generated/configured secret
   @volatile private var secretKey: String = _
 
diff --git a/core/gui/src/app/common/service/gui-config.service.mock.ts 
b/core/gui/src/app/common/service/gui-config.service.mock.ts
index 60f7e7413c..2012505ef5 100644
--- a/core/gui/src/app/common/service/gui-config.service.mock.ts
+++ b/core/gui/src/app/common/service/gui-config.service.mock.ts
@@ -47,6 +47,7 @@ export class MockGuiConfigService {
     sharingComputingUnitEnabled: false,
     operatorConsoleMessageBufferSize: 1000,
     defaultLocalUser: { username: "", password: "" },
+    expirationTimeInMinutes: 15,
   };
 
   get env(): GuiConfig {
diff --git a/core/gui/src/app/common/service/user/auth.service.ts 
b/core/gui/src/app/common/service/user/auth.service.ts
index b58d2bde27..cf26c51eb1 100644
--- a/core/gui/src/app/common/service/user/auth.service.ts
+++ b/core/gui/src/app/common/service/user/auth.service.ts
@@ -31,7 +31,6 @@ import { GuiConfigService } from "../gui-config.service";
 import { NzModalService } from "ng-zorro-antd/modal";
 
 export const TOKEN_KEY = "access_token";
-export const TOKEN_REFRESH_INTERVAL_IN_MIN = 16;
 
 /**
  * User Service contains the function of registering and logging the user.
@@ -171,6 +170,8 @@ export class AuthService {
 
   private registerAutoRefreshToken() {
     this.refreshTokenSubscription?.unsubscribe();
+    const TOKEN_REFRESH_INTERVAL_IN_MIN = 
this.config.env.expirationTimeInMinutes + 1;
+    // Token Refresh Interval set to Token Expiration Time + 1
     this.refreshTokenSubscription = interval(TOKEN_REFRESH_INTERVAL_IN_MIN * 
60 * 1000)
       .pipe(startWith(0)) // to trigger immediately for the first time.
       .subscribe(() => {
diff --git a/core/gui/src/app/common/type/gui-config.ts 
b/core/gui/src/app/common/type/gui-config.ts
index d60ba1cf01..8598693ac3 100644
--- a/core/gui/src/app/common/type/gui-config.ts
+++ b/core/gui/src/app/common/type/gui-config.ts
@@ -38,6 +38,7 @@ export interface GuiConfig {
   sharingComputingUnitEnabled: boolean;
   operatorConsoleMessageBufferSize: number;
   defaultLocalUser?: { username?: string; password?: string };
+  expirationTimeInMinutes: number;
 }
 
 export interface SidebarTabs {
diff --git 
a/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts 
b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts
index 7aa1b93c5b..d9a1577406 100644
--- a/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts
+++ b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts
@@ -26,6 +26,7 @@ import { AdminUserService } from 
"../../../service/admin/user/admin-user.service
 import { Role, User } from "../../../../common/type/user";
 import { UserService } from "../../../../common/service/user/user.service";
 import { UserQuotaComponent } from 
"../../user/user-quota/user-quota.component";
+import { GuiConfigService } from 
"../../../../common/service/gui-config.service";
 
 @UntilDestroy()
 @Component({
@@ -57,7 +58,8 @@ export class AdminUserComponent implements OnInit {
     private adminUserService: AdminUserService,
     private userService: UserService,
     private modalService: NzModalService,
-    private messageService: NzMessageService
+    private messageService: NzMessageService,
+    private config: GuiConfigService
   ) {
     this.currentUid = this.userService.getCurrentUser()?.uid;
   }
@@ -184,15 +186,14 @@ export class AdminUserComponent implements OnInit {
     });
   }
 
-  private static readonly ACTIVE_WINDOW = 15 * 60 * 1000;
-
   isUserActive(user: User): boolean {
     if (!user.lastLogin) {
       return false;
     }
-
+    // Active window set to expiration-in-minutes from auth.conf
+    const active_window = this.config.env.expirationTimeInMinutes * 60 * 1000;
     const lastMs = user.lastLogin * 1000;
-    return Date.now() - lastMs < AdminUserComponent.ACTIVE_WINDOW;
+    return Date.now() - lastMs < active_window;
   }
 
   public filterByRole: NzTableFilterFn<User> = (list: string[], user: User) =>

Reply via email to