React MUI Login Page with MySQL Spring Boot (Username, Password and Role)

Your setup is mostly correct, but the root cause of your “Invalid username or password” error lies in how your backend and frontend are handling the login response format and password encoding together.

Let’s go step by step:


🧩 1. The actual backend issue

Your backend’s login method:

public String loginUser(String username, String password) { return userRepository.findByUsername(username) .filter(user -> passwordEncoder.matches(password, user.getPassword())) .map(user -> jwtUtil.generateToken(user.getUsername(), user.getRole().name())) .orElseThrow(() -> new RuntimeException("Invalid username or password")); }

works fine logically — it:

  • finds the user by username

  • checks the password using passwordEncoder.matches()

  • returns a JWT token

BUT you are returning just a String (the token).

Your frontend’s AuthContext.js is expecting this:

const { token, ...userInfo } = res.data;

That means it expects the backend to return an object like:

{ "token": "jwt-token-here", "username": "john", "role": "ADMIN" }

But your backend returns just a plain token string, so res.data.token becomes undefined.
That’s why the frontend can’t handle the response properly and the login “fails.”


🧱 2. The password part (encoded vs raw)

Your registration uses:

user.setPassword(passwordEncoder.encode(user.getPassword()));

so the password is encoded in the database.

During login:

passwordEncoder.matches(password, user.getPassword())

correctly compares raw password with encoded — ✅
No issue here, as long as the same encoder is used.

So password matching works fine.
The only reason you see “Invalid username or password” is likely because the user isn’t being found (wrong username) or you’re testing with unencoded passwords in DB from older runs.

You can verify quickly:

SELECT username, password FROM user;

If you see plain text passwords (not starting with $2a$ or $2b$), then re-register the user — those won’t match.


🩹 3. The required backend fix

Change your loginUser() and AuthController to return a JSON object containing token, username, and role.

✅ Update in AuthService.java

public Map<String, Object> loginUser(String username, String password) { return userRepository.findByUsername(username) .filter(user -> passwordEncoder.matches(password, user.getPassword())) .map(user -> { String token = jwtUtil.generateToken(user.getUsername(), user.getRole().name()); Map<String, Object> response = new HashMap<>(); response.put("token", token); response.put("username", user.getUsername()); response.put("role", user.getRole().name()); return response; }) .orElseThrow(() -> new RuntimeException("Invalid username or password")); }

✅ Update in AuthController.java

@PostMapping("/login") public ResponseEntity<Map<String, Object>> loginUser(@RequestBody User user) { Map<String, Object> response = authService.loginUser(user.getUsername(), user.getPassword()); return ResponseEntity.ok(response); }

Now, the response from backend will look like:

{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "username": "john", "role": "ADMIN" }

and your frontend’s line:

const { token, ...userInfo } = res.data;

will correctly pick token and store the rest in localStorage.


✅ 4. Double-check these final details

a. Register a fresh user

Since passwords are encoded, old users (from before encoding) won’t work.

b. Confirm .env or application.properties

Your jwt.secret must be a valid Base64 string (at least 32 bytes long). Example:

jwt.secret=VGhpcy1pcy1hLXNlY3JldC1rZXktZm9yLWp3dC1zaWduaW5nLXRlc3Q=

c. Ensure your frontend points to the right auth base URL

In constants.js:

export const BASE_URL_AUTH = "http://localhost:8080"; // Example

✅ Final Summary

ProblemFix
Backend returns plain string instead of JSONReturn { token, username, role } object
Password check fails for old usersRe-register so passwords are encoded
Frontend expecting structured JSONNow matches backend output
JWT key not Base64 encodedEnsure proper secret format

Would you like me to show how to modify your frontend login logic slightly to show better error messages and persist both token + role in context cleanly?

Post a Comment

0 Comments