Let’s learn to create the Login API with JWT in our User management service Java GRPC. we have already learned about onboarding/creating new users to the User Management Service. The user has provided an email address and password during the registration process. Now we will ask for the same email address and password from the user while calling the Login API and provide then a JWT access token if the credentials are correct

Create Login Controller

The login controller will play the orchestration process of login functionality

  • Validate the incoming fields
  • Check if the user exists in the database with the same email address and password
  • Return JWT token if credentials are correct

Inside the controller folder create a new file LoginController.java

package user.management.system.grpc.controller;

import java.sql.SQLException;

import com.cwrr.user_management.LoginRequest;
import com.cwrr.user_management.LoginResponse;

import user.management.system.grpc.db.UserRepository;
import user.management.system.grpc.exception.Exception4XX;
import user.management.system.grpc.exception.Exception5XX;
import user.management.system.grpc.model.User;
import user.management.system.grpc.service.JWTService;

public class LoginController {

    UserRepository userRepository;
    JWTService jwtService;

    public LoginController(UserRepository userRepository, JWTService jwtService) {
        this.userRepository = userRepository;
        this.jwtService = jwtService;
    }

    public LoginResponse login(LoginRequest loginRequest) throws Exception4XX, Exception5XX, SQLException {
     
        if(loginRequest.getEmail().isEmpty()) {
            throw new Exception4XX("300", "email", "Email can not be empty");
        }
        if(loginRequest.getPassword().isEmpty()) {
            throw new Exception4XX("300", "password", "Password can not be empty");
        }

        
        User user = userRepository.findByEmailAndPassword(loginRequest.getEmail(),loginRequest.getPassword());
        if(user == null) {
            throw new Exception4XX("304", "email and password", "invalid email and password combination");
        }

        String token = jwtService.generateToken(user.getFirstName(), user.getEmail() , user.getLastName(), user.getId());


        return LoginResponse.newBuilder()
        .setSuccess(true)
        .setJwtToken(token)
        .build();       

    }
    
}
  • Instance Variables
    • userRepository
    • jwtService
      • This service is responsible for creating and validating the token
  • Public Methods
    • LoginController Constructor
      • Accept userRespository and jwtService for filling up the class dependencies
    • login
      • Accept the LoginRequst and return the LoginResponse which contains the JWT token
      • In case of errors throw exceptions like Exception4XX, Exception5XX
  • Code Logic
    • Validation of incoming fields is performed
      • Validation Fails
        • Return error to user
      • Validation Success
        • Check if the user with an email and password exists in the database
          • User Already Exists
            • Create a JWT token with the help of the JWT service
            • Return LoginResponse
          • User Not Exists in the database
            • Return LoginResposne with error object in it

User Management Server Login User

we have already added the login RPC in the UserManagementServer.java file. Now let’s add the logic where we integrate it with the LoginController

Add the below content for your login RPC

@Override
    public void login(com.cwrr.user_management.LoginRequest loginRequest, io.grpc.stub.StreamObserver<com.cwrr.user_management.LoginResponse> responseObserver) {
        
        try {
            LoginResponse loginResponse = loginController.login(loginRequest);
            responseObserver.onNext(loginResponse);
            responseObserver.onCompleted();
            
        } catch(Exception4XX e){
            e.printStackTrace();
            Error error = Error.newBuilder().setCode(e.getCode()).setEntity(e.getEntity()).setMessage(e.getMessage()).build();
            LoginResponse loginResponse = LoginResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(loginResponse);
            responseObserver.onCompleted();
        }catch(Exception5XX e){
            e.printStackTrace();
            Error error = Error.newBuilder().setCode(e.getCode()).setEntity(e.getEntity()).setMessage(e.getMessage()).build();
            LoginResponse loginResponse = LoginResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(loginResponse);
            responseObserver.onCompleted();
        } catch (Exception e) {
            e.printStackTrace();
            Error error = Error.newBuilder().setCode("900").setEntity("internal server error").setMessage("internal server error").build();
            LoginResponse loginResponse = LoginResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(loginResponse);
            responseObserver.onCompleted();
        }
    }
  • login
    • This is the method where the request will reach first when someone calls the login RPC
    • This calls the login method present in LoginController
    • All the Exceptions are handled and a meaningful response is returned to the user.

