This is an automated email from the ASF dual-hosted git repository.
jleroux pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-plugins.git
The following commit(s) were added to refs/heads/trunk by this push:
new 0746465bc Authentication refresh token mechanism feature -
plugins-update (OFBIZ-13212) (PR-135)
0746465bc is described below
commit 0746465bcf4d8bd9ef9188bd0ed61d10b098fc73
Author: ArashPreet <[email protected]>
AuthorDate: Thu Apr 10 19:19:23 2025 +0530
Authentication refresh token mechanism feature - plugins-update
(OFBIZ-13212) (PR-135)
- Modified plugins/rest-api to support refresh token.
- Get refresh token while login.
- Get access token by providing refresh token.
* Documentation updated for refresh token mechanism.
---------
Co-authored-by: ArashPreet Singh <[email protected]>
---
rest-api/src/docs/asciidoc/rest-api.adoc | 51 ++++++++++++++++++++++
.../ws/rs/resources/AuthenticationResource.java | 42 +++++++++++++++++-
2 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/rest-api/src/docs/asciidoc/rest-api.adoc
b/rest-api/src/docs/asciidoc/rest-api.adoc
index 98fc07c2c..941bf89b1 100644
--- a/rest-api/src/docs/asciidoc/rest-api.adoc
+++ b/rest-api/src/docs/asciidoc/rest-api.adoc
@@ -155,3 +155,54 @@ Response +
}
}
----
+
+== Refresh Token Mechanism
+
+The authentication system now supports a refresh token mechanism. This allows
clients to obtain a new `access_token` using a previously issued
`refresh_token`.
+
+=== Login API Enhancement
+
+Upon successful login, the response includes both `access_token` and
`refresh_token`.
+
+.Response Example
+[source,json]
+----
+{
+ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
+ "refresh_token": "dGhpc19pc19hX3JlZnJlc2hfdG9rZW4..."
+}
+----
+
+=== Get Access Token Using Refresh Token
+
+A new endpoint has been introduced to obtain a new `access_token` using a
valid `refresh_token`.
+
+*URL:* `POST https://localhost:8443/rest/auth/refresh-token`
+
+==== Request
+
+The request should contain the `refresh_token` in the body.
+
+.Request Example
+[source,json]
+----
+{
+ "Refresh-Token": "dGhpc19pc19hX3JlZnJlc2hfdG9rZW4..."
+}
+----
+
+==== Response
+
+If the refresh token is valid, a new `access_token` is returned.
+
+.Response Example
+[source,json]
+----
+{
+ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
+}
+----
+
+==== Errors
+
+- `401 Unauthorized`: If the provided refresh token is missing, expired, or
invalid.
\ No newline at end of file
diff --git
a/rest-api/src/main/java/org/apache/ofbiz/ws/rs/resources/AuthenticationResource.java
b/rest-api/src/main/java/org/apache/ofbiz/ws/rs/resources/AuthenticationResource.java
index 8a7948396..623d7339d 100644
---
a/rest-api/src/main/java/org/apache/ofbiz/ws/rs/resources/AuthenticationResource.java
+++
b/rest-api/src/main/java/org/apache/ofbiz/ws/rs/resources/AuthenticationResource.java
@@ -73,9 +73,47 @@ public class AuthenticationResource extends OFBizResource {
GenericValue userLogin = (GenericValue)
httpRequest.getAttribute("userLogin");
//TODO : Move this into an OFBiz service. All such implementations
should be inside an OFBiz service.
String jwtToken = JWTManager.createJwt(getDelegator(),
UtilMisc.toMap("userLoginId", userLogin.getString("userLoginId")));
- Map<String, Object> tokenPayload = UtilMisc.toMap("access_token",
jwtToken, "expires_in",
- EntityUtilProperties.getPropertyValue("security",
"security.jwt.token.expireTime", "1800", getDelegator()), "token_type",
"Bearer");
+ String refreshToken = JWTManager.createRefreshToken(getDelegator(),
userLogin.getString("userLoginId"));
+
+ Map<String, Object> tokenPayload = UtilMisc.toMap("access_token",
jwtToken, "refresh_token", refreshToken,
+ "expires_in",
EntityUtilProperties.getPropertyValue("security",
"security.jwt.token.expireTime", "1800", getDelegator()),
+ "token_type", "Bearer");
return RestApiUtil.success("Token granted.", tokenPayload);
}
+ /**
+ * Generates a new access token using a refresh token.
+ * <p>
+ * Subclasses overriding this method should ensure they call the parent
implementation
+ * or handle JWT validation and token generation securely.
+ * </p>
+ *
+ * @param refreshToken The refresh token provided in the request header.
+ * @return A response containing the new access and refresh tokens.
+ ]*/
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/refresh-token")
+ @Operation(description = "Generates a new access token using a refresh
token.")
+ public Response refreshToken(@HeaderParam("Refresh-Token") String
refreshToken) {
+
+ httpRequest.setAttribute("delegator", getDelegator());
+ httpRequest.setAttribute("dispatcher", getDispatcher());
+ Map<String, Object> claims =
JWTManager.validateRefreshToken(refreshToken,
JWTManager.getJWTKey(getDelegator()));
+
+ // Fetch delegator, dispatcher, and userLogin
+ if (claims.containsKey("errorMessage")) {
+ System.out.println("Error with JWT token: ");
+ }
+
+ String userLoginId = (String) claims.get("userLoginId");
+
+ String newAccessToken = JWTManager.createJwt(getDelegator(),
UtilMisc.toMap("userLoginId", userLoginId));
+ String newRefreshToken = JWTManager.createRefreshToken(getDelegator(),
userLoginId);
+
+ Map<String, Object> tokenPayload = UtilMisc.toMap("access_token",
newAccessToken, "refresh_token", newRefreshToken, "expires_in",
+ EntityUtilProperties.getPropertyValue("security",
"security.jwt.token.expireTime", "1800", getDelegator()), "token_type",
"Bearer");
+
+ return RestApiUtil.success("Token refreshed.", tokenPayload);
+ }
}