diff --git a/changelog.md b/changelog.md
index 375a3af0..365536a0 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## v1.10.0
+
+### Oct 27, 2025
+
+- Feature : TOTP support
+
 ## v1.9.0
 
 ### Oct 13, 2025
@@ -8,7 +14,7 @@
 
 ## v1.8.0
 
-### Sep 15, 2025
+### Sep 29, 2025
 
 - Feature : OAuth 2.0 support with PKCE flow
 - Improved code organization and removed redundant methods
diff --git a/pom.xml b/pom.xml
index 0b0ceaee..11e2b793 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
     cms
     jar
     contentstack-management-java
-    1.9.0
+    1.10.0
     Contentstack Java Management SDK for Content Management API, Contentstack is a headless CMS with an
         API-first approach
     
@@ -214,6 +214,11 @@
             kotlin-stdlib
             2.1.21
         
+         
+            com.warrenstrange
+            googleauth
+            1.5.0
+        
     
 
 
diff --git a/src/main/java/com/contentstack/cms/Contentstack.java b/src/main/java/com/contentstack/cms/Contentstack.java
index dbf3dbc0..1f01dbcb 100644
--- a/src/main/java/com/contentstack/cms/Contentstack.java
+++ b/src/main/java/com/contentstack/cms/Contentstack.java
@@ -27,6 +27,7 @@
 import com.contentstack.cms.stack.Stack;
 import com.contentstack.cms.user.User;
 import com.google.gson.Gson;
+import com.warrenstrange.googleauth.GoogleAuthenticator;
 
 import okhttp3.ConnectionPool;
 import okhttp3.OkHttpClient;
@@ -40,9 +41,8 @@
  * Contentstack Java Management SDK
  * 
  * Java Management SDK Interact with the Content Management APIs and
- * allow you to create, update,
- * delete, and fetch content from your Contentstack account. (They are
- * read-write in nature.)
+ * allow you to create, update, delete, and fetch content from your Contentstack
+ * account. (They are read-write in nature.)
  * 
  * You can use them to build your own apps and manage your content from
  * Contentstack.
