简体   繁体   中英

Spring Boot oauth2 with local user database

I have implemented OIDC authentication in my Spring Boot web application by adding the spring-boot-starter-oauth2-client dependency and configuring OAuth2 client settings in application.properties .

In the Spring Boot and OAuth2 guide there is a section "How to Add a Local User Database":

How to Add a Local User Database

Many applications need to hold data about their users locally, even if authentication is delegated to an external provider. We don't show the code here, but it is easy to do in two steps.

  1. Choose a backend for your database, and set up some repositories (using Spring Data, say) for a custom User object that suits your needs and can be populated, fully or partially, from external authentication.

  2. Implement and expose OAuth2UserService to call the Authorization Server as well as your database. Your implementation can delegate to the default implementation, which will do the heavy lifting of calling the Authorization Server. Your implementation should return something that extends your custom User object and implements OAuth2User.

Hint: add a field in the User object to link to a unique identifier in the external provider (not the user's name, but something that's unique to the account in the external provider).

I have searched a bit but I have not found a code example for the scenario described in the excerpt.

What is the best way to implement the scenario above?

I guess the main parts would be:

  • On OIDC login, automatically create a user in the database if it does not exist
  • The web application controller methods have access to the database object that represents the logged-in user

Update:

The guide has a github issue comment that suggests to look at the custom-error sample from the guide's source code . I guess the first part (on OIDC login, automatically create a user if one does not exist) can be done after the call to DefaultOAuth2UserService().loadUser(request) . But what about the second part - how can my custom db-backed-user-object be made available to my web application's controller methods?

@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService(WebClient rest) {
    DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
    return request -> {
        OAuth2User user = delegate.loadUser(request);
        if (!"github".equals(request.getClientRegistration().getRegistrationId())) {
            return user;
        }

        OAuth2AuthorizedClient client = new OAuth2AuthorizedClient
                (request.getClientRegistration(), user.getName(), request.getAccessToken());
        String url = user.getAttribute("organizations_url");
        List<Map<String, Object>> orgs = rest
                .get().uri(url)
                .attributes(oauth2AuthorizedClient(client))
                .retrieve()
                .bodyToMono(List.class)
                .block();

        if (orgs.stream().anyMatch(org -> "spring-projects".equals(org.get("login")))) {
            return user;
        }

        throw new OAuth2AuthenticationException(new OAuth2Error("invalid_token", "Not in Spring Team", ""));
    };
}

Github uses OAuth2UserService<OAuth2UserRequest, OAuth2User> what you need is OAuth2UserService<OidcUserRequest, OidcUser> . So did you try creating another @Bean which plugs into the correct place spring expects?

If not, create one like this

  @Bean
  public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
    final OidcUserService delegate = new OidcUserService();
    return (userRequest) -> {
      // Delegate to the default implementation for loading a user
      OidcUser user = delegate.loadUser(userRequest);
      log.info("User from oauth server: " + user);
      //OAuth2AccessToken accessToken = userRequest.getAccessToken();
      //Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
      //Fetch the authority information from the protected resource using accessToken
      //Map the authority information to one or more GrantedAuthority's and add it to mappedAuthorities
      //Create a copy of user using mappedAuthorities
      //Insert/update local DB
      //user = new DefaultOidcUser(mappedAuthorities, user.getIdToken(), user.getUserInfo());
      return user;
    };
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM