Интеграционные тесты (рабочий код работает хорошо) не выполняются при запросе конечных точек 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();
}
}
Итак:
- UI (Angular) вызывает
https://localhost:5051/tokens
с заголовком"Authorization: Basic ENCODED_USERNAME_PASSWORD"
- Backend отвечает вновь сгенерированным токеном JWT в теле и заголовком
"Set-Cookie: LtpaToken2=SOME_TOKEN; Path=/; HttpOnly"
- Интерфейс пользователя использует этот токен для всех других запросов к конечным точкам 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);
}
Одна вещь, которую нужно отметить, этот проектоснован на следующем проекте .