Search in sources :

Example 1 with ContextState

use of io.quarkus.arc.InjectableContext.ContextState in project quarkus by quarkusio.

the class WebAuthnController method login.

/**
 * Endpoint for login
 *
 * @param ctx the current request
 */
public void login(RoutingContext ctx) {
    try {
        // might throw runtime exception if there's no json or is bad formed
        final JsonObject webauthnLogin = ctx.getBodyAsJson();
        if (webauthnLogin == null || !containsRequiredString(webauthnLogin, "name")) {
            ctx.fail(400, new IllegalArgumentException("Request missing 'name' field"));
            return;
        }
        // input basic validation is OK
        final String username = webauthnLogin.getString("name");
        ManagedContext requestContext = Arc.container().requestContext();
        requestContext.activate();
        ContextState contextState = requestContext.getState();
        // STEP 18 Generate assertion
        security.getWebAuthn().getCredentialsOptions(username, generateServerGetAssertion -> {
            requestContext.destroy(contextState);
            if (generateServerGetAssertion.failed()) {
                ctx.fail(generateServerGetAssertion.cause());
                return;
            }
            final JsonObject getAssertion = generateServerGetAssertion.result();
            authMech.getLoginManager().save(getAssertion.getString("challenge"), ctx, CHALLENGE_COOKIE, null, ctx.request().isSSL());
            authMech.getLoginManager().save(username, ctx, USERNAME_COOKIE, null, ctx.request().isSSL());
            ok(ctx, getAssertion);
        });
    } catch (IllegalArgumentException e) {
        ctx.fail(400, e);
    } catch (RuntimeException e) {
        ctx.fail(e);
    }
}
Also used : ContextState(io.quarkus.arc.InjectableContext.ContextState) JsonObject(io.vertx.core.json.JsonObject) ManagedContext(io.quarkus.arc.ManagedContext)

Example 2 with ContextState

use of io.quarkus.arc.InjectableContext.ContextState in project quarkus by quarkusio.

the class WebAuthnController method callback.

/**
 * Endpoint for callback
 *
 * @param ctx the current request
 */
public void callback(RoutingContext ctx) {
    try {
        // might throw runtime exception if there's no json or is bad formed
        final JsonObject webauthnResp = ctx.getBodyAsJson();
        // input validation
        if (webauthnResp == null || !containsRequiredString(webauthnResp, "id") || !containsRequiredString(webauthnResp, "rawId") || !containsRequiredObject(webauthnResp, "response") || !containsOptionalString(webauthnResp.getJsonObject("response"), "userHandle") || !containsRequiredString(webauthnResp, "type") || !"public-key".equals(webauthnResp.getString("type"))) {
            ctx.fail(400, new IllegalArgumentException("Response missing one or more of id/rawId/response[.userHandle]/type fields, or type is not public-key"));
            return;
        }
        RestoreResult challenge = authMech.getLoginManager().restore(ctx, CHALLENGE_COOKIE);
        RestoreResult username = authMech.getLoginManager().restore(ctx, USERNAME_COOKIE);
        if (challenge == null || challenge.getPrincipal() == null || challenge.getPrincipal().isEmpty() || username == null || username.getPrincipal() == null || username.getPrincipal().isEmpty()) {
            ctx.fail(400, new IllegalArgumentException("Missing challenge or username"));
            return;
        }
        ManagedContext requestContext = Arc.container().requestContext();
        requestContext.activate();
        ContextState contextState = requestContext.getState();
        // input basic validation is OK
        // authInfo
        WebAuthnCredentials credentials = new WebAuthnCredentials().setOrigin(origin).setDomain(domain).setChallenge(challenge.getPrincipal()).setUsername(username.getPrincipal()).setWebauthn(webauthnResp);
        identityProviderManager.authenticate(HttpSecurityUtils.setRoutingContextAttribute(new WebAuthnAuthenticationRequest(credentials), ctx)).subscribe().with(new Consumer<SecurityIdentity>() {

            @Override
            public void accept(SecurityIdentity identity) {
                requestContext.destroy(contextState);
                // invalidate the challenge
                WebAuthnSecurity.removeCookie(ctx, WebAuthnController.CHALLENGE_COOKIE);
                WebAuthnSecurity.removeCookie(ctx, WebAuthnController.USERNAME_COOKIE);
                try {
                    authMech.getLoginManager().save(identity, ctx, null, ctx.request().isSSL());
                    ok(ctx);
                } catch (Throwable t) {
                    log.error("Unable to complete post authentication", t);
                    ctx.fail(t);
                }
            }
        }, new Consumer<Throwable>() {

            @Override
            public void accept(Throwable throwable) {
                requestContext.terminate();
                if (throwable instanceof AttestationException) {
                    ctx.fail(400, throwable);
                } else {
                    ctx.fail(throwable);
                }
            }
        });
    } catch (IllegalArgumentException e) {
        ctx.fail(400, e);
    } catch (RuntimeException e) {
        ctx.fail(e);
    }
}
Also used : AttestationException(io.vertx.ext.auth.webauthn.impl.attestation.AttestationException) RestoreResult(io.quarkus.vertx.http.runtime.security.PersistentLoginManager.RestoreResult) JsonObject(io.vertx.core.json.JsonObject) SecurityIdentity(io.quarkus.security.identity.SecurityIdentity) WebAuthnCredentials(io.vertx.ext.auth.webauthn.WebAuthnCredentials) ContextState(io.quarkus.arc.InjectableContext.ContextState) ManagedContext(io.quarkus.arc.ManagedContext)

Example 3 with ContextState

use of io.quarkus.arc.InjectableContext.ContextState in project quarkus by quarkusio.

the class RequestContextPropagationTest method testPropagation.

@Test
public void testPropagation() {
    ArcContainer arc = Arc.container();
    ManagedContext requestContext = arc.requestContext();
    try {
        arc.instance(SuperController.class).get().getId();
        fail();
    } catch (ContextNotActiveException expected) {
    }
    requestContext.activate();
    assertFalse(SuperController.DESTROYED.get());
    SuperController controller1 = arc.instance(SuperController.class).get();
    SuperController controller2 = arc.instance(SuperController.class).get();
    String controller2Id = controller2.getId();
    assertEquals(controller1.getId(), controller2Id);
    assertNotNull(controller2.getButton());
    assertTrue(controller2.getButton() == controller1.getButton());
    // Store existing instances
    ContextState state = requestContext.getState();
    // Deactivate but don't destroy
    requestContext.deactivate();
    assertFalse(SuperController.DESTROYED.get());
    assertFalse(SuperButton.DESTROYED.get());
    try {
        // Proxy should not work
        controller1.getId();
        fail();
    } catch (ContextNotActiveException expected) {
    }
    requestContext.activate(state);
    assertEquals(arc.instance(SuperController.class).get().getId(), controller2Id);
    // add req. scoped bean, note that we have already captured the state prior to this
    // we do this to prove that even after capture, newly added beans still get to be propagated
    YetAnotherReqScopedBean yetAnotherReqScopedBean = arc.instance(YetAnotherReqScopedBean.class).get();
    int generatedNumber = yetAnotherReqScopedBean.getRandomNumber();
    // end the context and re-start with originally stored state and assume the bean is part of it
    requestContext.deactivate();
    requestContext.activate(state);
    // check that the bean is not created anew - that means the contextual storage was shared between activations
    assertEquals(arc.instance(YetAnotherReqScopedBean.class).get().getRandomNumber(), generatedNumber);
    requestContext.terminate();
    assertTrue(SuperController.DESTROYED.get());
    assertTrue(SuperButton.DESTROYED.get());
}
Also used : ArcContainer(io.quarkus.arc.ArcContainer) ContextNotActiveException(javax.enterprise.context.ContextNotActiveException) ContextState(io.quarkus.arc.InjectableContext.ContextState) ManagedContext(io.quarkus.arc.ManagedContext) Test(org.junit.jupiter.api.Test)

Example 4 with ContextState

use of io.quarkus.arc.InjectableContext.ContextState in project quarkus by quarkusio.

the class RouteHandler method handle.

