Как защитить REST API Spring Boot с помощью Azure AD B2C? - PullRequest
1 голос
/ 30 октября 2019

Я использую Spring Boot 2.2.0 с azure-active-directory-b2c-spring-boot-starter 2.2.0. Мне удалось защитить веб-страницу Thymeleaf этим (следуя их учебному пособию). Теперь я хочу, чтобы REST API был защищен таким же образом, поскольку реальным приложением будет мобильное приложение, которое выполняет вызовы REST для моего бэкэнда Spring Boot.

Я уже понял, как получитьтокен с потоком предоставления пароля, используя:

POST https://<my-tenant-id>.b2clogin.com/<my-tenant-id.onmicrosoft.com/oauth2/v2.0/token?p=B2C_1_<my-custom-policy>

(с именем пользователя и паролем в качестве параметров)

Таким образом, мобильное приложение может использовать этот вызов. Но как мне настроить приложение Spring Boot, чтобы использование Authorization: Bearer <access-token> для вызовов API работало? Какие зависимости / стартеры мне нужны и как мне что-то настраивать?

ОБНОВЛЕНИЕ:

Я попытался добавить:

<dependency>
  <groupId>org.springframework.security.oauth</groupId>
  <artifactId>spring-security-oauth2</artifactId>
  <version>2.3.7.RELEASE</version>
</dependency>

С:

@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class OAuth2ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("my-azure-b2c-test");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/api/**")
            .authenticated();
    }
}

Но когда я делаю запрос в своем приложении Spring Boot, я получаю 401 с ошибкой "invalid_token".

1 Ответ

1 голос
/ 30 октября 2019

Решение кажется довольно простым, если вы его знаете.

Сначала добавьте следующие зависимости:

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-resource-server</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>

Далее укажите свойство spring.security.oauth2.resourceserver.jwt.jwk-set-uri в файле application.properties.

Чтобы узнать это значение, выполните GET (используя cURL или другой инструмент) для https://<my-tenant-id>.b2clogin.com/<my-tenant-id>.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_<my-custom-policy>

. Это вернет тело JSON со значением jwks_uri. Возьмите это значение и поместите его в файл application.properties.

Теперь создайте этот класс Java в проекте:

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/api/**")
            .authenticated()
            .and()
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
    }
}

Если у вас теперь есть контроллер, подобный этому:

@RestController
public class ApiController {

    @GetMapping("/api/test")
    public String apiTest(@AuthenticationPrincipal Principal principal) {
        return "test " + principal;
    }
}

Вы увидите, что принципал не равен NULL, если вы выполните GET для api/test с правильным заголовком Authorization (и он имеет тип org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken)

Единственное, чтоК сожалению, у Принципала нет полномочий, и мне все еще нужно выяснить, почему.

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