Интеграционные тесты не пройдены при авторизации JWT в OpenLiberty - PullRequest
0 голосов
/ 20 мая 2019

Интеграционные тесты (рабочий код работает хорошо) не выполняются при запросе конечных точек REST, защищенных с помощью @RolesAllowed.Выдается следующая ошибка:

[5/20/19 8:44:21:363 CEST] 00000109 com.ibm.ws.security.jaspi.JaspiServiceImpl                   I CWWKS1652A: Authentication failed with status AuthStatus.SEND_FAILUR for the web request 
/banking/users/bed6109f-ef8a-47ec-8fa4-e57c71415a10. The user defined Java Authentication SPI for Containers (JASPIC) service null has determined that the authentication data is not valid.

Проект основан на OpenLiberty с JWT .Разница в части пользовательского интерфейса.Мой пользовательский интерфейс основан на Angular, поэтому для аутентификации (выдачи JWT) используется следующая конечная точка REST:

@RequestScoped
@Path("/tokens")
@PermitAll
public class AuthResource {
    @Inject
    private SecurityContext securityContext;
    @Inject
    private AuthService authService;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getJwt() {
        if (securityContext.isCallerInRole("USER") || securityContext.isCallerInRole("ADMIN")) {
            String name = securityContext.getCallerPrincipal().getName();
            AuthPojo authPojo = authService.createJwt(name);

            return Response.ok(authPojo).build();
        }

        return Response.status(Response.Status.UNAUTHORIZED).build();
    }
}

Итак:

  1. UI (Angular) вызывает https://localhost:5051/tokens с заголовком"Authorization: Basic ENCODED_USERNAME_PASSWORD"
  2. Backend отвечает вновь сгенерированным токеном JWT в теле и заголовком "Set-Cookie: LtpaToken2=SOME_TOKEN; Path=/; HttpOnly"
  3. Интерфейс пользователя использует этот токен для всех других запросов к конечным точкам REST, аннотированных "@RolesAllowed({"ADMIN", "USER" })"

Еще раз, в производственном коде вся эта схема работает хорошо, но Интеграционные тесты не проходят.

Вот код Интеграционного теста:

public class MyResourceIT {
    private static final String URL = "https://localhost:" +
        System.getProperty("liberty.test.ssl.port") + "/users/" + USER_ID1;

    private String authHeader;

    @Before
    public void setup() throws Exception {
        authHeader = "Bearer " + new JwtVerifier().createAdminJwt(USER_NAME1);
    }

    @Test
    public void getUserAndAccounts() {
        Response response = HttpClientHelper.processRequest(URL, "GET", null, authHeader);
        System.out.println("My URL: " + URL);
        System.out.println("My Header: " + authHeader);

        assertThat("HTTP GET failed", response.getStatus(), is(Response.Status.OK.getStatusCode()));
    }
}

Похоже, проблема в том, почему вместо 401Возвращается 200 - Cookie LtpaToken2, который не установлен в Test.Вместо этого используется заголовок "Authorization: Bearer JWT_TOKEN", но это не работает.

Я ожидаю, что конечная точка, защищенная "@RolesAllowed", должна ответить 200, если указан заголовок "Authorization: Bearer JWT_TOKEN".Есть ли какие-то хитрости, которые нужно сделать с cookie?

ОБНОВЛЕНИЕ 2019-05-23

Это весь проект .Пример теста находится здесь .Неудачный тест игнорируется

    @Test
    public void getUserAndAccounts_withJwt_authorized() throws IOException {
        Response response = HttpClientHelper.processRequest(URL, "GET", null, authHeader, null);

        assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
    }

Маркер JWT создается в следующем классе в аннотированном методе @Before:

    private String authHeader;
    @Before
    public void setup() throws Exception {
        authHeader = "Bearer " + new JwtVerifier().createAdminJwt(USER_NAME1);
    }

Одна вещь, которую нужно отметить, этот проектоснован на следующем проекте .

1 Ответ

0 голосов
/ 11 июня 2019

Поскольку сообщение CWWKS1652A было выдано без имени провайдера, это означает, что установлен appSecurity-3.0 и что для приложения настроен по крайней мере Jtt-375 (спецификация API безопасности Java EE) HttpAuthenticationMechanism с помощью аннотации или компонента реализация. Это приводит к тому, что создается внутренний поставщик JASPIC, поэтому в сообщении CWWKS1652A содержится значение NULL, и этот поставщик вызывает настроенный механизм HttpAuthenticationMechanism, который возвращает статус AuthStatus.SEND_FAILURE.

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

Если определено, что не настроен HttpAuthenticationMechanism, то определите, существует ли внешняя фабрика провайдера JASPIC (реализация AuthConfigFactory), установленная через свойство authconfigprovider.factory. В любом случае провайдер отвечает сообщением AuthStatus.SEND_FAILURE, показанным в сообщении.

...