@Override
public void handle(RoutingContext context) {
    QuarkusHttpUser user = (QuarkusHttpUser) context.user();
    // todo: how should we handle non-proactive authentication here?
    if (requestContext.isActive()) {
        if (currentIdentityAssociation != null) {
            if (user != null) {
                SecurityIdentity identity = user.getSecurityIdentity();
                currentIdentityAssociation.setIdentity(identity);
            } else {
                currentIdentityAssociation.setIdentity(QuarkusHttpUser.getSecurityIdentity(context, null));
            }
        }
        if (user != null) {
            securityIdentityEvent.fire(user.getSecurityIdentity());
        }
        invoke(context);
    } else {
        try {
            // First attempt to obtain the request context state.
            // If there is a route filter and the request can have body (POST, PUT, etc.) the route
            // method is invoked asynchronously (once all data are read).
            // However, the request context is activated by the filter and we need to make sure
            // the same context is then used in the route method
            ContextState state = context.get(REQUEST_CONTEXT_STATE);
            // Activate the context, i.e. set the thread locals, state can be null
            requestContext.activate(state);
            currentVertxRequest.setCurrent(context);
            if (currentIdentityAssociation != null) {
                if (user != null) {
                    SecurityIdentity identity = user.getSecurityIdentity();
                    currentIdentityAssociation.setIdentity(identity);
                } else {
                    currentIdentityAssociation.setIdentity(QuarkusHttpUser.getSecurityIdentity(context, null));
                }
            }
            if (user != null) {
                securityIdentityEvent.fire(user.getSecurityIdentity());
            }
            if (state == null) {
                // Reactive routes can use async processing (e.g. mutiny Uni/Multi) and context propagation
                // 1. Store the state (which is basically a shared Map instance)
                // 2. Terminate the context correctly when the response is disposed or an exception is thrown
                final ContextState endState = requestContext.getState();
                context.put(REQUEST_CONTEXT_STATE, endState);
                context.addEndHandler(new Handler<AsyncResult<Void>>() {

                    @Override
                    public void handle(AsyncResult<Void> result) {
                        requestContext.destroy(endState);
                    }
                });
            }
            invoke(context);
        } finally {
            // Deactivate the context, i.e. cleanup the thread locals
            requestContext.deactivate();
        }
    }
}
Also used : SecurityIdentity(io.quarkus.security.identity.SecurityIdentity) ContextState(io.quarkus.arc.InjectableContext.ContextState) QuarkusHttpUser(io.quarkus.vertx.http.runtime.security.QuarkusHttpUser) AsyncResult(io.vertx.core.AsyncResult)

Example 5 with ContextState

use of io.quarkus.arc.InjectableContext.ContextState in project quarkus by vaadin.

the class InjectableContextTest method getState_beanExistsInContext_contextualInstanceAndBeanAreReturned.

@Test
public void getState_beanExistsInContext_contextualInstanceAndBeanAreReturned() {
    createContext().activate();
    TestBean reference = context.get(contextual, creationalContext);
    reference.setState("hello");
    ContextState state = context.getState();
    Map<InjectableBean<?>, Object> instances = state.getContextualInstances();
    assertNotNull(instances);
    assertSame(reference, instances.get(contextual));
}
Also used : ContextState(io.quarkus.arc.InjectableContext.ContextState) InjectableBean(io.quarkus.arc.InjectableBean) Test(org.junit.jupiter.api.Test)

Aggregations

ContextState (io.quarkus.arc.InjectableContext.ContextState)8 ManagedContext (io.quarkus.arc.ManagedContext)6 JsonObject (io.vertx.core.json.JsonObject)3 SecurityIdentity (io.quarkus.security.identity.SecurityIdentity)2 AsyncResult (io.vertx.core.AsyncResult)2 Test (org.junit.jupiter.api.Test)2 ServerCall (io.grpc.ServerCall)1 ArcContainer (io.quarkus.arc.ArcContainer)1 InjectableBean (io.quarkus.arc.InjectableBean)1 RestoreResult (io.quarkus.vertx.http.runtime.security.PersistentLoginManager.RestoreResult)1 QuarkusHttpUser (io.quarkus.vertx.http.runtime.security.QuarkusHttpUser)1 Promise (io.vertx.core.Promise)1 WebAuthnCredentials (io.vertx.ext.auth.webauthn.WebAuthnCredentials)1 AttestationException (io.vertx.ext.auth.webauthn.impl.attestation.AttestationException)1 CompletionStage (java.util.concurrent.CompletionStage)1 ContextNotActiveException (javax.enterprise.context.ContextNotActiveException)1