Аутентификация с помощью oauth / openid в интеграционных тестах - PullRequest
0 голосов
/ 21 апреля 2020

У меня локально возникает следующая ситуация:

  • приложение с загрузочной пружиной, защищенное с помощью Spring Security и OpenID. Приложение настроено на использование потока кода авторизации.
  • keycloak сервер, на котором я могу аутентифицироваться

Теперь я хочу написать несколько интеграционных тестов, и я немного заблокирован.

По умолчанию моя безопасность настроена на сохранение состояния (поэтому я получить идентификатор сеанса cook ie, если я перейду к своему приложению, а не к токену доступа), что не является проблемой, поскольку у меня есть своего рода API-шлюз. И у меня есть следующее:

protected void configure(HttpSecurity http) throws Exception { // @formatter:off
    http.authorizeRequests(authorizeRequests -> authorizeRequests
            .anyRequest()
            .authenticated())
            .oauth2Login(AbstractAuthenticationFilterConfigurer::permitAll)
            .addFilterAfter(new CustomAuthenticationFilter(benutzerRepository), UsernamePasswordAuthenticationFilter.class)
            .logout(logout -> logout.logoutSuccessHandler(oidcLogoutSuccessHandler()));
}  // @formatter:on

И мой application.properties похож на:

spring.security.oauth2.client.registration.keycloak.client-id=application_name
spring.security.oauth2.client.registration.keycloak.client-secret=36a2740b-e7b9-4e66-9e2f-242a19d7815f
spring.security.oauth2.client.registration.keycloak.client-name=Keycloak
spring.security.oauth2.client.registration.keycloak.scope=openid, roles
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
spring.security.oauth2.client.registration.keycloak.redirect-uri={baseUrl}/login/oauth2/code/{registrationId}
spring.security.oauth2.client.provider.keycloak.authorization-uri=http://localhost:8180/auth/realms/application_name/protocol/openid-connect/auth
spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8180/auth/realms/application_name/protocol/openid-connect/token
spring.security.oauth2.client.provider.keycloak.user-info-uri=http://localhost:8180/auth/realms/application_name/protocol/openid-connect/userinfo
spring.security.oauth2.client.provider.keycloak.jwk-set-uri=http://localhost:8180/auth/realms/application_name/protocol/openid-connect/certs
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username

Это работает, но сейчас я хочу написать несколько интеграционных тестов. Так что, в основном, вызывая API из моего весеннего загрузочного приложения в тесте для запуска некоторых операций, и мой API, конечно, защищен.

Итак, что я сделал, так это WebClient, чтобы попытаться получить токен доступа только для ради моих интеграционных тестов, повторяя запросы, которые обычно "магически делаются" в фоновом режиме.

Моя идея состояла в том, чтобы: - вызвать с помощью webclient URL авторизации для получения кода - отправить этот код с идентификатором клиента и секрет клиента для получения токена

Звучит просто, но я просто заблокирован. Я продолжаю получать сообщение об ошибке = invalid_request от KEycloak, и я понятия не имею, почему.

Я просто пытаюсь сделать после начала, чтобы получить код (что, вероятно, неправильно ...):

URIBuilder authorizationURI = new URIBuilder("http://localhost:8180/auth/realms/application_name/protocol/openid-connect/auth");
        authorizationURI.addParameter("client_id", "application_name");
        authorizationURI.addParameter("scope", "openid");
        authorizationURI.addParameter("state", "123456");
        authorizationURI.addParameter("redirect_uri", "http://localhost:8080/login/oauth2/code/keycloak");
        authorizationURI.addParameter("response_type", "code");
        WebClient webclient = WebClient.builder()
                .baseUrl(authorizationURI.toString())
                .build();
        var test = webclient.post()
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .body(
                        BodyInserters.fromFormData("username", "user")
                                .with("password", "password"))
                .exchange()
                .block()
                .bodyToMono(String.class)
                .block();

1 Ответ

0 голосов
/ 21 апреля 2020

Если у кого-то есть такая же проблема, я нашел, как ее исправить.

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

URIBuilder authorizationURI = new URIBuilder("http://localhost:8180/auth/realms/application_name/protocol/openid-connect/token");
        WebClient webclient = WebClient.builder().build();
        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
        formData.put("grant_type", Collections.singletonList("client_credentials"));
        formData.put("client_id", Collections.singletonList("application_name"));
        formData.put("client_secret", Collections.singletonList("tralala-5d0e-4bea-938b-884c1ce4c981"));

И tadaaaa, вы получите токен доступа для ваших тестов.

...