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

chanholee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new a14243ca35 [ZEPPELIN-6181] Login form does not pass plus sign into 
authenticator
a14243ca35 is described below

commit a14243ca354d41af19e9cc2b7ad5383eef38ed64
Author: Yuijin Kim(yuikim) <106499310+kmular...@users.noreply.github.com>
AuthorDate: Tue Aug 26 20:10:35 2025 +0900

    [ZEPPELIN-6181] Login form does not pass plus sign into authenticator
    
    ### What is this PR for?
    
    This PR fixes an authentication bug where plus signs (+) in usernames or 
passwords were being incorrectly converted to spaces during login form 
submission. The issue affected both LDAP authenticator and local users in 
shiro.ini (IniRealm), causing authentication failures for any credentials 
containing URL-unsafe characters.
    
    ### What type of PR is it?
    
    Bug Fix
    
    ### Todos
    
    * [x] - Apply encodeURIComponent() to userName and password fields
    * [x] - Test with credentials containing plus signs and other special 
characters
    
    ### What is the Jira issue?
    
    * [ZEPPELIN-6181](https://issues.apache.org/jira/browse/ZEPPELIN-6181) : 
Login form does not pass plus sign into authenticator
    
    ### How should this be tested?
    
    **Manual Testing:**
    1. Create a test user with username containing plus sign (e.g., `user+test`)
    2. Create a test user with password containing plus sign (e.g., `pass+word`)
    3. Attempt to login through the web interface
    4. Verify authentication succeeds for both cases
    
    ### Screenshots (if appropriate)
    
    N/A
    
    ### Questions:
    
    * Does the license files need to update? **No**
    * Is there breaking changes for older versions? **No**
    * Does this needs documentation? **No** - This is a bug fix that maintains 
existing functionality
    
    Closes #5024 from kmularise/ZEPPELIN-6181.
    
    Signed-off-by: ChanHo Lee <chanho...@apache.org>
---
 .../src/app/services/ticket.service.ts             | 37 +++++++++++++++-------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/zeppelin-web-angular/src/app/services/ticket.service.ts 
b/zeppelin-web-angular/src/app/services/ticket.service.ts
index 05f75f3d5e..d12da61120 100644
--- a/zeppelin-web-angular/src/app/services/ticket.service.ts
+++ b/zeppelin-web-angular/src/app/services/ticket.service.ts
@@ -10,7 +10,7 @@
  * limitations under the License.
  */
 
-import { HttpClient, HttpParams } from '@angular/common/http';
+import { HttpClient } from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import { Router } from '@angular/router';
 import { forkJoin, BehaviorSubject, Subject } from 'rxjs';
@@ -86,19 +86,32 @@ export class TicketService {
     );
   }
 
+  // Note: We intentionally avoid using HttpParams here due to Angular issue 
#11058.
+  // See: https://github.com/angular/angular/issues/11058
+  // HttpParameterCodec incorrectly encodes special characters like '+' and 
'=',
+  // which can cause issues in application/x-www-form-urlencoded requests
+  // (e.g., '+' becomes space in PHP/Tomcat). Therefore, we manually build
+  // the payload using encodeURIComponent for each field.
   login(userName: string, password: string) {
-    const payload = new HttpParams().set('userName', userName).set('password', 
password);
-    return 
this.httpClient.post<ITicket>(`${this.baseUrlService.getRestApiBase()}/login`, 
payload).pipe(
-      tap(
-        data => {
-          this.nzMessageService.success('Login Success');
-          this.setTicket(data);
-        },
-        () => {
-          this.nzMessageService.warning("The username and password that you 
entered don't match.");
+    const payload = 
`userName=${encodeURIComponent(userName)}&password=${encodeURIComponent(password)}`;
+
+    return this.httpClient
+      .post<ITicket>(`${this.baseUrlService.getRestApiBase()}/login`, payload, 
{
+        headers: {
+          'Content-Type': 'application/x-www-form-urlencoded'
         }
-      )
-    );
+      })
+      .pipe(
+        tap(
+          data => {
+            this.nzMessageService.success('Login Success');
+            this.setTicket(data);
+          },
+          () => {
+            this.nzMessageService.warning("The username and password that you 
entered don't match.");
+          }
+        )
+      );
   }
 
   getZeppelinVersion() {

Reply via email to