Removing references to request and response from Resteasy
Closes #15374
This commit is contained in:
parent
8e6437e596
commit
168734b817
105 changed files with 677 additions and 293 deletions
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.examples.authenticator;
|
package org.keycloak.examples.authenticator;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||||
import org.keycloak.authentication.AuthenticationFlowError;
|
import org.keycloak.authentication.AuthenticationFlowError;
|
||||||
import org.keycloak.authentication.Authenticator;
|
import org.keycloak.authentication.Authenticator;
|
||||||
|
@ -96,11 +96,11 @@ public class SecretQuestionAuthenticator implements Authenticator, CredentialVal
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCookie(AuthenticationFlowContext context, String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
|
public void addCookie(AuthenticationFlowContext context, String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
|
||||||
HttpResponse response = context.getSession().getContext().getContextObject(HttpResponse.class);
|
HttpResponse response = context.getSession().getContext().getHttpResponse();
|
||||||
StringBuffer cookieBuf = new StringBuffer();
|
StringBuffer cookieBuf = new StringBuffer();
|
||||||
ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, comment, maxAge, secure, httpOnly, null);
|
ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, comment, maxAge, secure, httpOnly, null);
|
||||||
String cookie = cookieBuf.toString();
|
String cookie = cookieBuf.toString();
|
||||||
response.getOutputHeaders().add(HttpHeaders.SET_COOKIE, cookie);
|
response.addHeader(HttpHeaders.SET_COOKIE, cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.connections.jpa;
|
package org.keycloak.connections.jpa;
|
||||||
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
|
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
|
|
@ -66,6 +66,7 @@ import org.keycloak.vault.VaultTranscriber;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@ -199,6 +200,11 @@ public class ImportKeycloakSession implements KeycloakSession {
|
||||||
session.setAttribute(name, value);
|
session.setAttribute(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getAttributes() {
|
||||||
|
return session.getAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidate(InvalidationHandler.InvalidableObjectType type, Object... ids) {
|
public void invalidate(InvalidationHandler.InvalidableObjectType type, Object... ids) {
|
||||||
// For now, forward the invalidations only to those providers created specifically for this import session.
|
// For now, forward the invalidations only to those providers created specifically for this import session.
|
||||||
|
|
|
@ -30,7 +30,6 @@ import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.common.util.Resteasy;
|
import org.keycloak.common.util.Resteasy;
|
||||||
import org.keycloak.config.HostnameOptions;
|
import org.keycloak.config.HostnameOptions;
|
||||||
|
@ -295,7 +294,7 @@ public final class DefaultHostnameProvider implements HostnameProvider, Hostname
|
||||||
|
|
||||||
private int getRequestPort() {
|
private int getRequestPort() {
|
||||||
KeycloakSession session = Resteasy.getContextData(KeycloakSession.class);
|
KeycloakSession session = Resteasy.getContextData(KeycloakSession.class);
|
||||||
return session.getContext().getContextObject(HttpRequest.class).getUri().getBaseUri().getPort();
|
return session.getContext().getHttpRequest().getUri().getBaseUri().getPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T fromBaseUriOrDefault(Function<URI, T> resolver, URI baseUri, T defaultValue) {
|
private <T> T fromBaseUriOrDefault(Function<URI, T> resolver, URI baseUri, T defaultValue) {
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.quarkus.runtime.integration;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import javax.enterprise.inject.Instance;
|
||||||
|
import javax.enterprise.inject.spi.CDI;
|
||||||
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
|
import org.keycloak.services.HttpRequestImpl;
|
||||||
|
|
||||||
|
import io.vertx.ext.web.RoutingContext;
|
||||||
|
|
||||||
|
public class QuarkusHttpRequest extends HttpRequestImpl {
|
||||||
|
|
||||||
|
public <R> QuarkusHttpRequest(HttpRequest delegate) {
|
||||||
|
super(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate[] getClientCertificateChain() {
|
||||||
|
Instance<RoutingContext> instances = CDI.current().select(RoutingContext.class);
|
||||||
|
|
||||||
|
if (instances.isResolvable()) {
|
||||||
|
RoutingContext context = instances.get();
|
||||||
|
|
||||||
|
try {
|
||||||
|
SSLSession sslSession = context.request().sslSession();
|
||||||
|
|
||||||
|
if (sslSession == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (X509Certificate[]) sslSession.getPeerCertificates();
|
||||||
|
} catch (SSLPeerUnverifiedException ignore) {
|
||||||
|
// client not authenticated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.quarkus.runtime.integration;
|
||||||
|
|
||||||
|
import org.keycloak.common.util.Resteasy;
|
||||||
|
import org.keycloak.http.HttpRequest;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.services.DefaultKeycloakContext;
|
||||||
|
|
||||||
|
public class QuarkusKeycloakContext extends DefaultKeycloakContext {
|
||||||
|
|
||||||
|
public QuarkusKeycloakContext(KeycloakSession session) {
|
||||||
|
super(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpRequest createHttpRequest() {
|
||||||
|
return new QuarkusHttpRequest(Resteasy.getContextData(org.jboss.resteasy.spi.HttpRequest.class));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.quarkus.runtime.integration;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.services.DefaultKeycloakContext;
|
||||||
|
import org.keycloak.services.DefaultKeycloakSession;
|
||||||
|
import org.keycloak.services.DefaultKeycloakSessionFactory;
|
||||||
|
|
||||||
|
public class QuarkusKeycloakSession extends DefaultKeycloakSession {
|
||||||
|
|
||||||
|
public QuarkusKeycloakSession(DefaultKeycloakSessionFactory factory) {
|
||||||
|
super(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DefaultKeycloakContext createKeycloakContext(KeycloakSession session) {
|
||||||
|
return new QuarkusKeycloakContext(session);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
import org.keycloak.provider.ProviderManagerRegistry;
|
import org.keycloak.provider.ProviderManagerRegistry;
|
||||||
|
@ -122,4 +123,9 @@ public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionF
|
||||||
|
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeycloakSession create() {
|
||||||
|
return new QuarkusKeycloakSession(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,10 @@ package org.keycloak.quarkus.runtime.integration.web;
|
||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
import javax.enterprise.inject.Instance;
|
|
||||||
import javax.enterprise.inject.spi.CDI;
|
|
||||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
|
||||||
import javax.net.ssl.SSLSession;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.services.x509.X509ClientCertificateLookup;
|
import org.keycloak.services.x509.X509ClientCertificateLookup;
|
||||||
|
|
||||||
import io.vertx.ext.web.RoutingContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
|
@ -47,32 +40,14 @@ public class VertxClientCertificateLookup implements X509ClientCertificateLookup
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public X509Certificate[] getCertificateChain(HttpRequest httpRequest) {
|
public X509Certificate[] getCertificateChain(HttpRequest httpRequest) {
|
||||||
Instance<RoutingContext> instances = CDI.current().select(RoutingContext.class);
|
X509Certificate[] certificates = httpRequest.getClientCertificateChain();
|
||||||
|
|
||||||
if (instances.isResolvable()) {
|
if (logger.isTraceEnabled() && certificates != null) {
|
||||||
RoutingContext context = instances.get();
|
for (X509Certificate cert : certificates) {
|
||||||
|
logger.tracef("Certificate's SubjectDN => \"%s\"", cert.getSubjectDN().getName());
|
||||||
try {
|
|
||||||
SSLSession sslSession = context.request().sslSession();
|
|
||||||
|
|
||||||
if (sslSession == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
X509Certificate[] certificates = (X509Certificate[]) sslSession.getPeerCertificates();
|
|
||||||
|
|
||||||
if (logger.isTraceEnabled() && certificates != null) {
|
|
||||||
for (X509Certificate cert : certificates) {
|
|
||||||
logger.tracef("Certificate's SubjectDN => \"%s\"", cert.getSubjectDN().getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return certificates;
|
|
||||||
} catch (SSLPeerUnverifiedException ignore) {
|
|
||||||
// client not authenticated
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return certificates;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,13 @@
|
||||||
package org.keycloak.quarkus.runtime.services.resources;
|
package org.keycloak.quarkus.runtime.services.resources;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.common.Version;
|
import org.keycloak.common.Version;
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.common.util.MimeTypeUtil;
|
import org.keycloak.common.util.MimeTypeUtil;
|
||||||
import org.keycloak.common.util.SecretGenerator;
|
import org.keycloak.common.util.SecretGenerator;
|
||||||
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.quarkus.runtime.configuration.Configuration;
|
import org.keycloak.quarkus.runtime.configuration.Configuration;
|
||||||
import org.keycloak.services.ForbiddenException;
|
import org.keycloak.services.ForbiddenException;
|
||||||
|
@ -71,12 +71,6 @@ public class QuarkusWelcomeResource {
|
||||||
|
|
||||||
private AtomicBoolean shouldBootstrap;
|
private AtomicBoolean shouldBootstrap;
|
||||||
|
|
||||||
@Context
|
|
||||||
HttpHeaders headers;
|
|
||||||
|
|
||||||
@Context
|
|
||||||
HttpRequest request;
|
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
KeycloakSession session;
|
KeycloakSession session;
|
||||||
|
|
||||||
|
@ -98,6 +92,7 @@ public class QuarkusWelcomeResource {
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Produces(MediaType.TEXT_HTML_UTF_8)
|
@Produces(MediaType.TEXT_HTML_UTF_8)
|
||||||
public Response createUser() {
|
public Response createUser() {
|
||||||
|
HttpRequest request = session.getContext().getHttpRequest();
|
||||||
MultivaluedMap<String, String> formData = request.getDecodedFormParameters();
|
MultivaluedMap<String, String> formData = request.getDecodedFormParameters();
|
||||||
|
|
||||||
if (!shouldBootstrap()) {
|
if (!shouldBootstrap()) {
|
||||||
|
@ -254,6 +249,8 @@ public class QuarkusWelcomeResource {
|
||||||
ClientConnection clientConnection = session.getContext().getConnection();
|
ClientConnection clientConnection = session.getContext().getConnection();
|
||||||
InetAddress remoteInetAddress = InetAddress.getByName(clientConnection.getRemoteAddr());
|
InetAddress remoteInetAddress = InetAddress.getByName(clientConnection.getRemoteAddr());
|
||||||
InetAddress localInetAddress = InetAddress.getByName(clientConnection.getLocalAddr());
|
InetAddress localInetAddress = InetAddress.getByName(clientConnection.getLocalAddr());
|
||||||
|
HttpRequest request = session.getContext().getHttpRequest();
|
||||||
|
HttpHeaders headers = request.getHttpHeaders();
|
||||||
String xForwardedFor = headers.getHeaderString("X-Forwarded-For");
|
String xForwardedFor = headers.getHeaderString("X-Forwarded-For");
|
||||||
logger.debugf("Checking WelcomePage. Remote address: %s, Local address: %s, X-Forwarded-For header: %s", remoteInetAddress.toString(), localInetAddress.toString(), xForwardedFor);
|
logger.debugf("Checking WelcomePage. Remote address: %s, Local address: %s, X-Forwarded-For header: %s", remoteInetAddress.toString(), localInetAddress.toString(), xForwardedFor);
|
||||||
|
|
||||||
|
@ -273,18 +270,20 @@ public class QuarkusWelcomeResource {
|
||||||
String stateChecker = Base64Url.encode(SecretGenerator.getInstance().randomBytes());
|
String stateChecker = Base64Url.encode(SecretGenerator.getInstance().randomBytes());
|
||||||
String cookiePath = session.getContext().getUri().getPath();
|
String cookiePath = session.getContext().getUri().getPath();
|
||||||
boolean secureOnly = session.getContext().getUri().getRequestUri().getScheme().equalsIgnoreCase("https");
|
boolean secureOnly = session.getContext().getUri().getRequestUri().getScheme().equalsIgnoreCase("https");
|
||||||
CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, stateChecker, cookiePath, null, null, 300, secureOnly, true);
|
CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, stateChecker, cookiePath, null, null, 300, secureOnly, true, session);
|
||||||
return stateChecker;
|
return stateChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expireCsrfCookie() {
|
private void expireCsrfCookie() {
|
||||||
String cookiePath = session.getContext().getUri().getPath();
|
String cookiePath = session.getContext().getUri().getPath();
|
||||||
boolean secureOnly = session.getContext().getUri().getRequestUri().getScheme().equalsIgnoreCase("https");
|
boolean secureOnly = session.getContext().getUri().getRequestUri().getScheme().equalsIgnoreCase("https");
|
||||||
CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, "", cookiePath, null, null, 0, secureOnly, true);
|
CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, "", cookiePath, null, null, 0, secureOnly, true, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void csrfCheck(final MultivaluedMap<String, String> formData) {
|
private void csrfCheck(final MultivaluedMap<String, String> formData) {
|
||||||
String formStateChecker = formData.getFirst("stateChecker");
|
String formStateChecker = formData.getFirst("stateChecker");
|
||||||
|
HttpRequest request = session.getContext().getHttpRequest();
|
||||||
|
HttpHeaders headers = request.getHttpHeaders();
|
||||||
Cookie cookie = headers.getCookies().get(KEYCLOAK_STATE_CHECKER);
|
Cookie cookie = headers.getCookies().get(KEYCLOAK_STATE_CHECKER);
|
||||||
if (cookie == null) {
|
if (cookie == null) {
|
||||||
throw new ForbiddenException();
|
throw new ForbiddenException();
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.models.AuthenticationExecutionModel;
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.models.AuthenticationExecutionModel;
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.forms.login.LoginFormsProvider;
|
import org.keycloak.forms.login.LoginFormsProvider;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.broker.provider;
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.broker.provider.util.IdentityBrokerState;
|
import org.keycloak.broker.provider.util.IdentityBrokerState;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
|
70
server-spi/src/main/java/org/keycloak/http/HttpRequest.java
Normal file
70
server-spi/src/main/java/org/keycloak/http/HttpRequest.java
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.http;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import org.keycloak.models.KeycloakContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Represents an incoming HTTP request.
|
||||||
|
*
|
||||||
|
* <p>Instances of this class can be obtained from {@link KeycloakContext#getHttpRequest()}.
|
||||||
|
*/
|
||||||
|
public interface HttpRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HTTP method.
|
||||||
|
*
|
||||||
|
* @return the HTTP method.
|
||||||
|
*/
|
||||||
|
String getHttpMethod();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns the form parameters (e.g.: media type {@code application/x-www-form-urlencoded}) as a {@link MultivaluedMap} where the key and its correspondent value maps to the parameter name and
|
||||||
|
* value, respectively.
|
||||||
|
*
|
||||||
|
* <p>The values are already decoded using HTML form decoding.
|
||||||
|
*
|
||||||
|
* @return the decoded form parameters
|
||||||
|
*/
|
||||||
|
MultivaluedMap<String, String> getDecodedFormParameters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HTTP headers.
|
||||||
|
*
|
||||||
|
* @return the HTTP headers
|
||||||
|
*/
|
||||||
|
HttpHeaders getHttpHeaders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the client X509 certificate chain when processing TLS requests.
|
||||||
|
*
|
||||||
|
* @return the client certificate chain
|
||||||
|
*/
|
||||||
|
X509Certificate[] getClientCertificateChain();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link UriInfo} instance for the path being requested.
|
||||||
|
*
|
||||||
|
* @return the {@link UriInfo} for the current path
|
||||||
|
*/
|
||||||
|
UriInfo getUri();
|
||||||
|
}
|
48
server-spi/src/main/java/org/keycloak/http/HttpResponse.java
Normal file
48
server-spi/src/main/java/org/keycloak/http/HttpResponse.java
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.http;
|
||||||
|
/**
|
||||||
|
* <p>Represents an out coming HTTP response.
|
||||||
|
*
|
||||||
|
* <p>Instances of this class can be obtained from {@link org.keycloak.models.KeycloakContext#getHttpResponse}.
|
||||||
|
*/
|
||||||
|
public interface HttpResponse {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a status code.
|
||||||
|
*
|
||||||
|
* @param statusCode the status code
|
||||||
|
*/
|
||||||
|
void setStatus(int statusCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a value to the current list of values for the header with the given {@code name}.
|
||||||
|
*
|
||||||
|
* @param name the header name
|
||||||
|
* @param value the header value
|
||||||
|
*/
|
||||||
|
void addHeader(String name, String value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a header. Any existing values will be replaced.
|
||||||
|
*
|
||||||
|
* @param name the header name
|
||||||
|
* @param value the header value
|
||||||
|
*/
|
||||||
|
void setHeader(String name, String value);
|
||||||
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
package org.keycloak.models;
|
package org.keycloak.models;
|
||||||
|
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
|
import org.keycloak.http.HttpRequest;
|
||||||
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||||
import org.keycloak.urls.UrlType;
|
import org.keycloak.urls.UrlType;
|
||||||
|
|
||||||
|
@ -75,4 +77,8 @@ public interface KeycloakContext {
|
||||||
AuthenticationSessionModel getAuthenticationSession();
|
AuthenticationSessionModel getAuthenticationSession();
|
||||||
|
|
||||||
void setAuthenticationSession(AuthenticationSessionModel authenticationSession);
|
void setAuthenticationSession(AuthenticationSessionModel authenticationSession);
|
||||||
|
|
||||||
|
HttpRequest getHttpRequest();
|
||||||
|
|
||||||
|
HttpResponse getHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.keycloak.services.clientpolicy.ClientPolicyManager;
|
||||||
import org.keycloak.sessions.AuthenticationSessionProvider;
|
import org.keycloak.sessions.AuthenticationSessionProvider;
|
||||||
import org.keycloak.vault.VaultTranscriber;
|
import org.keycloak.vault.VaultTranscriber;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@ -123,6 +124,8 @@ public interface KeycloakSession {
|
||||||
Object removeAttribute(String attribute);
|
Object removeAttribute(String attribute);
|
||||||
void setAttribute(String name, Object value);
|
void setAttribute(String name, Object value);
|
||||||
|
|
||||||
|
Map<String, Object> getAttributes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidates intermediate states of the given objects, both immediately and at the end of this session.
|
* Invalidates intermediate states of the given objects, both immediately and at the end of this session.
|
||||||
* @param type Type of the objects to invalidate
|
* @param type Type of the objects to invalidate
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
|
import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
|
||||||
import org.keycloak.authentication.authenticators.client.ClientAuthUtil;
|
import org.keycloak.authentication.authenticators.client.ClientAuthUtil;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
|
@ -795,7 +795,7 @@ public class AuthenticationProcessor {
|
||||||
.setSession(session)
|
.setSession(session)
|
||||||
.setUriInfo(uriInfo)
|
.setUriInfo(uriInfo)
|
||||||
.setRequest(request);
|
.setRequest(request);
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
return processor.authenticate();
|
return processor.authenticate();
|
||||||
|
|
||||||
} else if (e.getError() == AuthenticationFlowError.DISPLAY_NOT_SUPPORTED) {
|
} else if (e.getError() == AuthenticationFlowError.DISPLAY_NOT_SUPPORTED) {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.OAuth2Constants;
|
|
||||||
import org.keycloak.authentication.authenticators.conditional.ConditionalAuthenticator;
|
import org.keycloak.authentication.authenticators.conditional.ConditionalAuthenticator;
|
||||||
import org.keycloak.models.AuthenticationExecutionModel;
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
import org.keycloak.models.AuthenticationFlowModel;
|
import org.keycloak.models.AuthenticationFlowModel;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.forms.login.LoginFormsProvider;
|
import org.keycloak.forms.login.LoginFormsProvider;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
|
|
@ -30,7 +30,7 @@ import org.keycloak.sessions.AuthenticationSessionModel;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriBuilderException;
|
import javax.ws.rs.core.UriBuilderException;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -49,7 +49,7 @@ import java.util.Map;
|
||||||
* <li>{@code user} the current {@link UserModel}</li>
|
* <li>{@code user} the current {@link UserModel}</li>
|
||||||
* <li>{@code session} the active {@link KeycloakSession}</li>
|
* <li>{@code session} the active {@link KeycloakSession}</li>
|
||||||
* <li>{@code authenticationSession} the current {@link org.keycloak.sessions.AuthenticationSessionModel}</li>
|
* <li>{@code authenticationSession} the current {@link org.keycloak.sessions.AuthenticationSessionModel}</li>
|
||||||
* <li>{@code httpRequest} the current {@link org.jboss.resteasy.spi.HttpRequest}</li>
|
* <li>{@code httpRequest} the current {@link org.keycloak.http.HttpRequest}</li>
|
||||||
* <li>{@code LOG} a {@link org.jboss.logging.Logger} scoped to {@link ScriptBasedAuthenticator}/li>
|
* <li>{@code LOG} a {@link org.jboss.logging.Logger} scoped to {@link ScriptBasedAuthenticator}/li>
|
||||||
* </ol>
|
* </ol>
|
||||||
* </p>
|
* </p>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.keycloak.authentication.authenticators.browser;
|
package org.keycloak.authentication.authenticators.browser;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||||
import org.keycloak.authentication.AuthenticationFlowError;
|
import org.keycloak.authentication.AuthenticationFlowError;
|
||||||
import org.keycloak.authentication.Authenticator;
|
import org.keycloak.authentication.Authenticator;
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package org.keycloak.authentication.authenticators.browser;
|
package org.keycloak.authentication.authenticators.browser;
|
||||||
|
|
||||||
import com.webauthn4j.data.AuthenticationParameters;
|
|
||||||
import com.webauthn4j.data.AuthenticationRequest;
|
import com.webauthn4j.data.AuthenticationRequest;
|
||||||
import com.webauthn4j.data.client.Origin;
|
import com.webauthn4j.data.client.Origin;
|
||||||
import com.webauthn4j.data.client.challenge.Challenge;
|
import com.webauthn4j.data.client.challenge.Challenge;
|
||||||
|
|
|
@ -20,7 +20,7 @@ import javax.ws.rs.HttpMethod;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||||
import org.keycloak.authentication.Authenticator;
|
import org.keycloak.authentication.Authenticator;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.authentication.authenticators.client;
|
package org.keycloak.authentication.authenticators.client;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.authentication.ClientAuthenticator;
|
import org.keycloak.authentication.ClientAuthenticator;
|
||||||
import org.keycloak.authentication.ClientAuthenticatorFactory;
|
import org.keycloak.authentication.ClientAuthenticatorFactory;
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
package org.keycloak.authentication.authenticators.x509;
|
package org.keycloak.authentication.authenticators.x509;
|
||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import javax.ws.rs.core.MultivaluedHashMap;
|
import javax.ws.rs.core.MultivaluedHashMap;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
@ -232,10 +232,9 @@ public class X509ClientCertificateAuthenticator extends AbstractX509ClientCertif
|
||||||
|
|
||||||
private void dumpContainerAttributes(AuthenticationFlowContext context) {
|
private void dumpContainerAttributes(AuthenticationFlowContext context) {
|
||||||
|
|
||||||
Enumeration<String> attributeNames = context.getHttpRequest().getAttributeNames();
|
Map<String, Object> attributeNames = context.getSession().getAttributes();
|
||||||
while(attributeNames.hasMoreElements()) {
|
for (String name : attributeNames.keySet()) {
|
||||||
String a = attributeNames.nextElement();
|
logger.tracef("[X509ClientCertificateAuthenticator:dumpContainerAttributes] \"%s\"", name);
|
||||||
logger.tracef("[X509ClientCertificateAuthenticator:dumpContainerAttributes] \"%s\"", a);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,8 @@ import org.keycloak.credential.CredentialProvider;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.PasswordPolicy;
|
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.credential.RecoveryAuthnCodesCredentialModel;
|
import org.keycloak.models.credential.RecoveryAuthnCodesCredentialModel;
|
||||||
import org.keycloak.models.utils.RecoveryAuthnCodesUtils;
|
|
||||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
|
|
@ -32,7 +32,7 @@ import javax.ws.rs.core.Response;
|
||||||
import com.webauthn4j.WebAuthnRegistrationManager;
|
import com.webauthn4j.WebAuthnRegistrationManager;
|
||||||
import com.webauthn4j.data.AuthenticatorTransport;
|
import com.webauthn4j.data.AuthenticatorTransport;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.WebAuthnConstants;
|
import org.keycloak.WebAuthnConstants;
|
||||||
import org.keycloak.authentication.CredentialRegistrator;
|
import org.keycloak.authentication.CredentialRegistrator;
|
||||||
import org.keycloak.authentication.InitiatedActionSupport;
|
import org.keycloak.authentication.InitiatedActionSupport;
|
||||||
|
|
|
@ -38,7 +38,7 @@ import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.common.DefaultEvaluationContext;
|
import org.keycloak.authorization.common.DefaultEvaluationContext;
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.keycloak.broker.oidc;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
||||||
|
@ -470,7 +470,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.session = provider.session;
|
this.session = provider.session;
|
||||||
this.clientConnection = session.getContext().getConnection();
|
this.clientConnection = session.getContext().getConnection();
|
||||||
this.httpRequest = session.getContext().getContextObject(HttpRequest.class);
|
this.httpRequest = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -584,7 +584,7 @@ public class SAMLEndpoint {
|
||||||
*/
|
*/
|
||||||
private AuthenticationSessionModel samlIdpInitiatedSSO(final String clientUrlName) {
|
private AuthenticationSessionModel samlIdpInitiatedSSO(final String clientUrlName) {
|
||||||
event.event(EventType.LOGIN);
|
event.event(EventType.LOGIN);
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
Optional<ClientModel> oClient = SAMLEndpoint.this.session.clients()
|
Optional<ClientModel> oClient = SAMLEndpoint.this.session.clients()
|
||||||
.searchClientsByAttributes(realm, Collections.singletonMap(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME, clientUrlName), 0, 1)
|
.searchClientsByAttributes(realm, Collections.singletonMap(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME, clientUrlName), 0, 1)
|
||||||
.findFirst();
|
.findFirst();
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class DefaultLocaleUpdaterProvider implements LocaleUpdaterProvider {
|
||||||
UriInfo uriInfo = session.getContext().getUri();
|
UriInfo uriInfo = session.getContext().getUri();
|
||||||
|
|
||||||
boolean secure = realm.getSslRequired().isRequired(uriInfo.getRequestUri().getHost());
|
boolean secure = realm.getSslRequired().isRequired(uriInfo.getRequestUri().getHost());
|
||||||
CookieHelper.addCookie(LocaleSelectorProvider.LOCALE_COOKIE, locale, AuthenticationManager.getRealmCookiePath(realm, uriInfo), null, null, -1, secure, true);
|
CookieHelper.addCookie(LocaleSelectorProvider.LOCALE_COOKIE, locale, AuthenticationManager.getRealmCookiePath(realm, uriInfo), null, null, -1, secure, true, session);
|
||||||
logger.debugv("Updating locale cookie to {0}", locale);
|
logger.debugv("Updating locale cookie to {0}", locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ public class DefaultLocaleUpdaterProvider implements LocaleUpdaterProvider {
|
||||||
UriInfo uriInfo = session.getContext().getUri();
|
UriInfo uriInfo = session.getContext().getUri();
|
||||||
|
|
||||||
boolean secure = realm.getSslRequired().isRequired(session.getContext().getConnection());
|
boolean secure = realm.getSslRequired().isRequired(session.getContext().getConnection());
|
||||||
CookieHelper.addCookie(LocaleSelectorProvider.LOCALE_COOKIE, "", AuthenticationManager.getRealmCookiePath(realm, uriInfo), null, "Expiring cookie", 0, secure, true);
|
CookieHelper.addCookie(LocaleSelectorProvider.LOCALE_COOKIE, "", AuthenticationManager.getRealmCookiePath(realm, uriInfo), null, "Expiring cookie", 0, secure, true, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.keycloak.protocol;
|
package org.keycloak.protocol;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authentication.AuthenticationProcessor;
|
import org.keycloak.authentication.AuthenticationProcessor;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
|
@ -73,7 +73,7 @@ public abstract class AuthorizationEndpointBase {
|
||||||
this.clientConnection = session.getContext().getConnection();
|
this.clientConnection = session.getContext().getConnection();
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.httpRequest = session.getContext().getContextObject(HttpRequest.class);
|
this.httpRequest = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.keycloak.Token;
|
||||||
import org.keycloak.TokenCategory;
|
import org.keycloak.TokenCategory;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.KeycloakContext;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
|
@ -124,13 +125,15 @@ public class RestartLoginCookie implements Token {
|
||||||
String encoded = session.tokens().encode(restart);
|
String encoded = session.tokens().encode(restart);
|
||||||
String path = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
|
String path = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
|
||||||
boolean secureOnly = realm.getSslRequired().isRequired(connection);
|
boolean secureOnly = realm.getSslRequired().isRequired(connection);
|
||||||
CookieHelper.addCookie(KC_RESTART, encoded, path, null, null, -1, secureOnly, true);
|
CookieHelper.addCookie(KC_RESTART, encoded, path, null, null, -1, secureOnly, true, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void expireRestartCookie(RealmModel realm, ClientConnection connection, UriInfo uriInfo) {
|
public static void expireRestartCookie(RealmModel realm, UriInfo uriInfo, KeycloakSession session) {
|
||||||
|
KeycloakContext context = session.getContext();
|
||||||
|
ClientConnection connection = context.getConnection();
|
||||||
String path = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
|
String path = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
|
||||||
boolean secureOnly = realm.getSslRequired().isRequired(connection);
|
boolean secureOnly = realm.getSslRequired().isRequired(connection);
|
||||||
CookieHelper.addCookie(KC_RESTART, "", path, null, null, 0, secureOnly, true);
|
CookieHelper.addCookie(KC_RESTART, "", path, null, null, 0, secureOnly, true, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cookie getRestartCookie(KeycloakSession session){
|
public static Cookie getRestartCookie(KeycloakSession session){
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class DockerEndpoint extends AuthorizationEndpointBase {
|
||||||
updateAuthenticationSession();
|
updateAuthenticationSession();
|
||||||
|
|
||||||
// So back button doesn't work
|
// So back button doesn't work
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
|
|
||||||
return handleBrowserAuthenticationRequest(authenticationSession, new DockerAuthV2Protocol(session, realm, session.getContext().getUri(), headers, event.event(login)), false, false);
|
return handleBrowserAuthenticationRequest(authenticationSession, new DockerAuthV2Protocol(session, realm, session.getContext().getUri(), headers, event.event(login)), false, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.crypto.KeyType;
|
import org.keycloak.crypto.KeyType;
|
||||||
|
@ -89,7 +89,7 @@ public class OIDCLoginProtocolService {
|
||||||
this.tokenManager = new TokenManager();
|
this.tokenManager = new TokenManager();
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.providerConfig = providerConfig;
|
this.providerConfig = providerConfig;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.keycloak.protocol.oidc;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.TokenCategory;
|
import org.keycloak.TokenCategory;
|
||||||
|
|
|
@ -201,7 +201,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
||||||
updateAuthenticationSession();
|
updateAuthenticationSession();
|
||||||
|
|
||||||
// So back button doesn't work
|
// So back button doesn't work
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case REGISTER:
|
case REGISTER:
|
||||||
return buildRegister();
|
return buildRegister();
|
||||||
|
@ -356,7 +356,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response buildRegister() {
|
private Response buildRegister() {
|
||||||
authManager.expireIdentityCookie(realm, session.getContext().getUri(), clientConnection);
|
authManager.expireIdentityCookie(realm, session.getContext().getUri(), session);
|
||||||
|
|
||||||
AuthenticationFlowModel flow = realm.getRegistrationFlow();
|
AuthenticationFlowModel flow = realm.getRegistrationFlow();
|
||||||
String flowId = flow.getId();
|
String flowId = flow.getId();
|
||||||
|
@ -368,7 +368,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response buildForgotCredential() {
|
private Response buildForgotCredential() {
|
||||||
authManager.expireIdentityCookie(realm, session.getContext().getUri(), clientConnection);
|
authManager.expireIdentityCookie(realm, session.getContext().getUri(), session);
|
||||||
|
|
||||||
AuthenticationFlowModel flow = realm.getResetCredentialsFlow();
|
AuthenticationFlowModel flow = realm.getResetCredentialsFlow();
|
||||||
String flowId = flow.getId();
|
String flowId = flow.getId();
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class IframeUtil {
|
||||||
|
|
||||||
InputStream resource = IframeUtil.class.getResourceAsStream(fileName);
|
InputStream resource = IframeUtil.class.getResourceAsStream(fileName);
|
||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
P3PHelper.addP3PHeader();
|
P3PHelper.addP3PHeader(session);
|
||||||
session.getProvider(SecurityHeadersProvider.class).options().allowAnyFrameAncestor();
|
session.getProvider(SecurityHeadersProvider.class).options().allowAnyFrameAncestor();
|
||||||
return Response.ok(resource).cacheControl(cacheControl).build();
|
return Response.ok(resource).cacheControl(cacheControl).build();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import static org.keycloak.utils.LockObjectsForModification.lockUserSessionsForM
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
|
@ -127,7 +127,7 @@ public class LogoutEndpoint {
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.providerConfig = providerConfig;
|
this.providerConfig = providerConfig;
|
||||||
this.offlineSessionsLazyLoadingEnabled = !Config.scope("userSessions").scope("infinispan").getBoolean("preloadOfflineSessionsFromDatabase", false);
|
this.offlineSessionsLazyLoadingEnabled = !Config.scope("userSessions").scope("infinispan").getBoolean("preloadOfflineSessionsFromDatabase", false);
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
package org.keycloak.protocol.oidc.endpoints;
|
package org.keycloak.protocol.oidc.endpoints;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.authentication.AuthenticationProcessor;
|
import org.keycloak.authentication.AuthenticationProcessor;
|
||||||
|
@ -164,8 +164,8 @@ public class TokenEndpoint {
|
||||||
this.tokenManager = tokenManager;
|
this.tokenManager = tokenManager;
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.httpResponse = session.getContext().getContextObject(HttpResponse.class);
|
this.httpResponse = session.getContext().getHttpResponse();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,9 +201,8 @@ public class TokenEndpoint {
|
||||||
// https://tools.ietf.org/html/rfc6749#section-5.1
|
// https://tools.ietf.org/html/rfc6749#section-5.1
|
||||||
// The authorization server MUST include the HTTP "Cache-Control" response header field
|
// The authorization server MUST include the HTTP "Cache-Control" response header field
|
||||||
// with a value of "no-store" as well as the "Pragma" response header field with a value of "no-cache".
|
// with a value of "no-store" as well as the "Pragma" response header field with a value of "no-cache".
|
||||||
MultivaluedMap<String, Object> outputHeaders = httpResponse.getOutputHeaders();
|
httpResponse.setHeader("Cache-Control", "no-store");
|
||||||
outputHeaders.putSingle("Cache-Control", "no-store");
|
httpResponse.setHeader("Pragma", "no-cache");
|
||||||
outputHeaders.putSingle("Pragma", "no-cache");
|
|
||||||
|
|
||||||
checkSsl();
|
checkSsl();
|
||||||
checkRealm();
|
checkRealm();
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
package org.keycloak.protocol.oidc.endpoints;
|
package org.keycloak.protocol.oidc.endpoints;
|
||||||
|
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
@ -61,7 +61,7 @@ public class TokenIntrospectionEndpoint {
|
||||||
this.clientConnection = session.getContext().getConnection();
|
this.clientConnection = session.getContext().getConnection();
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
|
|
|
@ -28,7 +28,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
@ -79,7 +79,7 @@ public class TokenRevocationEndpoint {
|
||||||
this.clientConnection = session.getContext().getConnection();
|
this.clientConnection = session.getContext().getConnection();
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
package org.keycloak.protocol.oidc.endpoints;
|
package org.keycloak.protocol.oidc.endpoints;
|
||||||
|
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.TokenCategory;
|
import org.keycloak.TokenCategory;
|
||||||
import org.keycloak.TokenVerifier;
|
import org.keycloak.TokenVerifier;
|
||||||
|
@ -107,7 +107,7 @@ public class UserInfoEndpoint {
|
||||||
this.tokenManager = tokenManager;
|
this.tokenManager = tokenManager;
|
||||||
this.appAuthManager = new AppAuthManager();
|
this.appAuthManager = new AppAuthManager();
|
||||||
this.error = new OAuth2Error().json(false).realm(realm);
|
this.error = new OAuth2Error().json(false).realm(realm);
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/")
|
@Path("/")
|
||||||
|
|
|
@ -18,7 +18,7 @@ package org.keycloak.protocol.oidc.grants.ciba.endpoints;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.TokenVerifier;
|
import org.keycloak.TokenVerifier;
|
||||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||||
|
@ -59,7 +59,7 @@ public class BackchannelAuthenticationCallbackEndpoint extends AbstractCibaEndpo
|
||||||
|
|
||||||
public BackchannelAuthenticationCallbackEndpoint(KeycloakSession session, EventBuilder event) {
|
public BackchannelAuthenticationCallbackEndpoint(KeycloakSession session, EventBuilder event) {
|
||||||
super(session, event);
|
super(session, event);
|
||||||
this.httpRequest = session.getContext().getContextObject(HttpRequest.class);
|
this.httpRequest = session.getContext().getHttpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/")
|
@Path("/")
|
||||||
|
|
|
@ -18,7 +18,7 @@ package org.keycloak.protocol.oidc.grants.ciba.endpoints;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
@ -76,7 +76,7 @@ public class BackchannelAuthenticationEndpoint extends AbstractCibaEndpoint {
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response processGrantRequest() {
|
public Response processGrantRequest() {
|
||||||
HttpRequest httpRequest = session.getContext().getContextObject(HttpRequest.class);
|
HttpRequest httpRequest = session.getContext().getHttpRequest();
|
||||||
CIBAAuthenticationRequest request = authorizeClient(httpRequest.getDecodedFormParameters());
|
CIBAAuthenticationRequest request = authorizeClient(httpRequest.getDecodedFormParameters());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.keycloak.protocol.oidc.grants.device.endpoints;
|
package org.keycloak.protocol.oidc.grants.device.endpoints;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.common.util.SecretGenerator;
|
import org.keycloak.common.util.SecretGenerator;
|
||||||
|
@ -86,7 +86,7 @@ public class DeviceEndpoint extends AuthorizationEndpointBase implements RealmRe
|
||||||
|
|
||||||
public DeviceEndpoint(KeycloakSession session, EventBuilder event) {
|
public DeviceEndpoint(KeycloakSession session, EventBuilder event) {
|
||||||
super(session, event);
|
super(session, event);
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,7 +123,7 @@ public class DeviceEndpoint extends AuthorizationEndpointBase implements RealmRe
|
||||||
}
|
}
|
||||||
|
|
||||||
// So back button doesn't work
|
// So back button doesn't work
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
|
|
||||||
if (!realm.getOAuth2DeviceConfig().isOAuth2DeviceAuthorizationGrantEnabled(client)) {
|
if (!realm.getOAuth2DeviceConfig().isOAuth2DeviceAuthorizationGrantEnabled(client)) {
|
||||||
event.error(Errors.NOT_ALLOWED);
|
event.error(Errors.NOT_ALLOWED);
|
||||||
|
@ -207,7 +207,7 @@ public class DeviceEndpoint extends AuthorizationEndpointBase implements RealmRe
|
||||||
checkRealm();
|
checkRealm();
|
||||||
|
|
||||||
// So back button doesn't work
|
// So back button doesn't work
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
|
|
||||||
// code is not known, we can infer the client neither. ask the user to provide the code.
|
// code is not known, we can infer the client neither. ask the user to provide the code.
|
||||||
if (StringUtil.isNullOrEmpty(userCode)) {
|
if (StringUtil.isNullOrEmpty(userCode)) {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.protocol.oidc.par.endpoints;
|
package org.keycloak.protocol.oidc.par.endpoints;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
@ -69,7 +69,7 @@ public class ParEndpoint extends AbstractParEndpoint {
|
||||||
|
|
||||||
public ParEndpoint(KeycloakSession session, EventBuilder event) {
|
public ParEndpoint(KeycloakSession session, EventBuilder event) {
|
||||||
super(session, event);
|
super(session, event);
|
||||||
this.httpRequest = session.getContext().getContextObject(HttpRequest.class);
|
this.httpRequest = session.getContext().getHttpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/")
|
@Path("/")
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
package org.keycloak.protocol.oidc.utils;
|
package org.keycloak.protocol.oidc.utils;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
|
||||||
import org.keycloak.authentication.AuthenticationProcessor;
|
import org.keycloak.authentication.AuthenticationProcessor;
|
||||||
import org.keycloak.authentication.ClientAuthenticator;
|
import org.keycloak.authentication.ClientAuthenticator;
|
||||||
import org.keycloak.authentication.ClientAuthenticatorFactory;
|
import org.keycloak.authentication.ClientAuthenticatorFactory;
|
||||||
|
@ -52,7 +51,7 @@ public class AuthorizeClientUtil {
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
if (cors != null) {
|
if (cors != null) {
|
||||||
cors.allowAllOrigins();
|
cors.allowAllOrigins();
|
||||||
HttpResponse httpResponse = session.getContext().getContextObject(HttpResponse.class);
|
HttpResponse httpResponse = session.getContext().getHttpResponse();
|
||||||
cors.build(httpResponse);
|
cors.build(httpResponse);
|
||||||
}
|
}
|
||||||
throw new WebApplicationException(response);
|
throw new WebApplicationException(response);
|
||||||
|
@ -101,7 +100,7 @@ public class AuthorizeClientUtil {
|
||||||
.setRealm(realm)
|
.setRealm(realm)
|
||||||
.setSession(session)
|
.setSession(session)
|
||||||
.setUriInfo(session.getContext().getUri())
|
.setUriInfo(session.getContext().getUri())
|
||||||
.setRequest(session.getContext().getContextObject(HttpRequest.class));
|
.setRequest(session.getContext().getHttpRequest());
|
||||||
|
|
||||||
return processor;
|
return processor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,6 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.specimpl.ResteasyHttpHeaders;
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
|
||||||
import org.keycloak.broker.saml.SAMLDataMarshaller;
|
import org.keycloak.broker.saml.SAMLDataMarshaller;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.common.VerificationException;
|
import org.keycloak.common.VerificationException;
|
||||||
|
@ -52,6 +50,8 @@ import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.events.EventType;
|
import org.keycloak.events.EventType;
|
||||||
import org.keycloak.executors.ExecutorsProvider;
|
import org.keycloak.executors.ExecutorsProvider;
|
||||||
|
import org.keycloak.http.HttpRequest;
|
||||||
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeyManager;
|
import org.keycloak.models.KeyManager;
|
||||||
|
@ -811,7 +811,7 @@ public class SamlService extends AuthorizationEndpointBase {
|
||||||
@GET
|
@GET
|
||||||
public void redirectBinding(@Suspended AsyncResponse asyncResponse, @QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest, @QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse, @QueryParam(GeneralConstants.RELAY_STATE) String relayState, @QueryParam(GeneralConstants.SAML_ARTIFACT_KEY) String artifact) {
|
public void redirectBinding(@Suspended AsyncResponse asyncResponse, @QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest, @QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse, @QueryParam(GeneralConstants.RELAY_STATE) String relayState, @QueryParam(GeneralConstants.SAML_ARTIFACT_KEY) String artifact) {
|
||||||
logger.debug("SAML GET");
|
logger.debug("SAML GET");
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
|
|
||||||
new RedirectBindingProtocol().execute(asyncResponse, samlRequest, samlResponse, relayState, artifact);
|
new RedirectBindingProtocol().execute(asyncResponse, samlRequest, samlResponse, relayState, artifact);
|
||||||
}
|
}
|
||||||
|
@ -919,7 +919,7 @@ public class SamlService extends AuthorizationEndpointBase {
|
||||||
@Produces(MediaType.TEXT_HTML_UTF_8)
|
@Produces(MediaType.TEXT_HTML_UTF_8)
|
||||||
public Response idpInitiatedSSO(@PathParam("client") String clientUrlName, @QueryParam("RelayState") String relayState) {
|
public Response idpInitiatedSSO(@PathParam("client") String clientUrlName, @QueryParam("RelayState") String relayState) {
|
||||||
event.event(EventType.LOGIN);
|
event.event(EventType.LOGIN);
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
ClientModel client = session.clients()
|
ClientModel client = session.clients()
|
||||||
.searchClientsByAttributes(realm, Collections.singletonMap(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME, clientUrlName), 0, 1)
|
.searchClientsByAttributes(realm, Collections.singletonMap(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME, clientUrlName), 0, 1)
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
|
@ -1311,16 +1311,15 @@ public class SamlService extends AuthorizationEndpointBase {
|
||||||
|
|
||||||
private class ArtifactResolutionRunnable implements ScheduledTask{
|
private class ArtifactResolutionRunnable implements ScheduledTask{
|
||||||
|
|
||||||
|
private final HttpRequest request;
|
||||||
|
private final HttpResponse response;
|
||||||
private AsyncResponse asyncResponse;
|
private AsyncResponse asyncResponse;
|
||||||
private URI clientArtifactBindingURI;
|
private URI clientArtifactBindingURI;
|
||||||
private String relayState;
|
private String relayState;
|
||||||
private Document doc;
|
private Document doc;
|
||||||
private UriInfo uri;
|
private UriInfo uri;
|
||||||
private String realmId;
|
private String realmId;
|
||||||
private HttpHeaders httpHeaders;
|
|
||||||
private ClientConnection connection;
|
private ClientConnection connection;
|
||||||
private org.jboss.resteasy.spi.HttpResponse response;
|
|
||||||
private HttpRequest request;
|
|
||||||
private String bindingType;
|
private String bindingType;
|
||||||
|
|
||||||
public ArtifactResolutionRunnable(String bindingType, AsyncResponse asyncResponse, Document doc, URI clientArtifactBindingURI, String relayState, ClientConnection connection){
|
public ArtifactResolutionRunnable(String bindingType, AsyncResponse asyncResponse, Document doc, URI clientArtifactBindingURI, String relayState, ClientConnection connection){
|
||||||
|
@ -1330,11 +1329,10 @@ public class SamlService extends AuthorizationEndpointBase {
|
||||||
this.relayState = relayState;
|
this.relayState = relayState;
|
||||||
this.uri = session.getContext().getUri();
|
this.uri = session.getContext().getUri();
|
||||||
this.realmId = realm.getId();
|
this.realmId = realm.getId();
|
||||||
this.httpHeaders = new ResteasyHttpHeaders(headers.getRequestHeaders());
|
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.response = session.getContext().getContextObject(org.jboss.resteasy.spi.HttpResponse.class);
|
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
|
||||||
this.bindingType = bindingType;
|
this.bindingType = bindingType;
|
||||||
|
this.request = session.getContext().getHttpRequest();
|
||||||
|
this.response = session.getContext().getHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1346,10 +1344,8 @@ public class SamlService extends AuthorizationEndpointBase {
|
||||||
Resteasy.pushContext(KeycloakTransaction.class, tx);
|
Resteasy.pushContext(KeycloakTransaction.class, tx);
|
||||||
|
|
||||||
Resteasy.pushContext(KeycloakSession.class, session);
|
Resteasy.pushContext(KeycloakSession.class, session);
|
||||||
Resteasy.pushContext(HttpHeaders.class, httpHeaders);
|
|
||||||
Resteasy.pushContext(org.jboss.resteasy.spi.HttpResponse.class, response);
|
|
||||||
Resteasy.pushContext(HttpRequest.class, request);
|
Resteasy.pushContext(HttpRequest.class, request);
|
||||||
|
Resteasy.pushContext(HttpResponse.class, response);
|
||||||
Resteasy.pushContext(ClientConnection.class, connection);
|
Resteasy.pushContext(ClientConnection.class, connection);
|
||||||
|
|
||||||
RealmManager realmManager = new RealmManager(session);
|
RealmManager realmManager = new RealmManager(session);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.keycloak.protocol.saml.profile.ecp.authenticator;
|
package org.keycloak.protocol.saml.profile.ecp.authenticator;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||||
import org.keycloak.authentication.AuthenticationFlowError;
|
import org.keycloak.authentication.AuthenticationFlowError;
|
||||||
import org.keycloak.authentication.Authenticator;
|
import org.keycloak.authentication.Authenticator;
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.keycloak.services;
|
||||||
|
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.common.util.Resteasy;
|
import org.keycloak.common.util.Resteasy;
|
||||||
|
import org.keycloak.http.HttpRequest;
|
||||||
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.locale.LocaleSelectorProvider;
|
import org.keycloak.locale.LocaleSelectorProvider;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakContext;
|
import org.keycloak.models.KeycloakContext;
|
||||||
|
@ -45,13 +47,13 @@ public class DefaultKeycloakContext implements KeycloakContext {
|
||||||
|
|
||||||
private ClientModel client;
|
private ClientModel client;
|
||||||
|
|
||||||
private ClientConnection connection;
|
|
||||||
|
|
||||||
private KeycloakSession session;
|
private KeycloakSession session;
|
||||||
|
|
||||||
private Map<UrlType, KeycloakUriInfo> uriInfo;
|
private Map<UrlType, KeycloakUriInfo> uriInfo;
|
||||||
|
|
||||||
private AuthenticationSessionModel authenticationSession;
|
private AuthenticationSessionModel authenticationSession;
|
||||||
|
private HttpRequest request;
|
||||||
|
private HttpResponse response;
|
||||||
|
|
||||||
public DefaultKeycloakContext(KeycloakSession session) {
|
public DefaultKeycloakContext(KeycloakSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
@ -85,9 +87,15 @@ public class DefaultKeycloakContext implements KeycloakContext {
|
||||||
return getUri(UrlType.FRONTEND);
|
return getUri(UrlType.FRONTEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use {@link #getHttpRequest()} to obtain the request headers.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getRequestHeaders() {
|
public HttpHeaders getRequestHeaders() {
|
||||||
return getContextObject(HttpHeaders.class);
|
return getHttpRequest().getHttpHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -136,4 +144,39 @@ public class DefaultKeycloakContext implements KeycloakContext {
|
||||||
this.authenticationSession = authenticationSession;
|
this.authenticationSession = authenticationSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest getHttpRequest() {
|
||||||
|
if (request == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
request = getContextObject(HttpRequest.class);
|
||||||
|
if (request == null) {
|
||||||
|
request = createHttpRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpResponse getHttpResponse() {
|
||||||
|
if (response == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
response = getContextObject(HttpResponse.class);
|
||||||
|
if (response == null) {
|
||||||
|
response = createHttpResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HttpRequest createHttpRequest() {
|
||||||
|
return new HttpRequestImpl(getContextObject(org.jboss.resteasy.spi.HttpRequest.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HttpResponse createHttpResponse() {
|
||||||
|
return new HttpResponseImpl(getContextObject(org.jboss.resteasy.spi.HttpResponse.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.keycloak.vault.VaultProvider;
|
||||||
import org.keycloak.vault.VaultTranscriber;
|
import org.keycloak.vault.VaultTranscriber;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -93,7 +94,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
||||||
public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
|
public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.transactionManager = new DefaultKeycloakTransactionManager(this);
|
this.transactionManager = new DefaultKeycloakTransactionManager(this);
|
||||||
context = new DefaultKeycloakContext(this);
|
context = createKeycloakContext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -158,6 +159,11 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
||||||
attributes.put(name, value);
|
attributes.put(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getAttributes() {
|
||||||
|
return Collections.unmodifiableMap(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeycloakTransactionManager getTransactionManager() {
|
public KeycloakTransactionManager getTransactionManager() {
|
||||||
return transactionManager;
|
return transactionManager;
|
||||||
|
@ -469,4 +475,8 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return closed;
|
return closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected DefaultKeycloakContext createKeycloakContext(KeycloakSession session) {
|
||||||
|
return new DefaultKeycloakContext(session);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.services;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import org.keycloak.http.HttpRequest;
|
||||||
|
|
||||||
|
public class HttpRequestImpl implements HttpRequest {
|
||||||
|
|
||||||
|
private org.jboss.resteasy.spi.HttpRequest delegate;
|
||||||
|
|
||||||
|
public <R> HttpRequestImpl(org.jboss.resteasy.spi.HttpRequest delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHttpMethod() {
|
||||||
|
return delegate.getHttpMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MultivaluedMap<String, String> getDecodedFormParameters() {
|
||||||
|
return delegate.getDecodedFormParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpHeaders getHttpHeaders() {
|
||||||
|
return delegate.getHttpHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate[] getClientCertificateChain() {
|
||||||
|
return (X509Certificate[]) delegate.getAttribute("javax.servlet.request.X509Certificate");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UriInfo getUri() {
|
||||||
|
return delegate.getUri();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.services;
|
||||||
|
|
||||||
|
import org.keycloak.http.HttpResponse;
|
||||||
|
|
||||||
|
public class HttpResponseImpl implements HttpResponse {
|
||||||
|
|
||||||
|
private org.jboss.resteasy.spi.HttpResponse delegate;
|
||||||
|
|
||||||
|
public HttpResponseImpl(org.jboss.resteasy.spi.HttpResponse delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStatus(int statusCode) {
|
||||||
|
delegate.setStatus(statusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addHeader(String name, String value) {
|
||||||
|
delegate.getOutputHeaders().add(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHeader(String name, String value) {
|
||||||
|
delegate.getOutputHeaders().putSingle(name, value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.services.clientpolicy.executor;
|
package org.keycloak.services.clientpolicy.executor;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
|
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
|
@ -81,7 +81,7 @@ public class HolderOfKeyEnforcerExecutor implements ClientPolicyExecutorProvider
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeOnEvent(ClientPolicyContext context) throws ClientPolicyException {
|
public void executeOnEvent(ClientPolicyContext context) throws ClientPolicyException {
|
||||||
HttpRequest request = session.getContext().getContextObject(HttpRequest.class);
|
HttpRequest request = session.getContext().getHttpRequest();
|
||||||
switch (context.getEvent()) {
|
switch (context.getEvent()) {
|
||||||
case REGISTER:
|
case REGISTER:
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.keycloak.services.clientpolicy.executor;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.ws.rs.HttpMethod;
|
import javax.ws.rs.HttpMethod;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
|
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
|
||||||
|
@ -84,7 +84,7 @@ public class SecureLogoutExecutor implements ClientPolicyExecutorProvider<Secure
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case LOGOUT_REQUEST:
|
case LOGOUT_REQUEST:
|
||||||
HttpRequest request = session.getContext().getContextObject(HttpRequest.class);
|
HttpRequest request = session.getContext().getHttpRequest();
|
||||||
|
|
||||||
if (HttpMethod.GET.equalsIgnoreCase(request.getHttpMethod()) && !configuration.isAllowFrontChannelLogout()) {
|
if (HttpMethod.GET.equalsIgnoreCase(request.getHttpMethod()) && !configuration.isAllowFrontChannelLogout()) {
|
||||||
throwFrontChannelLogoutNotAllowed();
|
throwFrontChannelLogoutNotAllowed();
|
||||||
|
|
|
@ -20,11 +20,10 @@ package org.keycloak.services.clientpolicy.executor;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.common.util.ObjectUtil;
|
import org.keycloak.common.util.ObjectUtil;
|
||||||
import org.keycloak.crypto.Algorithm;
|
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
import org.keycloak.jose.jws.JWSInputException;
|
import org.keycloak.jose.jws.JWSInputException;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
@ -83,7 +82,7 @@ public class SecureSigningAlgorithmForSignedJwtExecutor implements ClientPolicyE
|
||||||
case TOKEN_INTROSPECT:
|
case TOKEN_INTROSPECT:
|
||||||
case LOGOUT_REQUEST:
|
case LOGOUT_REQUEST:
|
||||||
boolean isRequireClientAssertion = Optional.ofNullable(configuration.isRequireClientAssertion()).orElse(Boolean.FALSE).booleanValue();
|
boolean isRequireClientAssertion = Optional.ofNullable(configuration.isRequireClientAssertion()).orElse(Boolean.FALSE).booleanValue();
|
||||||
HttpRequest req = session.getContext().getContextObject(HttpRequest.class);
|
HttpRequest req = session.getContext().getHttpRequest();
|
||||||
String clientAssertion = req.getDecodedFormParameters().getFirst(OAuth2Constants.CLIENT_ASSERTION);
|
String clientAssertion = req.getDecodedFormParameters().getFirst(OAuth2Constants.CLIENT_ASSERTION);
|
||||||
if (!isRequireClientAssertion && ObjectUtil.isBlank(clientAssertion)) {
|
if (!isRequireClientAssertion && ObjectUtil.isBlank(clientAssertion)) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class AppAuthManager extends AuthenticationManager {
|
||||||
if (authResult == null) return null;
|
if (authResult == null) return null;
|
||||||
// refresh the cookies!
|
// refresh the cookies!
|
||||||
createLoginCookie(session, realm, authResult.getUser(), authResult.getSession(), session.getContext().getUri(), session.getContext().getConnection());
|
createLoginCookie(session, realm, authResult.getUser(), authResult.getSession(), session.getContext().getUri(), session.getContext().getConnection());
|
||||||
if (authResult.getSession().isRememberMe()) createRememberMeCookie(realm, authResult.getUser().getUsername(), session.getContext().getUri(), session.getContext().getConnection());
|
if (authResult.getSession().isRememberMe()) createRememberMeCookie(authResult.getUser().getUsername(), session.getContext().getUri(), session);
|
||||||
return authResult;
|
return authResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
package org.keycloak.services.managers;
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.TokenVerifier;
|
import org.keycloak.TokenVerifier;
|
||||||
import org.keycloak.TokenVerifier.Predicate;
|
import org.keycloak.TokenVerifier.Predicate;
|
||||||
|
@ -46,6 +46,7 @@ import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.events.EventType;
|
import org.keycloak.events.EventType;
|
||||||
import org.keycloak.forms.login.LoginFormsProvider;
|
import org.keycloak.forms.login.LoginFormsProvider;
|
||||||
|
import org.keycloak.models.KeycloakContext;
|
||||||
import org.keycloak.models.SingleUseObjectKeyModel;
|
import org.keycloak.models.SingleUseObjectKeyModel;
|
||||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
|
@ -229,7 +230,7 @@ public class AuthenticationManager {
|
||||||
AccessToken token = verifier.verify().getToken();
|
AccessToken token = verifier.verify().getToken();
|
||||||
UserSessionModel cookieSession = lockUserSessionsForModification(session, () -> session.sessions().getUserSession(realm, token.getSessionState()));
|
UserSessionModel cookieSession = lockUserSessionsForModification(session, () -> session.sessions().getUserSession(realm, token.getSessionState()));
|
||||||
if (cookieSession == null || !cookieSession.getId().equals(userSession.getId())) return true;
|
if (cookieSession == null || !cookieSession.getId().equals(userSession.getId())) return true;
|
||||||
expireIdentityCookie(realm, uriInfo, connection);
|
expireIdentityCookie(realm, uriInfo, session);
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -686,8 +687,8 @@ public class AuthenticationManager {
|
||||||
checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
|
checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
|
||||||
|
|
||||||
// For resolving artifact we don't need any cookie, all details are stored in session storage so we can remove
|
// For resolving artifact we don't need any cookie, all details are stored in session storage so we can remove
|
||||||
expireIdentityCookie(realm, uriInfo, connection);
|
expireIdentityCookie(realm, uriInfo, session);
|
||||||
expireRememberMeCookie(realm, uriInfo, connection);
|
expireRememberMeCookie(realm, uriInfo, session);
|
||||||
|
|
||||||
String method = userSession.getNote(KEYCLOAK_LOGOUT_PROTOCOL);
|
String method = userSession.getNote(KEYCLOAK_LOGOUT_PROTOCOL);
|
||||||
EventBuilder event = new EventBuilder(realm, session, connection);
|
EventBuilder event = new EventBuilder(realm, session, connection);
|
||||||
|
@ -782,7 +783,7 @@ public class AuthenticationManager {
|
||||||
maxAge = realm.getSsoSessionMaxLifespanRememberMe() > 0 ? realm.getSsoSessionMaxLifespanRememberMe() : realm.getSsoSessionMaxLifespan();
|
maxAge = realm.getSsoSessionMaxLifespanRememberMe() > 0 ? realm.getSsoSessionMaxLifespanRememberMe() : realm.getSsoSessionMaxLifespan();
|
||||||
}
|
}
|
||||||
logger.debugv("Create login cookie - name: {0}, path: {1}, max-age: {2}", KEYCLOAK_IDENTITY_COOKIE, cookiePath, maxAge);
|
logger.debugv("Create login cookie - name: {0}, path: {1}, max-age: {2}", KEYCLOAK_IDENTITY_COOKIE, cookiePath, maxAge);
|
||||||
CookieHelper.addCookie(KEYCLOAK_IDENTITY_COOKIE, encoded, cookiePath, null, null, maxAge, secureOnly, true, SameSiteAttributeValue.NONE);
|
CookieHelper.addCookie(KEYCLOAK_IDENTITY_COOKIE, encoded, cookiePath, null, null, maxAge, secureOnly, true, SameSiteAttributeValue.NONE, keycloakSession);
|
||||||
//builder.cookie(new NewCookie(cookieName, encoded, cookiePath, null, null, maxAge, secureOnly));// todo httponly , true);
|
//builder.cookie(new NewCookie(cookieName, encoded, cookiePath, null, null, maxAge, secureOnly));// todo httponly , true);
|
||||||
|
|
||||||
// With user-storage providers, user ID can contain special characters, which need to be encoded
|
// With user-storage providers, user ID can contain special characters, which need to be encoded
|
||||||
|
@ -793,17 +794,20 @@ public class AuthenticationManager {
|
||||||
// THIS SHOULD NOT BE A HTTPONLY COOKIE! It is used for OpenID Connect Iframe Session support!
|
// THIS SHOULD NOT BE A HTTPONLY COOKIE! It is used for OpenID Connect Iframe Session support!
|
||||||
// Max age should be set to the max lifespan of the session as it's used to invalidate old-sessions on re-login
|
// Max age should be set to the max lifespan of the session as it's used to invalidate old-sessions on re-login
|
||||||
int sessionCookieMaxAge = session.isRememberMe() && realm.getSsoSessionMaxLifespanRememberMe() > 0 ? realm.getSsoSessionMaxLifespanRememberMe() : realm.getSsoSessionMaxLifespan();
|
int sessionCookieMaxAge = session.isRememberMe() && realm.getSsoSessionMaxLifespanRememberMe() > 0 ? realm.getSsoSessionMaxLifespanRememberMe() : realm.getSsoSessionMaxLifespan();
|
||||||
CookieHelper.addCookie(KEYCLOAK_SESSION_COOKIE, sessionCookieValue, cookiePath, null, null, sessionCookieMaxAge, secureOnly, false, SameSiteAttributeValue.NONE);
|
CookieHelper.addCookie(KEYCLOAK_SESSION_COOKIE, sessionCookieValue, cookiePath, null, null, sessionCookieMaxAge, secureOnly, false, SameSiteAttributeValue.NONE, keycloakSession);
|
||||||
P3PHelper.addP3PHeader();
|
P3PHelper.addP3PHeader(keycloakSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createRememberMeCookie(RealmModel realm, String username, UriInfo uriInfo, ClientConnection connection) {
|
public static void createRememberMeCookie(String username, UriInfo uriInfo, KeycloakSession session) {
|
||||||
|
KeycloakContext context = session.getContext();
|
||||||
|
RealmModel realm = context.getRealm();
|
||||||
|
ClientConnection connection = context.getConnection();
|
||||||
String path = getIdentityCookiePath(realm, uriInfo);
|
String path = getIdentityCookiePath(realm, uriInfo);
|
||||||
boolean secureOnly = realm.getSslRequired().isRequired(connection);
|
boolean secureOnly = realm.getSslRequired().isRequired(connection);
|
||||||
// remember me cookie should be persistent (hardcoded to 365 days for now)
|
// remember me cookie should be persistent (hardcoded to 365 days for now)
|
||||||
//NewCookie cookie = new NewCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getCentralLoginLifespan(), secureOnly);// todo httponly , true);
|
//NewCookie cookie = new NewCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getCentralLoginLifespan(), secureOnly);// todo httponly , true);
|
||||||
try {
|
try {
|
||||||
CookieHelper.addCookie(KEYCLOAK_REMEMBER_ME, "username:" + URLEncoder.encode(username, "UTF-8"), path, null, null, 31536000, secureOnly, true);
|
CookieHelper.addCookie(KEYCLOAK_REMEMBER_ME, "username:" + URLEncoder.encode(username, "UTF-8"), path, null, null, 31536000, secureOnly, true, session);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
throw new RuntimeException("Failed to urlencode", e);
|
throw new RuntimeException("Failed to urlencode", e);
|
||||||
}
|
}
|
||||||
|
@ -827,37 +831,40 @@ public class AuthenticationManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void expireIdentityCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) {
|
public static void expireIdentityCookie(RealmModel realm, UriInfo uriInfo, KeycloakSession session) {
|
||||||
|
ClientConnection connection = session.getContext().getConnection();
|
||||||
logger.debug("Expiring identity cookie");
|
logger.debug("Expiring identity cookie");
|
||||||
String path = getIdentityCookiePath(realm, uriInfo);
|
String path = getIdentityCookiePath(realm, uriInfo);
|
||||||
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true, connection, SameSiteAttributeValue.NONE);
|
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true, connection, SameSiteAttributeValue.NONE, session);
|
||||||
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false, connection, SameSiteAttributeValue.NONE);
|
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false, connection, SameSiteAttributeValue.NONE, session);
|
||||||
|
|
||||||
String oldPath = getOldCookiePath(realm, uriInfo);
|
String oldPath = getOldCookiePath(realm, uriInfo);
|
||||||
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, oldPath, true, connection, SameSiteAttributeValue.NONE);
|
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, oldPath, true, connection, SameSiteAttributeValue.NONE, session);
|
||||||
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, oldPath, false, connection, SameSiteAttributeValue.NONE);
|
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, oldPath, false, connection, SameSiteAttributeValue.NONE, session);
|
||||||
}
|
}
|
||||||
public static void expireOldIdentityCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) {
|
public static void expireOldIdentityCookie(RealmModel realm, UriInfo uriInfo, KeycloakSession session) {
|
||||||
|
ClientConnection connection = session.getContext().getConnection();
|
||||||
logger.debug("Expiring old identity cookie with wrong path");
|
logger.debug("Expiring old identity cookie with wrong path");
|
||||||
|
|
||||||
String oldPath = getOldCookiePath(realm, uriInfo);
|
String oldPath = getOldCookiePath(realm, uriInfo);
|
||||||
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, oldPath, true, connection, SameSiteAttributeValue.NONE);
|
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, oldPath, true, connection, SameSiteAttributeValue.NONE, session);
|
||||||
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, oldPath, false, connection, SameSiteAttributeValue.NONE);
|
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, oldPath, false, connection, SameSiteAttributeValue.NONE, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) {
|
public static void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo, KeycloakSession session) {
|
||||||
|
ClientConnection connection = session.getContext().getConnection();
|
||||||
logger.debug("Expiring remember me cookie");
|
logger.debug("Expiring remember me cookie");
|
||||||
String path = getIdentityCookiePath(realm, uriInfo);
|
String path = getIdentityCookiePath(realm, uriInfo);
|
||||||
String cookieName = KEYCLOAK_REMEMBER_ME;
|
String cookieName = KEYCLOAK_REMEMBER_ME;
|
||||||
expireCookie(realm, cookieName, path, true, connection, null);
|
expireCookie(realm, cookieName, path, true, connection, null, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void expireOldAuthSessionCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) {
|
public static void expireOldAuthSessionCookie(RealmModel realm, UriInfo uriInfo, KeycloakSession session) {
|
||||||
logger.debugv("Expire {1} cookie .", AuthenticationSessionManager.AUTH_SESSION_ID);
|
logger.debugv("Expire {1} cookie .", AuthenticationSessionManager.AUTH_SESSION_ID);
|
||||||
|
ClientConnection connection = session.getContext().getConnection();
|
||||||
String oldPath = getOldCookiePath(realm, uriInfo);
|
String oldPath = getOldCookiePath(realm, uriInfo);
|
||||||
expireCookie(realm, AuthenticationSessionManager.AUTH_SESSION_ID, oldPath, true, connection, SameSiteAttributeValue.NONE);
|
expireCookie(realm, AuthenticationSessionManager.AUTH_SESSION_ID, oldPath, true, connection, SameSiteAttributeValue.NONE, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static String getIdentityCookiePath(RealmModel realm, UriInfo uriInfo) {
|
protected static String getIdentityCookiePath(RealmModel realm, UriInfo uriInfo) {
|
||||||
|
@ -880,10 +887,10 @@ public class AuthenticationManager {
|
||||||
return uri.getRawPath();
|
return uri.getRawPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void expireCookie(RealmModel realm, String cookieName, String path, boolean httpOnly, ClientConnection connection, SameSiteAttributeValue sameSite) {
|
public static void expireCookie(RealmModel realm, String cookieName, String path, boolean httpOnly, ClientConnection connection, SameSiteAttributeValue sameSite, KeycloakSession session) {
|
||||||
logger.debugf("Expiring cookie: %s path: %s", cookieName, path);
|
logger.debugf("Expiring cookie: %s path: %s", cookieName, path);
|
||||||
boolean secureOnly = realm.getSslRequired().isRequired(connection);;
|
boolean secureOnly = realm.getSslRequired().isRequired(connection);;
|
||||||
CookieHelper.addCookie(cookieName, "", path, null, "Expiring cookie", 0, secureOnly, httpOnly, sameSite);
|
CookieHelper.addCookie(cookieName, "", path, null, "Expiring cookie", 0, secureOnly, httpOnly, sameSite, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm) {
|
public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm) {
|
||||||
|
@ -900,8 +907,8 @@ public class AuthenticationManager {
|
||||||
String tokenString = cookie.getValue();
|
String tokenString = cookie.getValue();
|
||||||
AuthResult authResult = verifyIdentityToken(session, realm, session.getContext().getUri(), session.getContext().getConnection(), checkActive, false, null, true, tokenString, session.getContext().getRequestHeaders(), VALIDATE_IDENTITY_COOKIE);
|
AuthResult authResult = verifyIdentityToken(session, realm, session.getContext().getUri(), session.getContext().getConnection(), checkActive, false, null, true, tokenString, session.getContext().getRequestHeaders(), VALIDATE_IDENTITY_COOKIE);
|
||||||
if (authResult == null) {
|
if (authResult == null) {
|
||||||
expireIdentityCookie(realm, session.getContext().getUri(), session.getContext().getConnection());
|
expireIdentityCookie(realm, session.getContext().getUri(), session);
|
||||||
expireOldIdentityCookie(realm, session.getContext().getUri(), session.getContext().getConnection());
|
expireOldIdentityCookie(realm, session.getContext().getUri(), session);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
authResult.getSession().setLastSessionRefresh(Time.currentTime());
|
authResult.getSession().setLastSessionRefresh(Time.currentTime());
|
||||||
|
@ -949,9 +956,9 @@ public class AuthenticationManager {
|
||||||
createLoginCookie(session, realm, userSession.getUser(), userSession, uriInfo, clientConnection);
|
createLoginCookie(session, realm, userSession.getUser(), userSession, uriInfo, clientConnection);
|
||||||
if (userSession.getState() != UserSessionModel.State.LOGGED_IN) userSession.setState(UserSessionModel.State.LOGGED_IN);
|
if (userSession.getState() != UserSessionModel.State.LOGGED_IN) userSession.setState(UserSessionModel.State.LOGGED_IN);
|
||||||
if (userSession.isRememberMe()) {
|
if (userSession.isRememberMe()) {
|
||||||
createRememberMeCookie(realm, userSession.getLoginUsername(), uriInfo, clientConnection);
|
createRememberMeCookie(userSession.getLoginUsername(), uriInfo, session);
|
||||||
} else {
|
} else {
|
||||||
expireRememberMeCookie(realm, uriInfo, clientConnection);
|
expireRememberMeCookie(realm, uriInfo, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
|
AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
|
||||||
|
|
|
@ -149,7 +149,7 @@ public class AuthenticationSessionManager {
|
||||||
StickySessionEncoderProvider encoder = session.getProvider(StickySessionEncoderProvider.class);
|
StickySessionEncoderProvider encoder = session.getProvider(StickySessionEncoderProvider.class);
|
||||||
String encodedAuthSessionId = encoder.encodeSessionId(authSessionId);
|
String encodedAuthSessionId = encoder.encodeSessionId(authSessionId);
|
||||||
|
|
||||||
CookieHelper.addCookie(AUTH_SESSION_ID, encodedAuthSessionId, cookiePath, null, null, -1, sslRequired, true, SameSiteAttributeValue.NONE);
|
CookieHelper.addCookie(AUTH_SESSION_ID, encodedAuthSessionId, cookiePath, null, null, -1, sslRequired, true, SameSiteAttributeValue.NONE, session);
|
||||||
|
|
||||||
log.debugf("Set AUTH_SESSION_ID cookie with value %s", encodedAuthSessionId);
|
log.debugf("Set AUTH_SESSION_ID cookie with value %s", encodedAuthSessionId);
|
||||||
}
|
}
|
||||||
|
@ -184,10 +184,10 @@ public class AuthenticationSessionManager {
|
||||||
* @return list of the values of AUTH_SESSION_ID cookies. It is assumed that values could be encoded with route added (EG. "5e161e00-d426-4ea6-98e9-52eb9844e2d7.node1" )
|
* @return list of the values of AUTH_SESSION_ID cookies. It is assumed that values could be encoded with route added (EG. "5e161e00-d426-4ea6-98e9-52eb9844e2d7.node1" )
|
||||||
*/
|
*/
|
||||||
List<String> getAuthSessionCookies(RealmModel realm) {
|
List<String> getAuthSessionCookies(RealmModel realm) {
|
||||||
Set<String> cookiesVal = CookieHelper.getCookieValue(AUTH_SESSION_ID);
|
Set<String> cookiesVal = CookieHelper.getCookieValue(session, AUTH_SESSION_ID);
|
||||||
|
|
||||||
if (cookiesVal.size() > 1) {
|
if (cookiesVal.size() > 1) {
|
||||||
AuthenticationManager.expireOldAuthSessionCookie(realm, session.getContext().getUri(), session.getContext().getConnection());
|
AuthenticationManager.expireOldAuthSessionCookie(realm, session.getContext().getUri(), session);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> authSessionIds = cookiesVal.stream().limit(AUTH_SESSION_COOKIE_LIMIT).collect(Collectors.toList());
|
List<String> authSessionIds = cookiesVal.stream().limit(AUTH_SESSION_COOKIE_LIMIT).collect(Collectors.toList());
|
||||||
|
@ -208,9 +208,8 @@ public class AuthenticationSessionManager {
|
||||||
|
|
||||||
// expire restart cookie
|
// expire restart cookie
|
||||||
if (expireRestartCookie) {
|
if (expireRestartCookie) {
|
||||||
ClientConnection clientConnection = session.getContext().getConnection();
|
|
||||||
UriInfo uriInfo = session.getContext().getUri();
|
UriInfo uriInfo = session.getContext().getUri();
|
||||||
RestartLoginCookie.expireRestartCookie(realm, clientConnection, uriInfo);
|
RestartLoginCookie.expireRestartCookie(realm, uriInfo, session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.BadRequestException;
|
import org.jboss.resteasy.spi.BadRequestException;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.AbstractOAuthClient;
|
import org.keycloak.AbstractOAuthClient;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
|
@ -72,7 +72,7 @@ public abstract class AbstractSecuredLocalService {
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.clientConnection = session.getContext().getConnection();
|
this.clientConnection = session.getContext().getConnection();
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.BadRequestException;
|
import org.jboss.resteasy.spi.BadRequestException;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
|
@ -69,7 +69,7 @@ public class ClientsManagementService {
|
||||||
this.clientConnection = session.getContext().getConnection();
|
this.clientConnection = session.getContext().getConnection();
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,9 @@ import java.util.function.BiConsumer;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
|
||||||
import org.keycloak.common.util.CollectionUtil;
|
import org.keycloak.common.util.CollectionUtil;
|
||||||
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.protocol.oidc.utils.WebOriginsUtils;
|
import org.keycloak.protocol.oidc.utils.WebOriginsUtils;
|
||||||
|
@ -141,11 +141,11 @@ public class Cors {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(HttpResponse response) {
|
public void build(HttpResponse response) {
|
||||||
build(response.getOutputHeaders()::add);
|
build(response::addHeader);
|
||||||
logger.debug("Added CORS headers to response");
|
logger.debug("Added CORS headers to response");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(BiConsumer<String, Object> addHeader) {
|
public void build(BiConsumer<String, String> addHeader) {
|
||||||
String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
|
String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
|
||||||
if (origin == null) {
|
if (origin == null) {
|
||||||
logger.trace("No origin header ignoring");
|
logger.trace("No origin header ignoring");
|
||||||
|
@ -184,7 +184,7 @@ public class Cors {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preflight) {
|
if (preflight) {
|
||||||
addHeader.accept(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
|
addHeader.accept(ACCESS_CONTROL_MAX_AGE, String.valueOf(DEFAULT_MAX_AGE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,7 @@ package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.authentication.AuthenticationProcessor;
|
import org.keycloak.authentication.AuthenticationProcessor;
|
||||||
import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
|
import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
|
||||||
|
@ -151,7 +150,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
if (realmModel == null) {
|
if (realmModel == null) {
|
||||||
throw new IllegalArgumentException("Realm can not be null.");
|
throw new IllegalArgumentException("Realm can not be null.");
|
||||||
}
|
}
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1207,7 +1206,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
if (errorMessage != null) processor.setForwardedErrorMessage(new FormMessage(null, errorMessage));
|
if (errorMessage != null) processor.setForwardedErrorMessage(new FormMessage(null, errorMessage));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
return processor.authenticate();
|
return processor.authenticate();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return processor.handleBrowserException(e);
|
return processor.handleBrowserException(e);
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
|
||||||
import org.keycloak.common.Version;
|
import org.keycloak.common.Version;
|
||||||
import org.keycloak.encoding.ResourceEncodingHelper;
|
import org.keycloak.encoding.ResourceEncodingHelper;
|
||||||
import org.keycloak.encoding.ResourceEncodingProvider;
|
import org.keycloak.encoding.ResourceEncodingProvider;
|
||||||
|
@ -124,7 +123,7 @@ public class JsResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
String contentType = "text/javascript";
|
String contentType = "text/javascript";
|
||||||
Cors cors = Cors.add(session.getContext().getContextObject(HttpRequest.class)).allowAllOrigins();
|
Cors cors = Cors.add(session.getContext().getHttpRequest()).allowAllOrigins();
|
||||||
|
|
||||||
ResourceEncodingProvider encodingProvider = ResourceEncodingHelper.getResourceEncodingProvider(session, contentType);
|
ResourceEncodingProvider encodingProvider = ResourceEncodingHelper.getResourceEncodingProvider(session, contentType);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.TokenVerifier;
|
import org.keycloak.TokenVerifier;
|
||||||
import org.keycloak.authentication.AuthenticationFlowException;
|
import org.keycloak.authentication.AuthenticationFlowException;
|
||||||
|
@ -29,7 +29,6 @@ import org.keycloak.authentication.RequiredActionFactory;
|
||||||
import org.keycloak.authentication.RequiredActionProvider;
|
import org.keycloak.authentication.RequiredActionProvider;
|
||||||
import org.keycloak.authentication.actiontoken.ActionTokenContext;
|
import org.keycloak.authentication.actiontoken.ActionTokenContext;
|
||||||
import org.keycloak.authentication.actiontoken.ActionTokenHandler;
|
import org.keycloak.authentication.actiontoken.ActionTokenHandler;
|
||||||
import org.keycloak.common.util.Resteasy;
|
|
||||||
import org.keycloak.models.DefaultActionTokenKey;
|
import org.keycloak.models.DefaultActionTokenKey;
|
||||||
import org.keycloak.authentication.actiontoken.ExplainedTokenVerificationException;
|
import org.keycloak.authentication.actiontoken.ExplainedTokenVerificationException;
|
||||||
import org.keycloak.authentication.actiontoken.resetcred.ResetCredentialsActionTokenHandler;
|
import org.keycloak.authentication.actiontoken.resetcred.ResetCredentialsActionTokenHandler;
|
||||||
|
@ -177,8 +176,8 @@ public class LoginActionsService {
|
||||||
this.clientConnection = session.getContext().getConnection();
|
this.clientConnection = session.getContext().getConnection();
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.event = event;
|
this.event = event;
|
||||||
CacheControlUtil.noBackButtonCacheControlHeader();
|
CacheControlUtil.noBackButtonCacheControlHeader(session);
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,7 +701,7 @@ public class LoginActionsService {
|
||||||
|
|
||||||
processLocaleParam(authSession);
|
processLocaleParam(authSession);
|
||||||
|
|
||||||
AuthenticationManager.expireIdentityCookie(realm, session.getContext().getUri(), clientConnection);
|
AuthenticationManager.expireIdentityCookie(realm, session.getContext().getUri(), session);
|
||||||
|
|
||||||
return processRegistration(checks.isActionRequest(), execution, authSession, null);
|
return processRegistration(checks.isActionRequest(), execution, authSession, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,7 @@ import java.net.URI;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authentication.AuthenticationProcessor;
|
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
|
|
@ -18,8 +18,8 @@ package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.common.util.PemUtils;
|
import org.keycloak.common.util.PemUtils;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
@ -55,8 +55,8 @@ public class PublicRealmResource {
|
||||||
public PublicRealmResource(KeycloakSession session) {
|
public PublicRealmResource(KeycloakSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.response = session.getContext().getContextObject(HttpResponse.class);
|
this.response = session.getContext().getHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.AuthorizationService;
|
import org.keycloak.authorization.AuthorizationService;
|
||||||
|
@ -213,7 +213,7 @@ public class RealmsResource {
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response getVersionPreflight(final @PathParam("realm") String name,
|
public Response getVersionPreflight(final @PathParam("realm") String name,
|
||||||
final @PathParam("provider") String providerName) {
|
final @PathParam("provider") String providerName) {
|
||||||
return Cors.add(session.getContext().getContextObject(HttpRequest.class), Response.ok()).allowedMethods("GET").preflight().auth().build();
|
return Cors.add(session.getContext().getHttpRequest(), Response.ok()).allowedMethods("GET").preflight().auth().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -236,7 +236,7 @@ public class RealmsResource {
|
||||||
|
|
||||||
if (wellKnown != null) {
|
if (wellKnown != null) {
|
||||||
ResponseBuilder responseBuilder = Response.ok(wellKnown.getConfig()).cacheControl(CacheControlUtil.noCache());
|
ResponseBuilder responseBuilder = Response.ok(wellKnown.getConfig()).cacheControl(CacheControlUtil.noCache());
|
||||||
return Cors.add(session.getContext().getContextObject(HttpRequest.class), responseBuilder).allowedOrigins("*").auth().build();
|
return Cors.add(session.getContext().getHttpRequest(), responseBuilder).allowedOrigins("*").auth().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
|
@ -274,7 +274,7 @@ public class RealmsResource {
|
||||||
private void checkSsl(RealmModel realm) {
|
private void checkSsl(RealmModel realm) {
|
||||||
if (!session.getContext().getUri().getBaseUri().getScheme().equals("https")
|
if (!session.getContext().getUri().getBaseUri().getScheme().equals("https")
|
||||||
&& realm.getSslRequired().isRequired(session.getContext().getConnection())) {
|
&& realm.getSslRequired().isRequired(session.getContext().getConnection())) {
|
||||||
HttpRequest request = session.getContext().getContextObject(HttpRequest.class);
|
HttpRequest request = session.getContext().getHttpRequest();
|
||||||
Cors cors = Cors.add(request).auth().allowedMethods(request.getHttpMethod()).auth().exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS);
|
Cors cors = Cors.add(request).auth().allowedMethods(request.getHttpMethod()).auth().exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS);
|
||||||
throw new CorsErrorResponseException(cors.allowAllOrigins(), OAuthErrorException.INVALID_REQUEST, "HTTPS required",
|
throw new CorsErrorResponseException(cors.allowAllOrigins(), OAuthErrorException.INVALID_REQUEST, "HTTPS required",
|
||||||
Response.Status.FORBIDDEN);
|
Response.Status.FORBIDDEN);
|
||||||
|
|
|
@ -25,7 +25,7 @@ import javax.ws.rs.core.UriBuilder;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authentication.AuthenticationProcessor;
|
import org.keycloak.authentication.AuthenticationProcessor;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.common.util.ObjectUtil;
|
import org.keycloak.common.util.ObjectUtil;
|
||||||
|
@ -257,7 +257,7 @@ public class SessionCodeChecks {
|
||||||
// Allow refresh, but rewrite browser history
|
// Allow refresh, but rewrite browser history
|
||||||
if (execution == null && lastExecFromSession != null) {
|
if (execution == null && lastExecFromSession != null) {
|
||||||
logger.debugf("Parameter 'execution' is not in the request, but flow wasn't changed. Will update browser history");
|
logger.debugf("Parameter 'execution' is not in the request, but flow wasn't changed. Will update browser history");
|
||||||
request.setAttribute(BrowserHistoryHelper.SHOULD_UPDATE_BROWSER_HISTORY, true);
|
session.setAttribute(BrowserHistoryHelper.SHOULD_UPDATE_BROWSER_HISTORY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -262,14 +262,14 @@ public class WelcomeResource {
|
||||||
String stateChecker = Base64Url.encode(SecretGenerator.getInstance().randomBytes());
|
String stateChecker = Base64Url.encode(SecretGenerator.getInstance().randomBytes());
|
||||||
String cookiePath = session.getContext().getUri().getPath();
|
String cookiePath = session.getContext().getUri().getPath();
|
||||||
boolean secureOnly = session.getContext().getUri().getRequestUri().getScheme().equalsIgnoreCase("https");
|
boolean secureOnly = session.getContext().getUri().getRequestUri().getScheme().equalsIgnoreCase("https");
|
||||||
CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, stateChecker, cookiePath, null, null, 300, secureOnly, true);
|
CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, stateChecker, cookiePath, null, null, 300, secureOnly, true, session);
|
||||||
return stateChecker;
|
return stateChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expireCsrfCookie() {
|
private void expireCsrfCookie() {
|
||||||
String cookiePath = session.getContext().getUri().getPath();
|
String cookiePath = session.getContext().getUri().getPath();
|
||||||
boolean secureOnly = session.getContext().getUri().getRequestUri().getScheme().equalsIgnoreCase("https");
|
boolean secureOnly = session.getContext().getUri().getRequestUri().getScheme().equalsIgnoreCase("https");
|
||||||
CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, "", cookiePath, null, null, 0, secureOnly, true);
|
CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, "", cookiePath, null, null, 0, secureOnly, true, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void csrfCheck(final MultivaluedMap<String, String> formData) {
|
private void csrfCheck(final MultivaluedMap<String, String> formData) {
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
package org.keycloak.services.resources.account;
|
package org.keycloak.services.resources.account;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.common.enums.AccountRestApiVersion;
|
import org.keycloak.common.enums.AccountRestApiVersion;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
|
@ -60,8 +60,8 @@ public class AccountLoader {
|
||||||
public AccountLoader(KeycloakSession session, EventBuilder event) {
|
public AccountLoader(KeycloakSession session, EventBuilder event) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.response = session.getContext().getContextObject(HttpResponse.class);
|
this.response = session.getContext().getHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/")
|
@Path("/")
|
||||||
|
@ -69,7 +69,7 @@ public class AccountLoader {
|
||||||
RealmModel realm = session.getContext().getRealm();
|
RealmModel realm = session.getContext().getRealm();
|
||||||
ClientModel client = getAccountManagementClient(realm);
|
ClientModel client = getAccountManagementClient(realm);
|
||||||
|
|
||||||
HttpRequest request = session.getContext().getContextObject(HttpRequest.class);
|
HttpRequest request = session.getContext().getHttpRequest();
|
||||||
HttpHeaders headers = session.getContext().getRequestHeaders();
|
HttpHeaders headers = session.getContext().getRequestHeaders();
|
||||||
MediaType content = headers.getMediaType();
|
MediaType content = headers.getMediaType();
|
||||||
List<MediaType> accepts = headers.getAcceptableMediaTypes();
|
List<MediaType> accepts = headers.getAcceptableMediaTypes();
|
||||||
|
|
|
@ -49,7 +49,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.common.enums.AccountRestApiVersion;
|
import org.keycloak.common.enums.AccountRestApiVersion;
|
||||||
|
@ -124,7 +124,7 @@ public class AccountRestService {
|
||||||
this.locale = session.getContext().resolveLocale(user);
|
this.locale = session.getContext().resolveLocale(user);
|
||||||
this.version = version;
|
this.version = version;
|
||||||
event.client(auth.getClient()).user(auth.getUser());
|
event.client(auth.getClient()).user(auth.getUser());
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.headers = session.getContext().getRequestHeaders();
|
this.headers = session.getContext().getRequestHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.keycloak.services.resources.account;
|
package org.keycloak.services.resources.account;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.services.resources.Cors;
|
import org.keycloak.services.resources.Cors;
|
||||||
|
|
||||||
import javax.ws.rs.OPTIONS;
|
import javax.ws.rs.OPTIONS;
|
||||||
|
|
|
@ -37,7 +37,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.broker.social.SocialIdentityProvider;
|
import org.keycloak.broker.social.SocialIdentityProvider;
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.model.PermissionTicket;
|
import org.keycloak.authorization.model.PermissionTicket;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
|
|
@ -34,7 +34,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authorization.model.PermissionTicket;
|
import org.keycloak.authorization.model.PermissionTicket;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.models.AccountRoles;
|
import org.keycloak.models.AccountRoles;
|
||||||
|
|
|
@ -34,7 +34,7 @@ import java.util.function.BiFunction;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authorization.model.PermissionTicket;
|
import org.keycloak.authorization.model.PermissionTicket;
|
||||||
import org.keycloak.authorization.store.PermissionTicketStore;
|
import org.keycloak.authorization.store.PermissionTicketStore;
|
||||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||||
|
|
|
@ -19,8 +19,8 @@ package org.keycloak.services.resources.admin;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import javax.ws.rs.NotFoundException;
|
import javax.ws.rs.NotFoundException;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
|
@ -85,8 +85,8 @@ public class AdminConsole {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.clientConnection = session.getContext().getConnection();
|
this.clientConnection = session.getContext().getConnection();
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.response = session.getContext().getContextObject(HttpResponse.class);
|
this.response = session.getContext().getHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class WhoAmI {
|
public static class WhoAmI {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.keycloak.services.resources.admin;
|
package org.keycloak.services.resources.admin;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.services.resources.Cors;
|
import org.keycloak.services.resources.Cors;
|
||||||
|
|
||||||
import javax.ws.rs.OPTIONS;
|
import javax.ws.rs.OPTIONS;
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
package org.keycloak.services.resources.admin;
|
package org.keycloak.services.resources.admin;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import javax.ws.rs.NotFoundException;
|
import javax.ws.rs.NotFoundException;
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
|
@ -258,11 +258,11 @@ public class AdminRoot {
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpResponse getHttpResponse() {
|
private HttpResponse getHttpResponse() {
|
||||||
return session.getContext().getContextObject(HttpResponse.class);
|
return session.getContext().getHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequest getHttpRequest() {
|
private HttpRequest getHttpRequest() {
|
||||||
return session.getContext().getContextObject(HttpRequest.class);
|
return session.getContext().getHttpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Theme getTheme(KeycloakSession session, RealmModel realm) throws IOException {
|
public static Theme getTheme(KeycloakSession session, RealmModel realm) throws IOException {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.services.resources.admin;
|
package org.keycloak.services.resources.admin;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.events.admin.OperationType;
|
import org.keycloak.events.admin.OperationType;
|
||||||
import org.keycloak.events.admin.ResourceType;
|
import org.keycloak.events.admin.ResourceType;
|
||||||
import org.keycloak.models.ClientInitialAccessModel;
|
import org.keycloak.models.ClientInitialAccessModel;
|
||||||
|
@ -84,10 +84,10 @@ public class ClientInitialAccessResource {
|
||||||
String token = ClientRegistrationTokenUtils.createInitialAccessToken(session, realm, clientInitialAccessModel);
|
String token = ClientRegistrationTokenUtils.createInitialAccessToken(session, realm, clientInitialAccessModel);
|
||||||
rep.setToken(token);
|
rep.setToken(token);
|
||||||
|
|
||||||
HttpResponse response = session.getContext().getContextObject(HttpResponse.class);
|
HttpResponse response = session.getContext().getHttpResponse();
|
||||||
|
|
||||||
response.setStatus(Response.Status.CREATED.getStatusCode());
|
response.setStatus(Response.Status.CREATED.getStatusCode());
|
||||||
response.getOutputHeaders().add(HttpHeaders.LOCATION, session.getContext().getUri().getAbsolutePathBuilder().path(clientInitialAccessModel.getId()).build().toString());
|
response.addHeader(HttpHeaders.LOCATION, session.getContext().getUri().getAbsolutePathBuilder().path(clientInitialAccessModel.getId()).build().toString());
|
||||||
|
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.representations.idm.ClientPoliciesRepresentation;
|
import org.keycloak.representations.idm.ClientPoliciesRepresentation;
|
||||||
|
@ -52,8 +52,8 @@ public class ClientPoliciesResource {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.auth = auth;
|
this.auth = auth;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.response = session.getContext().getContextObject(HttpResponse.class);
|
this.response = session.getContext().getHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
|
|
@ -28,8 +28,8 @@ import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.representations.idm.ClientProfilesRepresentation;
|
import org.keycloak.representations.idm.ClientProfilesRepresentation;
|
||||||
|
@ -53,8 +53,8 @@ public class ClientProfilesResource {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.realm = session.getContext().getRealm();
|
this.realm = session.getContext().getRealm();
|
||||||
this.auth = auth;
|
this.auth = auth;
|
||||||
this.request = session.getContext().getContextObject(HttpRequest.class);
|
this.request = session.getContext().getHttpRequest();
|
||||||
this.response = session.getContext().getContextObject(HttpResponse.class);
|
this.response = session.getContext().getHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
|
|
@ -324,8 +324,8 @@ public class UserResource {
|
||||||
if (authenticatedRealm.getId().equals(realm.getId()) && sessionState != null) {
|
if (authenticatedRealm.getId().equals(realm.getId()) && sessionState != null) {
|
||||||
sameRealm = true;
|
sameRealm = true;
|
||||||
UserSessionModel userSession = lockUserSessionsForModification(session, () -> session.sessions().getUserSession(authenticatedRealm, sessionState));
|
UserSessionModel userSession = lockUserSessionsForModification(session, () -> session.sessions().getUserSession(authenticatedRealm, sessionState));
|
||||||
AuthenticationManager.expireIdentityCookie(realm, session.getContext().getUri(), clientConnection);
|
AuthenticationManager.expireIdentityCookie(realm, session.getContext().getUri(), session);
|
||||||
AuthenticationManager.expireRememberMeCookie(realm, session.getContext().getUri(), clientConnection);
|
AuthenticationManager.expireRememberMeCookie(realm, session.getContext().getUri(), session);
|
||||||
AuthenticationManager.backchannelLogout(session, authenticatedRealm, userSession, session.getContext().getUri(), clientConnection, headers, true);
|
AuthenticationManager.backchannelLogout(session, authenticatedRealm, userSession, session.getContext().getUri(), clientConnection, headers, true);
|
||||||
}
|
}
|
||||||
EventBuilder event = new EventBuilder(realm, session, clientConnection);
|
EventBuilder event = new EventBuilder(realm, session, clientConnection);
|
||||||
|
|
|
@ -24,7 +24,7 @@ import java.util.regex.Pattern;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||||
import org.keycloak.utils.MediaType;
|
import org.keycloak.utils.MediaType;
|
||||||
|
@ -54,12 +54,12 @@ public abstract class BrowserHistoryHelper {
|
||||||
public abstract Response loadSavedResponse(KeycloakSession session, AuthenticationSessionModel authSession);
|
public abstract Response loadSavedResponse(KeycloakSession session, AuthenticationSessionModel authSession);
|
||||||
|
|
||||||
|
|
||||||
protected boolean shouldReplaceBrowserHistory(boolean actionRequest, HttpRequest httpRequest) {
|
protected boolean shouldReplaceBrowserHistory(boolean actionRequest, KeycloakSession session) {
|
||||||
if (actionRequest) {
|
if (actionRequest) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Boolean flowChanged = (Boolean) httpRequest.getAttribute(SHOULD_UPDATE_BROWSER_HISTORY);
|
Boolean flowChanged = (Boolean) session.getAttribute(SHOULD_UPDATE_BROWSER_HISTORY);
|
||||||
return (flowChanged != null && flowChanged);
|
return (flowChanged != null && flowChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ public abstract class BrowserHistoryHelper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response saveResponseAndRedirect(KeycloakSession session, AuthenticationSessionModel authSession, Response response, boolean actionRequest, HttpRequest httpRequest) {
|
public Response saveResponseAndRedirect(KeycloakSession session, AuthenticationSessionModel authSession, Response response, boolean actionRequest, HttpRequest httpRequest) {
|
||||||
if (!shouldReplaceBrowserHistory(actionRequest, httpRequest)) {
|
if (!shouldReplaceBrowserHistory(actionRequest, session)) {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ public abstract class BrowserHistoryHelper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response saveResponseAndRedirect(KeycloakSession session, AuthenticationSessionModel authSession, Response response, boolean actionRequest, HttpRequest httpRequest) {
|
public Response saveResponseAndRedirect(KeycloakSession session, AuthenticationSessionModel authSession, Response response, boolean actionRequest, HttpRequest httpRequest) {
|
||||||
if (!shouldReplaceBrowserHistory(actionRequest, httpRequest)) {
|
if (!shouldReplaceBrowserHistory(actionRequest, session)) {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
|
|
||||||
package org.keycloak.services.util;
|
package org.keycloak.services.util;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.common.util.Resteasy;
|
import org.keycloak.models.KeycloakContext;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
import javax.ws.rs.core.CacheControl;
|
import javax.ws.rs.core.CacheControl;
|
||||||
|
|
||||||
|
@ -28,9 +29,10 @@ import javax.ws.rs.core.CacheControl;
|
||||||
*/
|
*/
|
||||||
public class CacheControlUtil {
|
public class CacheControlUtil {
|
||||||
|
|
||||||
public static void noBackButtonCacheControlHeader() {
|
public static void noBackButtonCacheControlHeader(KeycloakSession session) {
|
||||||
HttpResponse response = Resteasy.getContextData(HttpResponse.class);
|
KeycloakContext context = session.getContext();
|
||||||
response.getOutputHeaders().putSingle("Cache-Control", "no-store, must-revalidate, max-age=0");
|
HttpResponse response = context.getHttpResponse();
|
||||||
|
response.setHeader("Cache-Control", "no-store, must-revalidate, max-age=0");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CacheControl getDefaultCacheControl() {
|
public static CacheControl getDefaultCacheControl() {
|
||||||
|
|
|
@ -18,10 +18,11 @@
|
||||||
package org.keycloak.services.util;
|
package org.keycloak.services.util;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.jboss.resteasy.util.CookieParser;
|
import org.jboss.resteasy.util.CookieParser;
|
||||||
import org.keycloak.common.util.Resteasy;
|
import org.keycloak.common.util.Resteasy;
|
||||||
import org.keycloak.common.util.ServerCookie;
|
import org.keycloak.common.util.ServerCookie;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
import javax.ws.rs.core.Cookie;
|
import javax.ws.rs.core.Cookie;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
@ -55,7 +56,7 @@ public class CookieHelper {
|
||||||
* @param httpOnly
|
* @param httpOnly
|
||||||
* @param sameSite
|
* @param sameSite
|
||||||
*/
|
*/
|
||||||
public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly, SameSiteAttributeValue sameSite) {
|
public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly, SameSiteAttributeValue sameSite, KeycloakSession session) {
|
||||||
SameSiteAttributeValue sameSiteParam = sameSite;
|
SameSiteAttributeValue sameSiteParam = sameSite;
|
||||||
// when expiring a cookie we shouldn't set the sameSite attribute; if we set e.g. SameSite=None when expiring a cookie, the new cookie (with maxAge == 0)
|
// when expiring a cookie we shouldn't set the sameSite attribute; if we set e.g. SameSite=None when expiring a cookie, the new cookie (with maxAge == 0)
|
||||||
// might be rejected by the browser in some cases resulting in leaving the original cookie untouched; that can even prevent user from accessing their application
|
// might be rejected by the browser in some cases resulting in leaving the original cookie untouched; that can even prevent user from accessing their application
|
||||||
|
@ -65,15 +66,15 @@ public class CookieHelper {
|
||||||
|
|
||||||
boolean secure_sameSite = sameSite == SameSiteAttributeValue.NONE || secure; // when SameSite=None, Secure attribute must be set
|
boolean secure_sameSite = sameSite == SameSiteAttributeValue.NONE || secure; // when SameSite=None, Secure attribute must be set
|
||||||
|
|
||||||
HttpResponse response = Resteasy.getContextData(HttpResponse.class);
|
HttpResponse response = session.getContext().getHttpResponse();
|
||||||
StringBuffer cookieBuf = new StringBuffer();
|
StringBuffer cookieBuf = new StringBuffer();
|
||||||
ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, comment, maxAge, secure_sameSite, httpOnly, sameSite);
|
ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, comment, maxAge, secure_sameSite, httpOnly, sameSite);
|
||||||
String cookie = cookieBuf.toString();
|
String cookie = cookieBuf.toString();
|
||||||
response.getOutputHeaders().add(HttpHeaders.SET_COOKIE, cookie);
|
response.addHeader(HttpHeaders.SET_COOKIE, cookie);
|
||||||
|
|
||||||
// a workaround for browser in older Apple OSs – browsers ignore cookies with SameSite=None
|
// a workaround for browser in older Apple OSs – browsers ignore cookies with SameSite=None
|
||||||
if (sameSiteParam == SameSiteAttributeValue.NONE) {
|
if (sameSiteParam == SameSiteAttributeValue.NONE) {
|
||||||
addCookie(name + LEGACY_COOKIE, value, path, domain, comment, maxAge, secure, httpOnly, null);
|
addCookie(name + LEGACY_COOKIE, value, path, domain, comment, maxAge, secure, httpOnly, null, session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,23 +89,23 @@ public class CookieHelper {
|
||||||
* @param secure
|
* @param secure
|
||||||
* @param httpOnly
|
* @param httpOnly
|
||||||
*/
|
*/
|
||||||
public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
|
public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly, KeycloakSession session) {
|
||||||
addCookie(name, value, path, domain, comment, maxAge, secure, httpOnly, null);
|
addCookie(name, value, path, domain, comment, maxAge, secure, httpOnly, null, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Set<String> getCookieValue(String name) {
|
public static Set<String> getCookieValue(KeycloakSession session, String name) {
|
||||||
Set<String> ret = getInternalCookieValue(name);
|
Set<String> ret = getInternalCookieValue(session, name);
|
||||||
if (ret.size() == 0) {
|
if (ret.size() == 0) {
|
||||||
String legacy = name + LEGACY_COOKIE;
|
String legacy = name + LEGACY_COOKIE;
|
||||||
logger.debugv("Could not find any cookies with name '{0}', trying '{1}'", name, legacy);
|
logger.debugv("Could not find any cookies with name '{0}', trying '{1}'", name, legacy);
|
||||||
ret = getInternalCookieValue(legacy);
|
ret = getInternalCookieValue(session, legacy);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<String> getInternalCookieValue(String name) {
|
private static Set<String> getInternalCookieValue(KeycloakSession session, String name) {
|
||||||
HttpHeaders headers = Resteasy.getContextData(HttpHeaders.class);
|
HttpHeaders headers = session.getContext().getHttpRequest().getHttpHeaders();
|
||||||
Set<String> cookiesVal = new HashSet<>();
|
Set<String> cookiesVal = new HashSet<>();
|
||||||
|
|
||||||
// check for cookies in the request headers
|
// check for cookies in the request headers
|
||||||
|
|
|
@ -7,7 +7,7 @@ import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
package org.keycloak.services.util;
|
package org.keycloak.services.util;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpResponse;
|
import org.keycloak.http.HttpResponse;
|
||||||
import org.keycloak.common.util.Resteasy;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IE requires P3P header to allow loading cookies from iframes when domain differs from main page (see KEYCLOAK-2828 for more details)
|
* IE requires P3P header to allow loading cookies from iframes when domain differs from main page (see KEYCLOAK-2828 for more details)
|
||||||
|
@ -27,9 +27,9 @@ import org.keycloak.common.util.Resteasy;
|
||||||
*/
|
*/
|
||||||
public class P3PHelper {
|
public class P3PHelper {
|
||||||
|
|
||||||
public static void addP3PHeader() {
|
public static void addP3PHeader(KeycloakSession session) {
|
||||||
HttpResponse response = Resteasy.getContextData(HttpResponse.class);
|
HttpResponse response = session.getContext().getHttpResponse();
|
||||||
response.getOutputHeaders().putSingle("P3P", "CP=\"This is not a P3P policy!\"");
|
response.setHeader("P3P", "CP=\"This is not a P3P policy!\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
package org.keycloak.services.x509;
|
package org.keycloak.services.x509;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.util.PemException;
|
import org.keycloak.common.util.PemException;
|
||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
package org.keycloak.services.x509;
|
package org.keycloak.services.x509;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,8 +34,6 @@ public class DefaultClientCertificateLookup implements X509ClientCertificateLook
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DefaultClientCertificateLookup.class);
|
private static final Logger logger = Logger.getLogger(DefaultClientCertificateLookup.class);
|
||||||
|
|
||||||
public static final String JAVAX_SERVLET_REQUEST_X509_CERTIFICATE = "javax.servlet.request.X509Certificate";
|
|
||||||
|
|
||||||
public DefaultClientCertificateLookup() {
|
public DefaultClientCertificateLookup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +45,7 @@ public class DefaultClientCertificateLookup implements X509ClientCertificateLook
|
||||||
@Override
|
@Override
|
||||||
public X509Certificate[] getCertificateChain(HttpRequest httpRequest) {
|
public X509Certificate[] getCertificateChain(HttpRequest httpRequest) {
|
||||||
|
|
||||||
X509Certificate[] certs = (X509Certificate[]) httpRequest.getAttribute(JAVAX_SERVLET_REQUEST_X509_CERTIFICATE);
|
X509Certificate[] certs = httpRequest.getClientCertificateChain();
|
||||||
if (logger.isTraceEnabled() && certs != null) {
|
if (logger.isTraceEnabled() && certs != null) {
|
||||||
for (X509Certificate cert : certs) {
|
for (X509Certificate cert : certs) {
|
||||||
logger.tracef("Certificate's SubjectDN => \"%s\"", cert.getSubjectDN().getName());
|
logger.tracef("Certificate's SubjectDN => \"%s\"", cert.getSubjectDN().getName());
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.logging.Logger.Level;
|
import org.jboss.logging.Logger.Level;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.crypto.CryptoIntegration;
|
import org.keycloak.common.crypto.CryptoIntegration;
|
||||||
import org.keycloak.common.util.PemException;
|
import org.keycloak.common.util.PemException;
|
||||||
import org.keycloak.common.util.PemUtils;
|
import org.keycloak.common.util.PemUtils;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.keycloak.services.x509;
|
package org.keycloak.services.x509;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.common.util.PemException;
|
import org.keycloak.common.util.PemException;
|
||||||
import org.keycloak.common.util.PemUtils;
|
import org.keycloak.common.util.PemUtils;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
package org.keycloak.services.x509;
|
package org.keycloak.services.x509;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
|
|
@ -13,7 +13,7 @@ AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationF
|
||||||
* user - current user {@see org.keycloak.models.UserModel}
|
* user - current user {@see org.keycloak.models.UserModel}
|
||||||
* realm - current realm {@see org.keycloak.models.RealmModel}
|
* realm - current realm {@see org.keycloak.models.RealmModel}
|
||||||
* session - current KeycloakSession {@see org.keycloak.models.KeycloakSession}
|
* session - current KeycloakSession {@see org.keycloak.models.KeycloakSession}
|
||||||
* httpRequest - current HttpRequest {@see org.jboss.resteasy.spi.HttpRequest}
|
* httpRequest - current HttpRequest {@see org.keycloak.http.HttpRequest}
|
||||||
* script - current script {@see org.keycloak.models.ScriptModel}
|
* script - current script {@see org.keycloak.models.ScriptModel}
|
||||||
* authenticationSession - current authentication session {@see org.keycloak.sessions.AuthenticationSessionModel}
|
* authenticationSession - current authentication session {@see org.keycloak.sessions.AuthenticationSessionModel}
|
||||||
* LOG - current logger {@see org.jboss.logging.Logger}
|
* LOG - current logger {@see org.jboss.logging.Logger}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue