Integration Tests (production code works well) fail while requesting REST endpoints secured with @RolesAllowed. Following error is thrown:
[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.
Project is based on OpenLiberty with JWT. The difference is in the UI part. My UI is based on Angular, so for authentication (JWT issuing) following REST Endpoint is used:
@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();
}
}
So:
- UI (Angular) calls
https://localhost:5051/tokens
with Header"Authorization: Basic ENCODED_USERNAME_PASSWORD"
- Backend responds with newly generated JWT Token in body and Header
"Set-Cookie: LtpaToken2=SOME_TOKEN; Path=/; HttpOnly"
- UI uses this token for all other requests against REST Endpoints annotated with
"@RolesAllowed({"ADMIN", "USER" })"
Once again, in production code, all this schema works well, but Integration Tests fail.
Here is Integration Test code:
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()));
}
}
Looks like the problem why 401 instead 200 is returned is LtpaToken2 Cookie which is not set in Test. Instead Header "Authorization: Bearer JWT_TOKEN"
is used, but this doesn't work.
I Expect that Endpoint secured with "@RolesAllowed"
should respond with 200 when header "Authorization: Bearer JWT_TOKEN"
is provided. Are there some tricks that should be done with a cookie?
UPDATE 2019-05-23
This is the whole project. Example test is located here. The failing test is ignored
@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 token is created within following class in the @Before annotated method:
private String authHeader;
@Before
public void setup() throws Exception {
authHeader = "Bearer " + new JwtVerifier().createAdminJwt(USER_NAME1);
}
One thing to notice, that project is based on the following project.