|
|
|
@ -5,16 +5,16 @@ import io.quarkus.security.identity.AuthenticationRequestContext;
|
|
|
|
import io.quarkus.security.identity.IdentityProvider;
|
|
|
|
import io.quarkus.security.identity.IdentityProvider;
|
|
|
|
import io.quarkus.security.identity.SecurityIdentity;
|
|
|
|
import io.quarkus.security.identity.SecurityIdentity;
|
|
|
|
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
|
|
|
|
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
|
|
|
|
|
|
|
|
import io.smallrye.mutiny.Uni;
|
|
|
|
|
|
|
|
import io.smallrye.mutiny.subscription.UniEmitter;
|
|
|
|
import io.vertx.core.http.HttpMethod;
|
|
|
|
import io.vertx.core.http.HttpMethod;
|
|
|
|
import io.vertx.core.logging.Logger;
|
|
|
|
import io.vertx.core.logging.Logger;
|
|
|
|
import io.vertx.core.logging.LoggerFactory;
|
|
|
|
import io.vertx.core.logging.LoggerFactory;
|
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
import java.util.function.Consumer;
|
|
|
|
import java.util.concurrent.CompletionStage;
|
|
|
|
|
|
|
|
import javax.enterprise.context.ApplicationScoped;
|
|
|
|
import javax.enterprise.context.ApplicationScoped;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import org.pagan.janitor.cache.SessionCache;
|
|
|
|
import org.pagan.janitor.cache.SessionCache;
|
|
|
|
import org.pagan.janitor.cache.SessionInfo;
|
|
|
|
import org.pagan.janitor.cache.SessionInfo;
|
|
|
|
//import org.pagan.janitor.security.JanitorPrincipalProducer.NullSessionToken;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @author Edward M. Kagan
|
|
|
|
* @author Edward M. Kagan
|
|
|
|
@ -34,11 +34,14 @@ public class JanitorIdentityProvider implements IdentityProvider<JanitorAuthenti
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public CompletionStage<SecurityIdentity> authenticate(
|
|
|
|
public Uni<SecurityIdentity> authenticate(JanitorAuthenticationRequest request,
|
|
|
|
JanitorAuthenticationRequest request,
|
|
|
|
|
|
|
|
AuthenticationRequestContext context) {
|
|
|
|
AuthenticationRequestContext context) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Uni.createFrom().emitter(new Consumer<UniEmitter<? super SecurityIdentity>>() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void accept(UniEmitter<? super SecurityIdentity> uniEmitter) {
|
|
|
|
if (request.getMethod() == null) {
|
|
|
|
if (request.getMethod() == null) {
|
|
|
|
return anonymous();
|
|
|
|
anonymous(uniEmitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
final HttpMethod method = request.getMethod();
|
|
|
|
final HttpMethod method = request.getMethod();
|
|
|
|
@ -46,24 +49,23 @@ public class JanitorIdentityProvider implements IdentityProvider<JanitorAuthenti
|
|
|
|
final String csrfToken = request.getCsrfToken();
|
|
|
|
final String csrfToken = request.getCsrfToken();
|
|
|
|
final String path = request.getPath();
|
|
|
|
final String path = request.getPath();
|
|
|
|
|
|
|
|
|
|
|
|
if (request.getOrigin() != null && request.getOrigin().length() > 0)
|
|
|
|
if (request.getOrigin() != null && request.getOrigin().length() > 0) {
|
|
|
|
{
|
|
|
|
// request.putHeader("Access-Control-Allow-Origin", request.getOrigin());
|
|
|
|
// request.putHeader("Access-Control-Allow-Origin", request.getOrigin());
|
|
|
|
// request.putHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE, PATCH, HEAD");
|
|
|
|
// request.putHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE, PATCH, HEAD");
|
|
|
|
// request.putHeader("Access-Control-Allow-Credentials", "true");
|
|
|
|
// request.putHeader("Access-Control-Allow-Credentials", "true");
|
|
|
|
// request.putHeader("Access-Control-Max-Age", "1209600");
|
|
|
|
// request.putHeader("Access-Control-Max-Age", "1209600");
|
|
|
|
// request.putHeader("Access-Control-Expose-Headers", "X-CSRF-TOKEN, X-CSRF-ERROR");
|
|
|
|
// request.putHeader("Access-Control-Expose-Headers", "X-CSRF-TOKEN, X-CSRF-ERROR");
|
|
|
|
// request.putHeader("Access-Control-Allow-Headers", "origin, accept, authorization, content-type, x-requested-with, x-csrf-token, x-csrf-error");
|
|
|
|
// request.putHeader("Access-Control-Allow-Headers", "origin, accept, authorization, content-type, x-requested-with, x-csrf-token, x-csrf-error");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (method == HttpMethod.OPTIONS) {
|
|
|
|
if (method == HttpMethod.OPTIONS) {
|
|
|
|
LOG.debug("method = OPTIONS");
|
|
|
|
LOG.debug("method = OPTIONS");
|
|
|
|
return anonymous();
|
|
|
|
anonymous(uniEmitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (sessionId == null) {
|
|
|
|
if (sessionId == null) {
|
|
|
|
LOG.debug("sessionId = null");
|
|
|
|
LOG.debug("sessionId = null");
|
|
|
|
return anonymous();
|
|
|
|
anonymous(uniEmitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SessionInfo sessionInfo = sessionCache.get(sessionId);
|
|
|
|
SessionInfo sessionInfo = sessionCache.get(sessionId);
|
|
|
|
@ -71,42 +73,42 @@ public class JanitorIdentityProvider implements IdentityProvider<JanitorAuthenti
|
|
|
|
|
|
|
|
|
|
|
|
if (sessionInfo == null) {
|
|
|
|
if (sessionInfo == null) {
|
|
|
|
LOG.debug("session info not found in session storage");
|
|
|
|
LOG.debug("session info not found in session storage");
|
|
|
|
return anonymous();
|
|
|
|
anonymous(uniEmitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (method != HttpMethod.GET && method != HttpMethod.HEAD) {
|
|
|
|
if (method != HttpMethod.GET && method != HttpMethod.HEAD) {
|
|
|
|
LOG.debug("path = " + path);
|
|
|
|
LOG.debug("path = " + path);
|
|
|
|
if (!path.equals("/api/auth/") && !path.equals("/api/auth") ) {
|
|
|
|
if (!path.equals("/api/auth/") && !path.equals("/api/auth")) {
|
|
|
|
if (csrfToken == null) {
|
|
|
|
if (csrfToken == null) {
|
|
|
|
LOG.warn("csrfToken is null");
|
|
|
|
LOG.warn("csrfToken is null");
|
|
|
|
return failed();
|
|
|
|
failed(uniEmitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!sessionInfo.csrfToken().equals(csrfToken)) {
|
|
|
|
if (!sessionInfo.csrfToken().equals(csrfToken)) {
|
|
|
|
LOG.error("bad csrfToken");
|
|
|
|
LOG.error("bad csrfToken");
|
|
|
|
return failed();
|
|
|
|
failed(uniEmitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
principal(uniEmitter, sessionInfo);
|
|
|
|
return principal(sessionInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private CompletionStage<SecurityIdentity> anonymous() {
|
|
|
|
private void anonymous(UniEmitter<? super SecurityIdentity> uniEmitter) {
|
|
|
|
return principal(SessionInfo.ANONYMOUS);
|
|
|
|
principal(uniEmitter, SessionInfo.ANONYMOUS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private CompletionStage<SecurityIdentity> principal(SessionInfo sessionInfo) {
|
|
|
|
private void principal(UniEmitter<? super SecurityIdentity> uniEmitter, SessionInfo sessionInfo) {
|
|
|
|
return CompletableFuture.completedFuture(
|
|
|
|
uniEmitter.complete(
|
|
|
|
QuarkusSecurityIdentity.builder().setPrincipal(sessionInfo)
|
|
|
|
QuarkusSecurityIdentity.builder()
|
|
|
|
|
|
|
|
.setPrincipal(sessionInfo)
|
|
|
|
.addRole(sessionInfo.role())
|
|
|
|
.addRole(sessionInfo.role())
|
|
|
|
.build()
|
|
|
|
.build()
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private CompletionStage<SecurityIdentity> failed() {
|
|
|
|
private void failed(UniEmitter<? super SecurityIdentity> uniEmitter) {
|
|
|
|
CompletableFuture<SecurityIdentity> cf = new CompletableFuture<SecurityIdentity>();
|
|
|
|
uniEmitter.fail(new AuthenticationFailedException());
|
|
|
|
cf.completeExceptionally(new AuthenticationFailedException());
|
|
|
|
|
|
|
|
return cf;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|