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);
+    }
 }

Reply via email to