@@ -66,8 +66,7 @@ public class Contentstack {
 
     /**
      * All accounts registered with Contentstack are known as Users. A stack can
-     * have many users with varying
-     * permissions and roles
+     * have many users with varying permissions and roles
      * 
      * To perform User operations first get User instance like below.
      * 
@@ -89,7 +88,8 @@ public class Contentstack {
      * 
      *
      * @return User
-     * @author ***REMOVED***
+     * @author ***REMOVED
+     ***
      * @see User
      * 
@@ -105,15 +105,14 @@ public User user() {
 
     /**
      * [Note]: Before executing any calls, retrieve the authtoken by
-     * authenticating yourself via the Log in call of User Session. The authtoken is
-     * returned to the 'Response' body of
-     * the Log in call and is mandatory in all the calls.
+     * authenticating yourself via the Log in call of User Session. The
+     * authtoken is returned to the 'Response' body of the Log in call and is
+     * mandatory in all the calls.
      * 
      * Example:
      * 
      * All accounts registered with Contentstack are known as Users. A stack can
-     * have many users with varying
-     * permissions and roles
+     * have many users with varying permissions and roles
      * 
      * To perform User operations first get User instance like below.
      * 
@@ -136,18 +135,20 @@ public User user() {
      *
      * 
      *
-     * @param emailId  the email id of the user
+     * @param emailId the email id of the user
      * @param password the password of the user
      * @return LoginDetails
      * @throws IOException the IOException
-     * @author ***REMOVED***
+     * @author ***REMOVED
+     ***
      * @see User
      * 
      */
     public Response login(String emailId, String password) throws IOException {
-        if (this.authtoken != null)
+        if (this.authtoken != null) {
             throw new IllegalStateException(Util.USER_ALREADY_LOGGED_IN);
+        }
         user = new User(this.instance);
         Response response = user.login(emailId, password).execute();
         setupLoginCredentials(response);
@@ -155,61 +156,58 @@ public Response login(String emailId, String password) throws IOEx
     }
 
     /**
-     * [Note]: Before executing any calls, retrieve the authtoken by
-     * authenticating yourself via the Log in call of User Session. The authtoken is
-     * returned to the 'Response' body of
-     * the Log in call and is mandatory in all the calls.
-     * 
-     * Example:
-     * 
-     * All accounts registered with Contentstack are known as Users. A stack can
-     * have many users with varying
-     * permissions and roles
-     * 
-     * To perform User operations first get User instance like below.
-     * 
-     * Example:
-     *
+     * Login with two-factor authentication. This method provides flexibility to use either:
+     * 1. A direct 2FA token using params.put("tfaToken", "123456"), OR
+     * 2. An MFA secret to generate TOTP using params.put("mfaSecret", "YOUR_SECRET")
+     * 
+     * Note: Do not provide both tfaToken and mfaSecret. Choose one authentication method.
+     *
+     * @param emailId    The email ID of the user
+     * @param password   The user's password
+     * @param params     Map containing either tfaToken or mfaSecret
+     * @return Response containing login details
+     * @throws IOException if there's a network error
+     * @throws IllegalArgumentException if validation fails or if both tfaToken and mfaSecret are provided
+     * @throws IllegalStateException if user is already logged in
+     * 
+     * Example:
      * 
-     * Contentstack contentstack = new Contentstack.Builder().setAuthtoken("authtoken").build();
-     * Response login = contentstack.login();
-     *
-     * Access more other user functions from the userInstance
+     * // Login with direct token
+     * {@code Map params = new HashMap<>();}
+     * {@code params.put("tfaToken", "123456");}
+     * {@code Response response = contentstack.login(email, password, params);}
+     * 
+     * // OR login with MFA secret
+     * {@code Map params = new HashMap<>();}
+     * {@code params.put("mfaSecret", "YOUR_SECRET");}
+     * {@code Response response = contentstack.login(email, password, params);}
      * 
-     *
-     * 
-     * OR: 
-     *
-     * 
-     * Contentstack contentstack = new Contentstack.Builder().build();
-     * Response login = contentstack.login("emailId", "password");
-     * 
-     *
-     * 
-     *
-     * @param emailId  the email id
-     * @param password the password
-     * @param tfaToken the tfa token
-     * @return LoginDetails
-     * @throws IOException the io exception
-     * @throws IOException the IOException
-     * @author ***REMOVED***
-     * @see Login
-     * your account
-     * 
      */
-    public Response login(String emailId, String password, String tfaToken) throws IOException {
-        if (this.authtoken != null)
+    public Response login(String emailId, String password, Map params) throws IOException {
+        // Check if already logged in
+        if (this.authtoken != null) {
             throw new IllegalStateException(Util.USER_ALREADY_LOGGED_IN);
+        }
+
+        // Validate basic inputs
+        if (emailId.trim().isEmpty()) {
+            throw new IllegalArgumentException("Email is required");
+        }
+        if (password.trim().isEmpty()) {
+            throw new IllegalArgumentException("Password is required");
+        }
+        if (params.isEmpty()) {
+            throw new IllegalArgumentException("Authentication parameters are required");
+        }
+
+        // Perform login
         user = new User(this.instance);
-        Response response = user.login(emailId, password, tfaToken).execute();
+        Response response = user.login(emailId, password, params).execute();
         setupLoginCredentials(response);
-        user = new User(this.instance);
         return response;
     }
 
+
     private void setupLoginCredentials(Response loginResponse) throws IOException {
         if (loginResponse.isSuccessful()) {
             LoginDetails loginDetails = loginResponse.body();
@@ -230,8 +228,8 @@ private void setupLoginCredentials(Response loginResponse) throws
     }
 
     /**
-     * The Log out of your account call is used to sign out the user of Contentstack
-     * account
+     * The Log out of your account call is used to sign out the user of
+     * Contentstack account
      * 
      *  Example 
      *
@@ -250,8 +248,8 @@ Response logout() throws IOException {
     }
 
     /**
-     * The Log out of your account using authtoken is used to sign out the user of
-     * Contentstack account
+     * The Log out of your account using authtoken is used to sign out the user
+     * of Contentstack account
      * 
      *  Example 
      *
@@ -276,9 +274,8 @@ Response logoutWithAuthtoken(String authtoken) throws IOException
 
     /**
      * Organization is the top-level entity in the hierarchy of Contentstack,
-     * consisting of stacks and stack resources,
-     * and users. Organization allows easy management of projects as well as users
-     * within the Organization.
+     * consisting of stacks and stack resources, and users. Organization allows
+     * easy management of projects as well as users within the Organization.
      * 
      *  Example 
      *
@@ -293,7 +290,7 @@ public Organization organization() {
         if (!isOAuthConfigured() && this.authtoken == null) {
             throw new IllegalStateException(Util.OAUTH_LOGIN_REQUIRED + " organization");
         }
-        
+
         // If using OAuth, get organization from tokens
         if (isOAuthConfigured() && oauthHandler.getTokens() != null) {
             String orgUid = oauthHandler.getTokens().getOrganizationUid();
@@ -301,19 +298,19 @@ public Organization organization() {
                 return organization(orgUid);
             }
         }
-        
+
         return new Organization(this.instance);
     }
 
     /**
      * Organization is the top-level entity in the hierarchy of Contentstack,
-     * consisting of stacks and stack resources,
-     * and users. Organization allows easy management of projects as well as users
-     * within the Organization.
+     * consisting of stacks and stack resources, and users. Organization allows
+     * easy management of projects as well as users within the Organization.
      * 
      *  Example 
      *
-     * @param organizationUid The UID of the organization that you want to retrieve
+     * @param organizationUid The UID of the organization that you want to
+     * retrieve
      * @return the organization
      * 
      * Example
@@ -322,7 +319,7 @@ public Organization organization() {
      *         Contentstack contentstack = new Contentstack.Builder().build();
      *         
      *         Organization org = contentstack.organization();
-     *         
+     * 
      */
     public Organization organization(@NotNull String organizationUid) {
         if (!isOAuthConfigured() && this.authtoken == null) {
@@ -337,10 +334,9 @@ public Organization organization(@NotNull String organizationUid) {
     /**
      * stack
-     * A stack is
-     * a space that stores the content of a project (a web or mobile property).
-     * Within a stack, you can create content
-     * structures, content entries, users, etc. related to the project
+     * A stack is a space that stores the content of a project (a web or mobile
+     * property). Within a stack, you can create content structures, content
+     * entries, users, etc. related to the project
      * 
      *  Example 
      *
@@ -361,10 +357,9 @@ public Stack stack() {
     /**
      * stack
-     * A stack is
-     * a space that stores the content of a project (a web or mobile property).
-     * Within a stack, you can create content
-     * structures, content entries, users, etc. related to the project
+     * A stack is a space that stores the content of a project (a web or mobile
+     * property). Within a stack, you can create content structures, content
+     * entries, users, etc. related to the project
      * 
      *  Example 
      *
@@ -386,10 +381,9 @@ public Stack stack(@NotNull Map header) {
     /**
      * stack
-     * A stack is
-     * a space that stores the content of a project (a web or mobile property).
-     * Within a stack, you can create content
-     * structures, content entries, users, etc. related to the project
+     * A stack is a space that stores the content of a project (a web or mobile
+     * property). Within a stack, you can create content structures, content
+     * entries, users, etc. related to the project
      * 
      *  Example 
      *
@@ -399,7 +393,7 @@ public Stack stack(@NotNull Map header) {
      * 
      *
      * @param managementToken the authorization for the stack
-     * @param apiKey          the apiKey for the stack
+     * @param apiKey the apiKey for the stack
      * @return the stack instance
      */
     public Stack stack(@NotNull String apiKey, @NotNull String managementToken) {
@@ -412,10 +406,9 @@ public Stack stack(@NotNull String apiKey, @NotNull String managementToken) {
     /**
      * stack
-     * A stack is
-     * a space that stores the content of a project (a web or mobile property).
-     * Within a stack, you can create content
-     * structures, content entries, users, etc. related to the project
+     * A stack is a space that stores the content of a project (a web or mobile
+     * property). Within a stack, you can create content structures, content
+     * entries, users, etc. related to the project
      * 
      *  Example 
      *
@@ -442,10 +435,9 @@ public Stack stack(@NotNull String key) {
     /**
      * stack
-     * A stack is
-     * a space that stores the content of a project (a web or mobile property).
-     * Within a stack, you can create content
-     * structures, content entries, users, etc. related to the project
+     * A stack is a space that stores the content of a project (a web or mobile
+     * property). Within a stack, you can create content structures, content
+     * entries, users, etc. related to the project
      * 
      *  Example 
      *
@@ -455,8 +447,8 @@ public Stack stack(@NotNull String key) {
      * 
      *
      * @param managementToken the authorization for the stack
-     * @param apiKey          the apiKey for the stack
-     * @param branch          the branch that include branching in the response
+     * @param apiKey the apiKey for the stack
+     * @param branch the branch that include branching in the response
      * @return the stack instance
      */
     public Stack stack(@NotNull String apiKey, @NotNull String managementToken, @NotNull String branch) {
@@ -469,6 +461,7 @@ public Stack stack(@NotNull String apiKey, @NotNull String managementToken, @Not
 
     /**
      * Get the OAuth authorization URL for the user to visit
+     *
      * @return Authorization URL string
      * @throws IllegalStateException if OAuth is not configured
      */
@@ -481,6 +474,7 @@ public String getOAuthAuthorizationUrl() {
 
     /**
      * Exchange OAuth authorization code for tokens
+     *
      * @param code Authorization code from OAuth callback
      * @return CompletableFuture containing OAuth tokens
      * @throws IllegalStateException if OAuth is not configured
@@ -494,8 +488,10 @@ public CompletableFuture exchangeOAuthCode(String code) {
 
     /**
      * Refresh the OAuth access token
+     *
      * @return CompletableFuture containing new OAuth tokens
-     * @throws IllegalStateException if OAuth is not configured or no refresh token available
+     * @throws IllegalStateException if OAuth is not configured or no refresh
+     * token available
      */
     public CompletableFuture refreshOAuthToken() {
         if (!isOAuthConfigured()) {
@@ -506,6 +502,7 @@ public CompletableFuture refreshOAuthToken() {
 
     /**
      * Get the current OAuth tokens
+     *
      * @return Current OAuth tokens or null if not available
      */
     public OAuthTokens getOAuthTokens() {
@@ -514,6 +511,7 @@ public OAuthTokens getOAuthTokens() {
 
     /**
      * Check if we have valid OAuth tokens
+     *
      * @return true if we have valid tokens
      */
     public boolean hasValidOAuthTokens() {
@@ -522,6 +520,7 @@ public boolean hasValidOAuthTokens() {
 
     /**
      * Check if OAuth is configured
+     *
      * @return true if OAuth is configured
      */
     public boolean isOAuthConfigured() {
@@ -530,6 +529,7 @@ public boolean isOAuthConfigured() {
 
     /**
      * Get the OAuth handler instance
+     *
      * @return OAuth handler or null if not configured
      */
     public OAuthHandler getOAuthHandler() {
@@ -538,6 +538,7 @@ public OAuthHandler getOAuthHandler() {
 
     /**
      * Logout from OAuth session and optionally revoke authorization
+     *
      * @param revokeAuthorization If true, revokes the OAuth authorization
      * @return CompletableFuture that completes when logout is done
      */
@@ -550,6 +551,7 @@ public CompletableFuture oauthLogout(boolean revokeAuthorization) {
 
     /**
      * Logout from OAuth session without revoking authorization
+     *
      * @return CompletableFuture that completes when logout is done
      */
     public CompletableFuture oauthLogout() {
@@ -595,8 +597,8 @@ public static class Builder {
         private Boolean retry = Util.RETRY_ON_FAILURE;// Default base url for contentstack
 
         /**
-         * Default ConnectionPool holds up to 5 idle connections which
-         * will be evicted after 5 minutes of inactivity.
+         * Default ConnectionPool holds up to 5 idle connections which will be
+         * evicted after 5 minutes of inactivity.
          */
         private ConnectionPool connectionPool = new ConnectionPool(); // Connection
 
@@ -609,8 +611,7 @@ public Builder() {
 
         /**
          * Sets proxy. (Setting proxy to the OkHttpClient) Proxy = new
-         * Proxy(Proxy.Type.HTTP, new
-         * InetSocketAddress(proxyHost, proxyPort));
+         * Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
          * 
          * 
          * {@code
@@ -687,26 +688,20 @@ public Builder setTimeout(int timeout) {
 
         /**
          * Create a new connection pool with tuning parameters appropriate for a
-         * single-user application.
-         * The tuning parameters in this pool are subject to change in future OkHttp
-         * releases. Currently,
-         * this pool holds up to 5 idle connections which will be evicted after 5
-         * minutes of inactivity.
+         * single-user application. The tuning parameters in this pool are
+         * subject to change in future OkHttp releases. Currently, this pool
+         * holds up to 5 idle connections which will be evicted after 5 minutes
+         * of inactivity
          * 
-         * 
-         * public ConnectionPool() {
-         * this(5, 5, TimeUnit.MINUTES);
-         * }
+         * public ConnectionPool() { this(5, 5, TimeUnit.MINUTES); }
          *
          * @param maxIdleConnections Maximum number of idle connections
-         * @param keepAliveDuration  The Keep Alive Duration
-         * @param timeUnit           A TimeUnit represents time durations at a given
-         *                           unit of granularity and provides utility methods to
-         *                           convert across units
+         * @param keepAliveDuration The Keep Alive Duration
+         * @param timeUnit A TimeUnit represents time durations at a given unit
+         * of granularity and provides utility methods to convert across units
          * @return instance of Builder
          * 
-         * Example:
-         * {@code
+         * Example:          {@code
          * Contentstack cs = new Contentstack.Builder()
          * .setAuthtoken(AUTHTOKEN)
          * .setConnectionPool(5, 400, TimeUnit.MILLISECONDS)
@@ -732,6 +727,7 @@ public Builder setAuthtoken(String authtoken) {
 
         /**
          * Sets OAuth configuration for the client
+         *
          * @param config OAuth configuration
          * @return Builder instance
          */
@@ -744,6 +740,7 @@ public Builder setOAuthConfig(OAuthConfig config) {
 
         /**
          * Sets the token callback for OAuth storage
+         *
          * @param callback The callback to handle token storage
          * @return Builder instance
          */
@@ -751,7 +748,7 @@ public Builder setTokenCallback(TokenCallback callback) {
             this.tokenCallback = callback;
             return this;
         }
-
+      
         /**
          * Configures OAuth authentication with PKCE flow (no client secret)
          * @param appId Application ID
@@ -787,10 +784,10 @@ public Builder setOAuth(String appId, String clientId, String redirectUri, Strin
          */
         public Builder setOAuth(String appId, String clientId, String redirectUri, String host, String clientSecret) {
             OAuthConfig.OAuthConfigBuilder builder = OAuthConfig.builder()
-                .appId(appId)
-                .clientId(clientId)
-                .redirectUri(redirectUri)
-                .host(host);
+                    .appId(appId)
+                    .clientId(clientId)
+                    .redirectUri(redirectUri)
+                    .host(host);
 
             // Only set clientSecret if provided (otherwise PKCE flow will be used)
             if (clientSecret != null && !clientSecret.trim().isEmpty()) {
@@ -828,7 +825,7 @@ private void validateClient(Contentstack contentstack) {
                     .addConverterFactory(GsonConverterFactory.create())
                     .client(httpClient(contentstack, this.retry)).build();
             contentstack.instance = this.instance;
-            
+
             // Initialize OAuth if configured
             if (this.oauthConfig != null) {
                 // OAuth handler and interceptor are created in httpClient
@@ -851,12 +848,12 @@ private OkHttpClient httpClient(Contentstack contentstack, Boolean retryOnFailur
                 OkHttpClient tempClient = builder.build();
                 this.oauthHandler = new OAuthHandler(tempClient, this.oauthConfig);
                 this.oauthInterceptor = new OAuthInterceptor(this.oauthHandler);
-                
+
                 // Configure early access if needed
                 if (this.earlyAccess != null) {
                     this.oauthInterceptor.setEarlyAccess(this.earlyAccess);
                 }
-                
+
                 // Add interceptor to handle OAuth, token refresh, and retries
                 builder.addInterceptor(this.oauthInterceptor);
             } else {
diff --git a/src/main/java/com/contentstack/cms/user/User.java b/src/main/java/com/contentstack/cms/user/User.java
index 53b05b8f..fb549976 100644
--- a/src/main/java/com/contentstack/cms/user/User.java
+++ b/src/main/java/com/contentstack/cms/user/User.java
@@ -8,26 +8,24 @@
 import org.json.simple.JSONObject;
 import retrofit2.Call;
 import retrofit2.Retrofit;
+import com.warrenstrange.googleauth.GoogleAuthenticator;
 
 import java.util.HashMap;
+import java.util.Map;
 
 /**
- * All accounts registered with Contentstack are known as Users.
- * A Stack
- * can have many users with varying
- * permissions and roles.
+ * All accounts registered with Contentstack are known as Users.
+ * A stack can have many users with varying permissions and roles.
  *
  * @author ***REMOVED***
  * @version v0.1.0
  * @since 2022-10-22
  */
-public class User implements BaseImplementation {
+public class User implements BaseImplementation {
 
     protected final UserService userService;
-    protected HashMap headers;
-    protected HashMap params;
+    protected final HashMap headers;
+    protected final HashMap params;
 
     /**
      * @param client Retrofit adapts a Java interface to HTTP calls by using
@@ -66,8 +64,13 @@ public User(Retrofit client) {
      * @return Call
      */
     public Call login(@NotNull String email, @NotNull String password) {
+        HashMap credentials = new HashMap<>();
+        credentials.put("email", email);
+        credentials.put("password", password);
+
         HashMap> userSession = new HashMap<>();
-        userSession.put("user", setCredentials(email, password));
+        userSession.put("user", credentials);
+        
         JSONObject userDetail = new JSONObject(userSession);
         return this.userService.login(loginHeader(), userDetail);
     }
@@ -79,28 +82,96 @@ private HashMap loginHeader() {
     }
 
     /**
-     * Login call.
+     * Login with two-factor authentication. This method provides flexibility to use either:
+     * 1. A direct 2FA token using params.put("tfaToken", "123456"), OR
+     * 2. An MFA secret to generate TOTP using params.put("mfaSecret", "YOUR_SECRET")
+     * 
+     * Note: Do not provide both tfaToken and mfaSecret. Choose one authentication method.
      *
-     * @param email    email for user to login
-     * @param password password for user to login
-     * @param tfaToken the tfa token
-     * @return Call
+     * @param email     email for user to login
+     * @param password  password for user to login
+     * @param params    Map containing either tfaToken or mfaSecret
+     * @return Call containing login details
+     * @throws IllegalArgumentException if validation fails or if both tfaToken and mfaSecret are provided
+     * 
+     * Example:
+     * 
+     * // Login with direct token
+     * {@code Map params = new HashMap<>();}
+     * {@code params.put("tfaToken", "123456");}
+     * {@code Call call = user.login(email, password, params);}
+     * 
+     * // OR login with MFA secret
+     * {@code Map params = new HashMap<>();}
+     * {@code params.put("mfaSecret", "YOUR_SECRET");}
+     * {@code Call call = user.login(email, password, params);}
+     * 
      */
-    public Call login(@NotNull String email, @NotNull String password, @NotNull String tfaToken) {
+    public Call login(@NotNull String email, @NotNull String password, @NotNull Map params) {
+        // Validate basic inputs
+        if (email.trim().isEmpty()) {
+            throw new IllegalArgumentException("Email is required");
+        }
+        if (password.trim().isEmpty()) {
+            throw new IllegalArgumentException("Password is required");
+        }
+        if (params.isEmpty()) {
+            throw new IllegalArgumentException("Authentication parameters are required");
+        }
+
+        String tfaToken = params.get("tfaToken");
+        String mfaSecret = params.get("mfaSecret");
+        
+        // Check for mutual exclusivity
+        boolean hasTfaToken = tfaToken != null && !tfaToken.trim().isEmpty();
+        boolean hasMfaSecret = mfaSecret != null && !mfaSecret.trim().isEmpty();
+        
+        if (hasTfaToken && hasMfaSecret) {
+            throw new IllegalArgumentException("Cannot provide both tfaToken and mfaSecret. Use either one.");
+        }
+        if (!hasTfaToken && !hasMfaSecret) {
+            throw new IllegalArgumentException("Must provide either tfaToken or mfaSecret");
+        }
+
+        // Generate TOTP if needed
+        String finalTfaToken = tfaToken;
+        if (!hasTfaToken && hasMfaSecret) {
+            finalTfaToken = generateTOTP(mfaSecret);
+        }
+
+        // Perform login
+        HashMap credentials = new HashMap<>();
+        credentials.put("email", email);
+        credentials.put("password", password);
+        credentials.put("tfa_token", finalTfaToken);
+
         HashMap> userSession = new HashMap<>();
-        userSession.put("user", setCredentials(email, password, tfaToken));
+        userSession.put("user", credentials);
+        
         JSONObject userDetail = new JSONObject(userSession);
         return this.userService.login(loginHeader(), userDetail);
     }
 
-    private HashMap setCredentials(@NotNull String... arguments) {
-        HashMap credentials = new HashMap<>();
-        credentials.put("email", arguments[0]);
-        credentials.put("password", arguments[1]);
-        if (arguments.length > 2) {
-            credentials.put("tfa_token", arguments[2]);
+    private String generateTOTP(String secret) {
+        if (secret == null || secret.trim().isEmpty()) {
+            throw new IllegalArgumentException("MFA secret cannot be null or empty");
+        }
+
+        try {
+            GoogleAuthenticator gAuth = new GoogleAuthenticator();
+            String totp = String.format("%06d", gAuth.getTotpPassword(secret));
+
+            // Validate the generated token
+            if (!totp.matches("\\d{6}")) {
+                throw new IllegalArgumentException("Generated TOTP token is invalid (not 6 digits)");
+            }
+
+            return totp;
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Failed to generate TOTP token: " + e.getMessage(), e);
         }
-        return credentials;
     }
 
     /**
@@ -128,8 +199,7 @@ public Call getUser() {
      * @return Call
      */
     public Call update(JSONObject body) {
-        HashMap headers = new HashMap<>();
-        return userService.update(headers, body);
+        return userService.update(new HashMap<>(), body);
     }
 
     /**
diff --git a/src/test/java/com/contentstack/cms/ContentstackAPITest.java b/src/test/java/com/contentstack/cms/ContentstackAPITest.java
index 6f1ca163..61ffba90 100644
--- a/src/test/java/com/contentstack/cms/ContentstackAPITest.java
+++ b/src/test/java/com/contentstack/cms/ContentstackAPITest.java
@@ -9,6 +9,8 @@
 import retrofit2.Response;
 
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
 /*
  @author  ***REMOVED***@gmail.com
@@ -69,8 +71,9 @@ void testContentstackUserLoginWhenAlreadyLoggedIn() throws IOException {
         Contentstack contentstack = new Contentstack.Builder()
                 .setAuthtoken(null)
                 .build();
-        Response response = contentstack.login("invalid@credentials.com", "invalid@password",
-                "invalid_tfa_token");
+        Map params = new HashMap<>();
+        params.put("tfaToken", "invalid_tfa_token");
+        Response response = contentstack.login("invalid@credentials.com", "invalid@password", params);
         Assertions.assertEquals(422, response.code());
     }
 
diff --git a/src/test/java/com/contentstack/cms/ContentstackUnitTest.java b/src/test/java/com/contentstack/cms/ContentstackUnitTest.java
index 6386cf22..8c9e57dc 100644
--- a/src/test/java/com/contentstack/cms/ContentstackUnitTest.java
+++ b/src/test/java/com/contentstack/cms/ContentstackUnitTest.java
@@ -17,6 +17,8 @@
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.Proxy;
+import java.util.HashMap;
+import java.util.Map;
 
 public class ContentstackUnitTest {
 
@@ -210,7 +212,9 @@ void testSetAuthtokenLogin() {
     void testSetAuthtokenLoginWithTfa() {
         Contentstack client = new Contentstack.Builder().setAuthtoken("fake@authtoken").build();
         try {
-            client.login("fake@email.com", "fake@password", "fake@tfa");
+            Map params = new HashMap<>();
+            params.put("tfaToken", "fake@tfa");
+            client.login("fake@email.com", "fake@password", params);
         } catch (Exception e) {
             Assertions.assertEquals("User is already loggedIn, Please logout then try to login again", e.getMessage());
         }
diff --git a/src/test/java/com/contentstack/cms/user/UserUnitTests.java b/src/test/java/com/contentstack/cms/user/UserUnitTests.java
index 685c4bd9..150eea96 100644
--- a/src/test/java/com/contentstack/cms/user/UserUnitTests.java
+++ b/src/test/java/com/contentstack/cms/user/UserUnitTests.java
@@ -10,6 +10,7 @@
 
 import java.net.URL;
 import java.util.HashMap;
+import java.util.Map;
 
 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -587,8 +588,7 @@ void testUserBaseParameters() {
         HashMap headers = new HashMap<>();
         headers.put("header", "something");
         Request requestInfo = userInstance.
-                addParams(headers).
-                addParam("param", "value")
+                addParam("param", (Object)"value")
                 .addHeader("key", "value")
                 .addHeaders(headers)
                 .logoutWithAuthtoken("authtoken")
@@ -596,4 +596,135 @@ void testUserBaseParameters() {
         Assertions.assertEquals(0,
                 requestInfo.url().queryParameterNames().size());
     }
+
+    @Test
+    @Order(42)
+    @DisplayName("Test login with TOTP token")
+    void testLoginWithTOTPToken() {
+        // Test basic login with TOTP token
+        Map params = new HashMap<>();
+        params.put("tfaToken", "123456");
+        Request requestInfo = userInstance.login("test@example.com", "password", params).request();
+        
+        // Verify request format
+        Assertions.assertEquals("POST", requestInfo.method());
+        Assertions.assertEquals("/v3/user-session", requestInfo.url().encodedPath());
+        
+        // Verify request body
+        String requestBody = requestInfo.body() != null ? requestInfo.body().toString() : "";
+        Assertions.assertTrue(requestBody.contains("\"tfa_token\":\"123456\""));
+    }
+
+    @Test
+    @Order(43)
+    @DisplayName("Test login with MFA parameters")
+    void testLoginWithMFAParameters() {
+        // Test login with both token and secret (should throw exception)
+        Map params = new HashMap<>();
+        params.put("tfaToken", "123456");
+        params.put("mfaSecret", "test-secret");
+        
+        IllegalArgumentException exception = Assertions.assertThrows(
+            IllegalArgumentException.class,
+            () -> userInstance.login("test@example.com", "password", params).request()
+        );
+        
+        Assertions.assertTrue(exception.getMessage().contains("Cannot provide both tfaToken and mfaSecret"));
+    }
+
+    @Test
+    @Order(44)
+    @DisplayName("Test login validation")
+    void testLoginValidation() {
+        Map params = new HashMap<>();
+        params.put("tfaToken", "123456");
+        
+        // Test with missing required parameters
+        Assertions.assertThrows(IllegalArgumentException.class, 
+            () -> userInstance.login("", "password", params).request());
+            
+        Assertions.assertThrows(IllegalArgumentException.class, 
+            () -> userInstance.login("test@example.com", "", params).request());
+            
+        Assertions.assertThrows(IllegalArgumentException.class, 
+            () -> userInstance.login("test@example.com", "password", new HashMap<>()).request());
+    }
+
+    @Test
+    @Order(45)
+    @DisplayName("Test TOTP generation from MFA secret")
+    void testTOTPGenerationFromSecret() {
+        // Test login with MFA secret only
+        Map params = new HashMap<>();
+        params.put("mfaSecret", "test-secret");
+        Request requestInfo = userInstance.login("test@example.com", "password", params).request();
+        
+        // Verify request format
+        Assertions.assertEquals("POST", requestInfo.method());
+        Assertions.assertEquals("/v3/user-session", requestInfo.url().encodedPath());
+        
+        // Verify generated TOTP format
+        String requestBody = requestInfo.body() != null ? requestInfo.body().toString() : "";
+        Assertions.assertTrue(requestBody.contains("\"tfa_token\":\""));
+        
+        // Extract TOTP token and verify it's 6 digits
+        String token = requestBody.split("\"tfa_token\":\"")[1].split("\"")[0];
+        Assertions.assertTrue(token.matches("\\d{6}"), "TOTP should be 6 digits");
+    }
+
+    @Test
+    @Order(46)
+    @DisplayName("Test invalid MFA secret handling")
+    void testInvalidMFASecret() {
+        // Test with invalid MFA secret
+        Map params = new HashMap<>();
+        params.put("mfaSecret", "invalid-secret");
+        
+        IllegalArgumentException exception = Assertions.assertThrows(
+            IllegalArgumentException.class,
+            () -> userInstance.login("test@example.com", "password", params).request()
+        );
+        
+        Assertions.assertTrue(exception.getMessage().contains("Invalid MFA secret key"));
+    }
+
+    @Test
+    @Order(47)
+    @DisplayName("Test empty parameters")
+    void testEmptyParameters() {
+        // Test with empty parameters map
+        Map params = new HashMap<>();
+        
+        IllegalArgumentException exception = Assertions.assertThrows(
+            IllegalArgumentException.class,
+            () -> userInstance.login("test@example.com", "password", params).request()
+        );
+        
+        Assertions.assertTrue(exception.getMessage().contains("Must provide either tfaToken or mfaSecret"));
+    }
+
+    @Test
+    @Order(48)
+    @DisplayName("Test empty values in parameters")
+    void testEmptyValues() {
+        // Test with empty tfaToken
+        Map params1 = new HashMap<>();
+        params1.put("tfaToken", "");
+        
+        IllegalArgumentException exception1 = Assertions.assertThrows(
+            IllegalArgumentException.class,
+            () -> userInstance.login("test@example.com", "password", params1).request()
+        );
+        Assertions.assertTrue(exception1.getMessage().contains("Must provide either tfaToken or mfaSecret"));
+        
+        // Test with empty mfaSecret
+        Map params2 = new HashMap<>();
+        params2.put("mfaSecret", "");
+        
+        IllegalArgumentException exception2 = Assertions.assertThrows(
+            IllegalArgumentException.class,
+            () -> userInstance.login("test@example.com", "password", params2).request()
+        );
+        Assertions.assertTrue(exception2.getMessage().contains("Must provide either tfaToken or mfaSecret"));
+    }
 }