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);
}
}
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);
}
}
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());
}
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();
}
}
}
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));
}
Aggregations