Spring Security и Azure. После перезапуска приложение пытается выполнить повторную авторизацию, но перенаправление Azure на redirect-uri приводит к 404 - PullRequest
0 голосов
/ 09 июля 2019

Я пишу веб-приложение Spring Boot 2. Он использует Azure AD для аутентификации пользователя (с использованием потока кода авторизации и делегированных разрешений), используя поддержку входа в Spring Security OAuth 2.0. Он также пытается получить доступ к ресурсам Microsoft Graph. Однако он не использует библиотеку Microsoft Azure для Spring.

По большей части приведенный ниже код работает как положено. (Я запускаю его локально.)

@Autowired
private RestTemplateBuilder restTemplateBuilder;

@RequestMapping("/aboutMe")
public String aboutMe(Model model,
                      @RegisteredOAuth2AuthorizedClient("azure") OAuth2AuthorizedClient authorizedClient) {
    String accessTokenValue = authorizedClient.getAccessToken().getTokenValue();

    RestTemplate restTemplate = buildRestTemplate(accessTokenValue);

    String user = restTemplate.getForObject("https://graph.microsoft.com/v1.0/me", String.class);

    model.addAttribute("user", user);

    return "pages/me";
}

private RestTemplate buildRestTemplate(String accessTokenValue) {
    RestTemplate restTemplate = restTemplateBuilder.additionalInterceptors(
        new ClientHttpRequestInterceptor() {
            @Override
            public ClientHttpResponse intercept(HttpRequest request, byte[] bytes,
                                ClientHttpRequestExecution execution) throws IOException {

                request.getHeaders().add("Authorization", "Bearer " + accessTokenValue);

                return execution.execute(request, bytes);
            }
        }).build();

    return restTemplate;
}

Однако следующий тестовый пример работает, как и ожидалось, до тех пор, пока приложение не будет перезапущено.

Контрольный пример

  1. Откройте браузер в первый раз и перейдите к http://localhost:8080/aboutMe.
  2. Браузер перейдет на страницу входа Microsoft. Войдите в систему, используя учетные данные Azure AD.
  3. После этого браузер перейдет на страницу /aboutMe.
  4. Закройте приложение и запустите его снова.
  5. Не закрывайте браузер. Оставьте это открытым.
  6. Попробуйте еще раз перейти к http://localhost:8080/aboutMe.

Фактический результат

  1. Браузер перенаправлен на конечную точку Microsoft https://login.microsoftonline.com/[tenantId]/oauth2/v2.0/authorize.
  2. Запрос Microsoft authorize затем перенаправляет браузер на redirect-uri приложения, которое в этом случае начинается с http://localhost:8080/login/oauth2/code/azure.
  3. Приложение отвечает 404 - Не найдено.

Ожидаемый результат

Или:

  • Azure AD должен снова отобразить страницу входа в систему и попросить пользователя снова пройти аутентификацию, а затем приложение должно правильно обработать ее;
  • или Либо приложение, либо Spring, либо оба должны обрабатывать запрос на перенаправление вместо возврата 404.

Исследование

Кажется, что 404 из-за того, что redirect-uri приложения не всегда "слушает", особенно в этом случае.

В приведенном выше коде контроллера @RegisteredOAuth2AuthorizedClient("azure") заставляет OAuth2AuthorizedClientArgumentResolver Spring Security выбросить ClientAuthorizationRequiredException, потому что он не может найти OAuth2AuthorizedClient - что мы и ожидали, учитывая, что приложение было перезапущен.

Затем ClientAuthorizationRequiredException заставляет OAuth2AuthorizationRequestRedirectFilter перенаправить браузер в Azure для запроса авторизации.

Однако вместо того, чтобы запрашивать учетные данные пользователя, Azure перенаправляет браузер на приложение redirect-uri, что выглядит как новая авторизация. (Я предполагаю, что это потому, что браузер отправил файлы cookie со своим запросом, который Azure считает действительным.)

Наконец, мой вопрос

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

Я считаю, что конечная точка /login/oauth2/code/azure обычно обрабатывается фильтрами Spring Security, поэтому я не уверен, как это перехватить.

Может быть, решение состоит в том, чтобы приложение запускало все свои куки в браузере при запуске? Но как насчет печенья Azure?

1 Ответ

0 голосов
/ 10 июля 2019

Мне удалось решить эту проблему, добавив .oauth2Client() в конфигурацию Spring Security.Вот рабочая конфигурация:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/web/**")
                .hasRole("USER")
            .antMatchers("/")
                .permitAll()
        .and()
        .oauth2Login()
            .userInfoEndpoint()
                .oidcUserService(this.oidcUserService())
            .and()
            .defaultSuccessUrl("/", false)
        .and()
        .logout()
            .logoutSuccessUrl(azureLogoutUri)
            .permitAll()
        // Without the oauth2Client(), the 404 happens
        .and()
        .oauth2Client();
}

Добавление .oauth2Client() заставляет Spring добавить в цепочку фильтров безопасности секунду OAuth2AuthorizationRequestRedirectFilter и OAuth2AuthorizationCodeGrantFilter.

, которые я ошибочно предположилчто oauth2Client() не было необходимости.Кажется, что это правда, только если он не находит WebSecurityConfigurerAdapter.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...