Как убедиться, что только токены JWT из собственного приложения принимаются на защищенном сервере ресурсов Spring Security - PullRequest
1 голос
/ 31 октября 2019

Я использую Spring Security с Spring Boot 2.2.0, пытаюсь заставить работать Azure AD B2C, используя spring-security-oauth2-resource-server:5.2.0 и spring-security-oauth2-jose:5.2.0.

Используя эту конфигурацию:

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

с spring.security.oauth2.resourceserver.jwt.jwk-set-uri, установленным в моем application.properties.

Я могу получить токен из Azure AD B2C и получить доступ к своей собственной конечной точке API, используя этот токен. Однако, если я использую токен из другого каталога , конечная точка также может быть доступна.

Я вижу в утверждениях принципала, что это происходит из другого каталога Azure. Это то, что мне нужно вручную добавить в мое приложение (тестирование, если идентификатор приложения совпадает в заявке)? Или я должен добавить какую-то другую конфигурацию, которую я еще не сделал?

Я также попытался добавить свой собственный компонент JwtDecoder, как это, используя JwtDecoders.fromOidcIssuerLocation("https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/?p=B2C_1_ropc_flow");, но это дает:

java.lang.IllegalStateException: The Issuer "https://mycompb2ctestorg.b2clogin.com/60780907-bc3a-469a-82d1-b89ffed655af/v2.0/" 
provided in the configuration did not match the requested issuer 
"https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/?p=B2C_1_ropc_flow"

Также,использование:

spring.security.oauth2.resourceserver.jwt.issuer-uri=https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/?p=B2C_1_ropc_flow

дает то же исключение, что и попытка объявить мой собственный JwtDecoder bean.

Ответы [ 2 ]

0 голосов
/ 02 ноября 2019

Прочитав о пользовательских валидаторах токенов в документах Spring Security, я добавил специальный валидатор, который проверяет утверждение аудитории, чтобы убедиться, что токен был выдан для моего собственного приложения. Для этого создайте этот класс валидатора:

private static class AudienceValidator implements OAuth2TokenValidator<Jwt> {

    @Override
    public OAuth2TokenValidatorResult validate(Jwt token) {
        if (token.getAudience().contains("my-application-id-here")) {
            return OAuth2TokenValidatorResult.success();
        } else {
            return OAuth2TokenValidatorResult.failure(
                    new OAuth2Error("invalid_token", "The audience is not as expected, got " + token.getAudience(),
                                    null));
        }
    }
}

И используйте его, объявив свой собственный компонент JwtDecoder в своем классе конфигурации WebSecurityConfigurerAdapter:

@Bean
public JwtDecoder jwtDecoder() {
    NimbusJwtDecoder result = NimbusJwtDecoder.withJwkSetUri(properties.getJwt().getJwkSetUri()).build();
    result.setJwtValidator(
            new DelegatingOAuth2TokenValidator<Jwt>(
                   JwtValidators.createDefault(), 
                   new AudienceValidator()) 
            );
    return result;
}

Валидатор по умолчанию будетпроверить такие вещи, как отметка времени. Если все в порядке, AudienceValidator проверит утверждение аудитории.

ПРИМЕЧАНИЕ. Порядок, который вы передаете в валидаторы в DelegatingOAuth2TokenValidator, определяет порядок проверки токена JWT. В приведенном здесь примере отметка времени проверяется перед аудиторией. Если вы хотите сначала проверить аудиторию, сначала поместите ее в конструктор DelegatingOAuth2TokenValidator

0 голосов
/ 31 октября 2019

Я подозреваю, что исключение, которое вы получаете при попытке объявить свой собственный луч JwtDecoder , происходит от косой черты, которая отсутствует.

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

Spring Security удаляет любую косую черту из URI эмитентаперед добавлением, как того требует спецификация. Однако после извлечения конфигурации URI издателя возвращенной конфигурации сопоставляется с «очищенной» версией URI проблемы, а не с изначально предоставленным.

Поскольку fromOidcIssuerLocation () не знает о первоначально предоставленном URL-адресе эмитента, он сопоставляется с cleanedIssuer, что вызывает описанную проблему. Самый простой способ решить эту проблему - выполнить очистку в из функцииOidcIssuerLocation () , которая по-прежнему имеет исходную версию, доступную для сопоставления.

Еще одно примечание, связанное с первым заданным вами вопросом.

Если я знаю идентификатор вашего API + идентификатор вашего арендатора, я могу получить токен доступа для вашего API, используя учетные данные клиента! Маркер не будет содержать области или роли, он не может. Поэтому крайне важно проверить наличие действительных делегированных разрешений (или областей действия) или допустимых разрешений приложений (в утверждении о ролях).

Посмотрите на этот конкретный код.

 JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

        TokenValidationParameters validationParameters = new TokenValidationParameters
        {
            // We accept both the App Id URI and the AppId of this service application
            ValidAudiences = new[] { audience, clientId },

            // Supports both the Azure AD V1 and V2 endpoint
            ValidIssuers = new[] { issuer, $"{issuer}/v2.0" },
            IssuerSigningKeys = signingKeys
        };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...