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
- Part 1: What we are going to Build | User Management Service | Java | GRPC
- Part 2: MySQL Database | User Management Service | Java GRPC
- Part 3: GRPC Server Java | User Management Service
- Part 4: Create User in User Management Service GRPC Java
- Part 5: JWT token Java | User Management Service Java GRPC
- Part 6: Login API with JWT | User Management service Java GRPC
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
- This is the userRepository database instance.
- It is responsible for performing operations on the user database table
- UserRepository.java class was created in the previous post
- jwtService
- This service is responsible for creating and validating the token
- userRepository
- 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
- LoginController Constructor
- 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 Already Exists
- Check if the user with an email and password exists in the database
- Validation Fails
- Validation of incoming fields is performed
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
This was all about the user creation
Previous: Part 5: JWT token Java | User Management Service Java GRPC