Каким образом обменять code на access_token (правильно) в Spring OAuth2?

Обмен code на access_token в Spring OAuth2 происходит при использовании Authorization Code Flow. Этот поток позволяет пользователям предоставить доступ к своему аккаунту на стороннем ресурсе (например, Facebook или Google), чтобы приложение могло получить токен доступа и получить доступ к защищенным ресурсам от имени пользователя.

Для успешного обмена кода на токен доступа в Spring OAuth2, вам потребуется настроить несколько компонентов.

1. Конфигурация клиентской информации:
В классе конфигурации вам нужно определить информацию о клиенте, который будет запрашивать доступ к ресурсам. Это делается с использованием объекта ClientDetailsServiceConfigurer.

   @Configuration
   @EnableAuthorizationServer
   public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
         
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients
                .inMemory()
                .withClient("clientId")
                .secret("clientSecret")
                .authorizedGrantTypes("authorization_code")
                .scopes("read", "write")
                .redirectUris("http://localhost:8080/callback");
        }
         
        // другие настройки
   }

Здесь clientId и clientSecret - значения, которые вы получаете при регистрации вашего приложения на стороннем ресурсе. authorizedGrantTypes указывает, что ваше приложение использует Authorization Code Flow. scopes определяют, какие ресурсы пользователь разрешает вашему приложению.

2. Контроллер для обработки запроса callback:
Вы должны создать контроллер, который будет получать код авторизации и использовать его для получения токена доступа. Ваш контроллер должен быть аннотирован как @Controller или @RestController и иметь метод, который будет принимать код авторизации.

   @RestController
   public class OAuth2CallbackController {
     
        @Autowired
        private AuthorizationCodeTokenGranter tokenGranter;
     
        @RequestMapping(value = "/callback", method = RequestMethod.GET)
        public String callback(@RequestParam("code") String code, HttpServletRequest request) {
            TokenRequest tokenRequest = tokenGranter.createTokenRequest(Collections.emptyMap(), code);
            OAuth2AccessToken token = tokenGranter.getTokenServices().createAccessToken(tokenGranter.getClient(), tokenRequest);
            // делайте что-то с полученным токеном доступа
            return "Success!";
        }
   }

Здесь AuthorizationCodeTokenGranter - это класс, предоставляющий методы для создания и получения токенов в кодовом потоке авторизации.

Теперь, когда вы настроили клиентскую информацию и контроллер обратного вызова, вы можете перенаправить пользователя на страницу авторизации стороннего ресурса следующим образом:

@GetMapping("/authorize")
public void authorize(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String authorizeUrl = "http://facebook.com/oauth/authorize?response_type=code"
        + "&client_id=clientId"
        + "&redirect_uri=http://localhost:8080/callback";
    response.sendRedirect(authorizeUrl);
}

При перенаправлении пользователя на страницу авторизации он будет предоставлять свои учетные данные на стороннем ресурсе, а затем будет перенаправлен обратно на ваш адрес обратного вызова с кодом авторизации. Ваш контроллер обратного вызова затем получит этот код и обменяет его на токен доступа.

В результате успешного обмена кода на токен доступа вы сможете использовать полученный токен для доступа к защищенным ресурсам от имени пользователя.