admin管理员组

文章数量:1398786

I've built a couple monolith applications using stateful sessions already. I now wanted to challenge myself and create my first micro service application using OAuth2.

After spending many hours watching tutorials, and reading spring documentation, about JWT, OAuth2 and authenticating and authorising micro services using Spring I came up with an implementation but I am not sure if this is the correct approach (or if I am doing sth stupid). Many of the tutorials I watched all do different things.

My project consists of an API (OAuth Resource and Authorisation Server) that is also responsible for authenticating and authorising users who log in using the frontend (individual service) and micro services that use this API and also communicate with each other. The micro services will all share the public key to decode the JWTs (using RSA) and a JWT decoder bean to do that.

My approach to authenticating users looks like the following. I was wondering if I can use the exact same approach to authenticate the micro services as well or if there is a better approach. Is this approach even secure or do you spot potential flaws that I might have overlooked?

User Authentication:

 @PostMapping("/token/user")
 ResponseEntity<String> getTokenForUser(@RequestBody @Valid UserLoginRequest loginRequest) {

        LOG.debug(loginRequest.toString());

        Authentication authentication =
                userAuthenticationManager.authenticate(
                        new UsernamePasswordAuthenticationToken(
                                loginRequest.username, loginRequest.password));

        String subject = authentication.getName();
        String scope =
                authentication.getAuthorities().stream()
                        .map(GrantedAuthority::getAuthority)
                        .collect(Collectors.joining(" "));

        LOG.debug("User: {}", subject);
        LOG.debug("Scope: {}", scope);

        return ResponseEntity.ok(jwtService.generateToken(subject, scope));
    }

    private record UserLoginRequest(@NotBlank String username, @NotBlank String password) {}

Explanation: I defined a authenticationManager bean and implemented a user entity which implements UserDetails and a created a UserService that implements the UserDetailsService which makes a query to my db that retrieves a user based on the provided username. This already works and issues a JWT.

My approach for the micro service authentication and authorisation

  1. Create a new db table with entities like this:
@Entity
@Table(name = "micro_services")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MicroService implements UserDetails {
    @Id private Long serviceId;
    private String serviceSecret;
    private String scope;
}
  1. Create a new MicroServiceDetailsService which implements UserDetailsService that would query a MircoService entity from the database using the MicroServiceRepository
  2. Create another AuthenticationManager Bean (could this cause conflict with the other one?) that authenticates micro services
 @Bean
    AuthenticationManager microServiceAuthenticationManager() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(microServiceDetailsService);
        authenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
        return new ProviderManager(authenticationProvider);
    }
  1. Create a new endpoint for micro services to call to authenticate themselves and get a JWT
  @PostMapping("/token/service")
    ResponseEntity<String> getTokenForService(
            @RequestBody @Valid ServiceLoginRequest loginRequest) {
        LOG.debug(loginRequest.toString());

        Authentication authentication =
                microServiceAuthenticationManager.authenticate(
                        new UsernamePasswordAuthenticationToken(
                                loginRequest.serviceId, loginRequest.serviceSecret));

        String subject = authentication.getName();
        String scope =
                authentication.getAuthorities().stream()
                        .map(GrantedAuthority::getAuthority)
                        .collect(Collectors.joining(" "));

        LOG.debug("Service: {}", subject);
        LOG.debug("Scope: {}", scope);

        return ResponseEntity.ok(jwtService.generateToken(subject, scope));
    }

    private record ServiceLoginRequest(@NotBlank String serviceId, @NotBlank String serviceSecret) {}

RegisteredClientRepository? I have seen RegisteredClientRepository often when researching about OAuth2 and JWT authentication for micro services. Should I rather use that instead? From what I have seen you would need to hard code all clients, at least that's how it has been done in all examples and tutorials I saw.

I use Spring version 3.4.3

Thank you very very much in advance!

本文标签: javaImplementing User and Microservice JWT Authentication using Spring BootStack Overflow