集成测试因OpenLiberty上的JWT授权而失败

时间:2019-05-20 07:17:52

标签: jwt integration-testing open-liberty

请求使用@RolesAllowed保护的REST端点时,集成测试(生产代码运行良好)失败。 引发以下错误:

[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 with JWT。区别在于UI部分。我的UI基于Angular,因此为了进行身份验证(JWT发行),使用了REST Endpoint:

@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(角度)使用标头https://localhost:5051/tokens调用"Authorization: Basic ENCODED_USERNAME_PASSWORD"
  2. 后端在正文和标头"Set-Cookie: LtpaToken2=SOME_TOKEN; Path=/; HttpOnly"中以新生成的JWT令牌进行响应
  3. UI针对针对带有"@RolesAllowed({"ADMIN", "USER" })"注释的REST端点的所有其他请求使用此令牌。

再一次,在生产代码中,所有这些架构都可以正常工作,但是集成测试失败。

这是集成测试代码:

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的问题是LtpaToken2 Cookie,它在Test中没有设置。而是使用标题"Authorization: Bearer JWT_TOKEN",但这不起作用。

我希望提供头文件"@RolesAllowed"时,受"Authorization: Bearer JWT_TOKEN"保护的端点应以200响应。使用cookie应该有一些技巧吗?

更新2019-05-23

这是整个project。 测试示例位于here。测试失败被忽略

    @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注释方法的后class中创建的:

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

值得注意的是,该项目基于以下project

1 个答案:

答案 0 :(得分:0)

由于发出的CWWKS1652A消息没有提供程序名称,因此这表明已设置appSecurity-3.0,并且已通过注释或bean为该应用程序至少配置了JSR-375(又名Java EE安全API规范)HttpAuthenticationMechanism。实施。这将导致创建一个内部JASPIC提供程序,因此,在CWWKS1652A消息中为null,并且此提供程序调用已配置的HttpAuthenticationMechanism,该方法返回AuthStatus.SEND_FAILURE状态。

请确保您打算使用HttpAuthenticationMechanism,并在受到此机制的挑战时传递有效的身份验证凭据。

如果确定未配置HttpAuthenticationMechanism,则确定是否通过authconfigprovider.factory属性设置了外部JASPIC提供程序工厂(AuthConfigFactory实现)。无论哪种情况,都是提供者响应消息中显示的AuthStatus.SEND_FAILURE。