简体   繁体   English

带有本地用户数据库的 Spring Boot oauth2

[英]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 .我通过添加spring-boot-starter-oauth2-client依赖项并在application.properties中配置 OAuth2 客户端设置,在我的 Spring Boot Web 应用程序中实现了 OIDC 身份验证。

In the Spring Boot and OAuth2 guide there is a section "How to Add a Local User Database":Spring Boot 和 OAuth2指南中有一节“如何添加本地用户数据库”:

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.为您的数据库选择一个后端,并为适合您需要的自定义用户对象设置一些存储库(例如使用 Spring Data),并且可以从外部身份验证中全部或部分填充。

  2. Implement and expose OAuth2UserService to call the Authorization Server as well as your database.实施并公开 OAuth2UserService 以调用授权服务器以及您的数据库。 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.您的实现应该返回扩展您的自定义用户对象并实现 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在 OIDC 登录时,如果用户不存在,则自动在数据库中创建一个用户
  • The web application controller methods have access to the database object that represents the logged-in user Web 应用程序控制器方法可以访问代表登录用户的数据库对象

Update:更新:

The guide has a github issue comment that suggests to look at the custom-error sample from the guide's source code .该指南有一个 github 问题评论,建议查看指南源代码中的custom-error示例。 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) .我想第一部分(在 OIDC 登录时,如果用户不存在则自动创建用户)可以在调用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?但是第二部分呢——如何让我的自定义 db-backed-user-object 对我的 Web 应用程序的控制器方法可用?

@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> . Github 使用OAuth2UserService<OAuth2UserRequest, OAuth2User>你需要的是OAuth2UserService<OidcUserRequest, OidcUser> So did you try creating another @Bean which plugs into the correct place spring expects?那么您是否尝试创建另一个插入 spring 期望的正确位置的@Bean

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;
    };
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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