The full UserMangementServer.java file is

package user.management.system.grpc.server;


import com.cwrr.user_management.CreateUserResponse;
import com.cwrr.user_management.Error;
import com.cwrr.user_management.LoginResponse;
import com.cwrr.user_management.UserManagementServiceGrpc.UserManagementServiceImplBase;

import user.management.system.grpc.controller.UserCreateController;
import user.management.system.grpc.db.Database;
import user.management.system.grpc.db.UserRepository;
import user.management.system.grpc.controller.LoginController;
import user.management.system.grpc.exception.Exception4XX;
import user.management.system.grpc.exception.Exception5XX;
import user.management.system.grpc.service.JWTService;

public class UserManagementServer extends UserManagementServiceImplBase{

    UserCreateController userCreateController;
    LoginController loginController;

    public UserManagementServer() {

        Database db = new Database();
        JWTService jwtService = new JWTService();
        UserRepository userRepository = new UserRepository(db);
        userCreateController = new UserCreateController(userRepository);
        loginController = new LoginController(userRepository, jwtService);
    }

    @Override
    public void createUser(com.cwrr.user_management.CreateUserRequest createUserRequest, io.grpc.stub.StreamObserver<com.cwrr.user_management.CreateUserResponse> responseObserver) {
        
        try {
            
            int userId = userCreateController.createUser(createUserRequest);
            CreateUserResponse createUserResponse = CreateUserResponse.newBuilder()
            .setSuccess(true)
            .setUserId(userId)
            .build();
            responseObserver.onNext(createUserResponse);
            responseObserver.onCompleted();
        } catch(Exception5XX e){
            e.printStackTrace();
            Error error = Error.newBuilder().setCode(e.getCode()).setEntity(e.getEntity()).setMessage(e.getMessage()).build();
            CreateUserResponse createUserResponse = CreateUserResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(createUserResponse);
            responseObserver.onCompleted();
        } catch(Exception4XX e){
            e.printStackTrace();
            Error error = Error.newBuilder().setCode(e.getCode()).setEntity(e.getEntity()).setMessage(e.getMessage()).build();
            CreateUserResponse createUserResponse = CreateUserResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(createUserResponse);
            responseObserver.onCompleted();
        } catch (Exception e) {
            e.printStackTrace();
            Error error = Error.newBuilder().setCode("900").setEntity("internal server error").setMessage("internal server error").build();
            CreateUserResponse createUserResponse = CreateUserResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(createUserResponse);
            responseObserver.onCompleted();
        }
             
    }

    @Override
    public void login(com.cwrr.user_management.LoginRequest loginRequest, io.grpc.stub.StreamObserver<com.cwrr.user_management.LoginResponse> responseObserver) {
        
        try {
            LoginResponse loginResponse = loginController.login(loginRequest);
            responseObserver.onNext(loginResponse);
            responseObserver.onCompleted();
            
        } catch(Exception4XX e){
            e.printStackTrace();
            Error error = Error.newBuilder().setCode(e.getCode()).setEntity(e.getEntity()).setMessage(e.getMessage()).build();
            LoginResponse loginResponse = LoginResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(loginResponse);
            responseObserver.onCompleted();
        }catch(Exception5XX e){
            e.printStackTrace();
            Error error = Error.newBuilder().setCode(e.getCode()).setEntity(e.getEntity()).setMessage(e.getMessage()).build();
            LoginResponse loginResponse = LoginResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(loginResponse);
            responseObserver.onCompleted();
        } catch (Exception e) {
            e.printStackTrace();
            Error error = Error.newBuilder().setCode("900").setEntity("internal server error").setMessage("internal server error").build();
            LoginResponse loginResponse = LoginResponse.newBuilder()
            .setSuccess(false)
            .setError(error)
            .build();
            responseObserver.onNext(loginResponse);
            responseObserver.onCompleted();
        }
    }

}

Note: We have added the jwtService and the loginContorller inside the constructor.

Start the server

You can start the server and use any GRPC client like the Postman to hit this RPC to get JWT token on successful credentials check.

./gradlew run
Gradle run java server

This was all about the user creation

Previous: Part 5: JWT token Java | User Management Service Java GRPC

References

Leave a Reply

Your email address will not be published. Required fields are marked *