/******************************************************************************* * Copyright (c) 2016, 2020 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ package org.eclipse.hono.service.auth; import static org.assertj.core.api.Assertions.assertThat; import java.net.HttpURLConnection; import org.eclipse.hono.auth.AuthoritiesImpl; import org.eclipse.hono.client.ClientErrorException; import org.eclipse.hono.client.ServerErrorException; import org.eclipse.hono.client.ServiceInvocationException; import org.eclipse.hono.config.SignatureSupportingConfigProperties; import org.eclipse.hono.util.AuthenticationConstants; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExtendWith; import io.vertx.core.Vertx; import io.vertx.core.eventbus.MessageConsumer; import io.vertx.core.json.JsonObject; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; /** * Tests verifying behavior of {@link EventBusAuthenticationService}. */ @ExtendWith(VertxExtension.class) @TestInstance(Lifecycle.PER_CLASS) public class EventBusAuthenticationServiceTest { private static Vertx vertx; private static String secret = "dafhkjsdahfuksahuioahgfqgpsgjkhfdjkg"; private static AuthTokenHelper authTokenHelperForSigning; private static AuthTokenHelper authTokenHelperForValidating; private MessageConsumer<JsonObject> authRequestConsumer; /** * Sets up vert.x. */ @BeforeAll public static void init() { vertx = Vertx.vertx(); final SignatureSupportingConfigProperties props = new SignatureSupportingConfigProperties(); props.setSharedSecret(secret); props.setTokenExpiration(100); authTokenHelperForSigning = AuthTokenHelperImpl.forSigning(vertx, props); authTokenHelperForValidating = AuthTokenHelperImpl.forValidating(vertx, props); } /** * Unregisters the consumer for the authentication requests. */ @AfterEach public void unregisterAuthRequestConsumer() { if (authRequestConsumer != null) { authRequestConsumer.unregister(); } } /** * Verifies that an authentication request is sent via the vert.x event bus and the reply * is passed on to the handler of the <code>authenticate</code> method. * * @param ctx The vert.x test context. */ @Test public void testAuthenticateSuccess(final VertxTestContext ctx) { final String token = createTestToken(); authRequestConsumer = vertx.eventBus().consumer(AuthenticationConstants.EVENT_BUS_ADDRESS_AUTHENTICATION_IN, message -> { message.reply(AuthenticationConstants.getAuthenticationReply(token)); }); final EventBusAuthenticationService eventBusAuthService = new EventBusAuthenticationService(vertx, authTokenHelperForValidating); eventBusAuthService.authenticate(new JsonObject(), ctx.succeeding(t -> { ctx.verify(() -> assertThat(t.getToken()).isEqualTo(token)); ctx.completeNow(); })); } /** * Verifies that the correct exception is given to the handler of the <code>authenticate</code> method in * case no event bus handler is registered for handling authentication requests. * * @param ctx The vert.x test context. */ @Test public void testAuthenticateFailureNoHandler(final VertxTestContext ctx) { final EventBusAuthenticationService eventBusAuthService = new EventBusAuthenticationService(vertx, authTokenHelperForValidating); eventBusAuthService.authenticate(new JsonObject(), ctx.failing(t -> { ctx.verify(() -> { assertThat(t).isInstanceOf(ServerErrorException.class); assertThat(((ServiceInvocationException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_INTERNAL_ERROR); }); ctx.completeNow(); })); } /** * Verifies that an authentication request is sent via the vert.x event bus and the failure reply * is passed on to the handler of the <code>authenticate</code> method. * * @param ctx The vert.x test context. */ @Test public void testAuthenticateFailureValidStatusCode(final VertxTestContext ctx) { final String failureMessage = "failureMessage"; authRequestConsumer = vertx.eventBus().consumer(AuthenticationConstants.EVENT_BUS_ADDRESS_AUTHENTICATION_IN, message -> { message.fail(HttpURLConnection.HTTP_UNAUTHORIZED, failureMessage); }); final EventBusAuthenticationService eventBusAuthService = new EventBusAuthenticationService(vertx, authTokenHelperForValidating); eventBusAuthService.authenticate(new JsonObject(), ctx.failing(t -> { ctx.verify(() -> { assertThat(t).isInstanceOf(ClientErrorException.class); assertThat(((ServiceInvocationException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_UNAUTHORIZED); assertThat(t.getMessage()).isEqualTo(failureMessage); }); ctx.completeNow(); })); } /** * Verifies that an authentication request is sent via the vert.x event bus and the failure reply, * containing an invalid error code, is passed on to the handler of the <code>authenticate</code> method * as an internal error. * * @param ctx The vert.x test context. */ @Test public void testAuthenticateFailureInvalidStatusCode(final VertxTestContext ctx) { final String failureMessage = "failureMessage"; authRequestConsumer = vertx.eventBus().consumer(AuthenticationConstants.EVENT_BUS_ADDRESS_AUTHENTICATION_IN, message -> { message.fail(200, failureMessage); }); final EventBusAuthenticationService eventBusAuthService = new EventBusAuthenticationService(vertx, authTokenHelperForValidating); eventBusAuthService.authenticate(new JsonObject(), ctx.failing(t -> { ctx.verify(() -> { assertThat(t).isInstanceOf(ServerErrorException.class); assertThat(((ServiceInvocationException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_INTERNAL_ERROR); assertThat(t.getMessage()).isEqualTo(failureMessage); }); ctx.completeNow(); })); } private String createTestToken() { return authTokenHelperForSigning.createToken("authId", new AuthoritiesImpl()); } }