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) =>