I'm using Spring Security 2.x's Preauthentication with X.509 certificates.
I get the certificateText via HttpServletRequest.getAttribute("CERTIFICATE").
Sometimes, the above call returns "" (empty). I believe it occurs when the HTTP session has expired.
What would explain why HttpServletRequest.getAttribute("CERT") returns empty?
EDIT In Kerberos, for example, the ticket is available in every HTTP request. Is the cert not always in X.509 HTTP requests?
Please access to certificate using this code:
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
Certificate is always populated to request after successful client certificate authentication.
Ensure your support long certificate chain:
Add the max_packet_size propery to the worker.properties file
worker.ajp13w.max_packet_size=65536
Add the packetSize propery to the configuration of Ajp connector in the Tomcat configuration \conf\server.xml
<Connector port="8089"
enableLookups="false" redirectPort="8443" protocol="AJP/1.3" packetSize="65536"/>
Apache logs:
http://httpd.apache.org/docs/2.2/logs.html#accesslog
http://httpd.apache.org/docs/2.2/logs.html#errorlog
http://httpd.apache.org/docs/2.2/mod/core.html#loglevel
Related
I'm trying to setup Apache Guacamole with KeyCloak as OpenID Connect Authorization Server.
Guacamole is redirecting me to KeyCloak, I can Log in with my user I created on KeyCloak and I get redirected back to Guacamole, but there it says that my token is invalid
08:08:11.477 [http-nio-4432-exec-7] INFO o.a.g.a.o.t.TokenValidationService - Rejected invalid OpenID token: Unable to process JOSE object (cause: org.jose4j.lang.UnresolvableKeyException: Unable to find a suitable verification key for JWS w/ header {"alg":"RS256","typ" : "JWT","kid" : "8ZNpgh_vnmG0HMMNYdOz1lw4ECoWxmsiUGte1mJfvyI"} due to an unexpected exception (javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty) while obtaining or using keys from JWKS endpoint at https://172.16.47.229:12345/auth/realms/Guacamole-test/protocol/openid-connect/certs): JsonWebSignature{"alg":"RS256","typ" : "JWT","kid" : "8ZNpgh_vnmG0HMMNYdOz1lw4ECoWxmsiUGte1mJfvyI"}->eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4Wk5wZ2hfdm5tRzBITU1OWWRPejFsdzRFQ29XeG1zaVVHdGUxbUpmdnlJIn0.eyJleHAiOjE2MDIzOTczODgsImlhdCI6MTYwMjM5NjQ4OCwiYXV0aF90aW1lIjoxNjAyMzk2NDcwLCJqdGkiOiI5Y2RiZDVjZC01MDJhLTRjNmItYTM3Mi1jZDIxMTNjNTE1NTMiLCJpc3MiOiJodHRwczovLzE3Mi4xNi40Ny4yMjk6MTIzNDUvYXV0aC9yZWFsbXMvR3VhY2Ftb2xlLXRlc3QiLCJhdWQiOiJHdWFjYW1vbGUiLCJzdWIiOiI1YzQ3N2NiZC04ZjIzLTRlMjEtYmNhMi1kMzNlMTRhZGY0ZDYiLCJ0eXAiOiJJRCIsImF6cCI6Ikd1YWNhbW9sZSIsIm5vbmNlIjoiaTQyZDBpZTc4c2s0MjRjMHJzMmJvdTM4YnUiLCJzZXNzaW9uX3N0YXRlIjoiMjNlZjdhMTYtMDhhNS00YTNkLTgxYTItYTQ2ZmE1NmM1NjE3IiwiYWNyIjoiMCIsImlzX3N1cGVydXNlciI6IlRydWUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJ0ZXN0IHRlc3QiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0dXNlciIsImdpdmVuX25hbWUiOiJ0ZXN0IiwiZmFtaWx5X25hbWUiOiJ0ZXN0IiwiZW1haWwiOiJ0ZXN0QHRlc3QuY29tIn0.eOhkDqcgfdJnO12PRDqLIHACRNVdVHoSDFjThHWc6Ug1gdoz9t_T2K7F_B6dJSbNygAJrGvc5BVRx9XCJH1fVFSYhpXVqCO0jrHm0XJKhw_kBce4x3ZluGAtktx614j9qFzUwZHXOkFAUGPtyPQKuRTfdzHqQUILLJhVdSRPmou40rX31-l7VwqWZk_Yp1JCdQsA61XvJcQrU_aiKivZFaDGiY5GrnpL8zcEwJcFemptVoGKrG63O_LjxDCxhLpO1C1fi8GjngMSfco9aAp4AaGpHWy8ofJAu-TWbLGf-UPLUhC3lf903-Q_BU3eehYxtMyN1eet0HeGm0x_gV_wvA
In KeyCloak I created a Client as follows:
(Will change the Valid Redirect URI`s once I have it working)
And my guacamole.properites look like this:
guacd-port: 4822
guacd-hostname: localhost
# OpenID Connect Properties
openid-authorization-endpoint: https://172.16.47.229:12345/auth/realms/Guacamole-test/protocol/openid-connect/auth
openid-jwks-endpoint: https://172.16.47.229:12345/auth/realms/Guacamole-test/protocol/openid-connect/certs
openid-issuer: https://172.16.47.229:12345/auth/realms/Guacamole-test
openid-client-id: Guacamole
openid-redirect-uri: http://172.16.47.229:4432/guacamole/
# Postgresql Properties
postgresql-hostname: 172.16.47.229
postgresql-port: 4444
postgresql-database: guacamoledb
postgresql-username: guacamoleuser
postgresql-password: test
What do I have to change for guacamole to accept the token?
Update: I found the configuration to be working, if I use KeyCloak with HTTP instead of HTTPS, but that is not desirable. I have now also configured Guacamole, or more precisely the tomcat that's hosting guacamole, to use https, but I still can not get it to work (without having to use HTTP for KeyCloak).
I've caught the same issue. Most probably you just have to provide valid SSL certificate for your IdP (Keycloak).
Possible workaround was found here: How to configure Keycloak to work with Guacamole's OpenID plugin?.
I've re-compiled guacamole-auth-openid extension with this change:
diff --git a/extensions/guacamole-auth-openid/src/main/java/org/apache/guacamole/auth/openid/token/TokenValidationService.java b/extensions/guacamole-auth-openid/src/main/java/org/apache/guacamole/auth/openid/token/TokenValidationService.java
index 5efb09dab..27d818ee5 100644
--- a/extensions/guacamole-auth-openid/src/main/java/org/apache/guacamole/auth/openid/token/TokenValidationService.java
+++ b/extensions/guacamole-auth-openid/src/main/java/org/apache/guacamole/auth/openid/token/TokenValidationService.java
## -79,6 +79,7 ## public class TokenValidationService {
// Create JWT consumer for validating received token
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
+ .setSkipSignatureVerification()
.setRequireExpirationTime()
.setMaxFutureValidityInMinutes(confService.getMaxTokenValidity())
.setAllowedClockSkewInSeconds(confService.getAllowedClockSkew())
And this solved the issue. Don't think it's applicable for production needs but in production self-signed certificates should not be used.
With Guacamole 1.4.0 and Keycloak 15.0.2 I fixed the HTTPS issue by mounting a custom cacerts keystore in the the Guacamole container. This custom keystore is just the OpenJDK 8 cacerts with Let's Encrypt CA bundle https://letsencrypt.org/certs/isrgrootx1.pem imported. Because my Keycloak and Guacamole instance use Let's Encrypt certificates.
On the host I had OpenJDK 8 installed. So Docker mount was
/etc/ssl/certs/java/cacerts:/usr/local/openjdk-8/jre/lib/security/cacerts
I am trying to run schema registry server with SSL authentication but while starting the server
./schema-registry-start ../etc/schema-registry/schema-registry.properties
I keep on getting :
[2019-11-29 15:20:13,778] ERROR Error starting the schema registry (io.confluent.kafka.schemaregistry.rest.SchemaRegistryRestApplication:67)
io.confluent.kafka.schemaregistry.exceptions.SchemaRegistryException: No listener configured with requested scheme SSL
io.confluent.kafka.schemaregistry.storage.KafkaSchemaRegistry.getSchemeAndPortForIdentity(KafkaSchemaRegistry.java:210)
But I have the listeners,broker everything configured
kafkastore.bootstrap.servers=SSL://<my-brokers>
security.protocol=SSL
ssl.truststore.location=/home/ec2-user/kafka.client.truststore.jks
ssl.keystore.location=/home/ec2-user/kafka.client.keystore.jks
ssl.keystore.password=my-pass
ssl.key.password=my-key
listeners=https://0.0.0.0:443
ssl.enabled.protocols=TLSv1.2
ssl.client.auth=fals
schema.registry.inter.instance.protocol=SSL
schema.registry.url=https://<IP>:443
You'll want to verify the listeners of the brokers
Then, security protocol itself isn't valid, plus the inter instance protocol of the registry should be https, not SSL
https://docs.confluent.io/current/schema-registry/installation/config.html
Plus, you have a typo on ssl.client.auth=false, and schema.registry.url is a client setting only, not on the server
From client (eg: https://localhost:8080/) we are passing the certificate related values and calling the rest services ( hosted on different port - https://localhost:446/serviceName).
The issue is like, when we try to pass the certificate , SSL handshake is happening correctly (no error on debug) , but the certificate value is not passed to the service hosted on another port. Certificate value is accessed in server code by referring to (X509Certificate)httpReq.getAttribute("javax.servlet.request.X509Certificate");
Note : We use Spring boot application which intenally runs on tomcat server.And desired CA authorised certificates, keystore and truststore are present in resource path in both the projects (client and service hosted). In rest service project config file, the client-auth is set to false.
Sample code snippet used to call rest service:
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(restserviceTruststore)
.loadKeyMaterial(restserviceKeyStore, password).build();
HttpClient client = HttpClients.custom() .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSslcontext(sslContext).build();
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(client));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<String> request = new HttpEntity<>(XML, headers);
response = restTemplate.postForObject(endpointURL, request, String.class);
Question:
1) From client what keystore and trustore should we need to pass to SSLContext? Is it server's keystore /truststore or clients?
2)What are the exact steps to be followed to resolve this issue.
When user clicks login, redirected to Keycloak login page & then after successful login, user comes back to application with 400 error page.
Server log shows following:
[Server:node-00] 13:40:00,709 WARN
[org.keycloak.adapters.OAuthRequestAuthenticator] (default task-30)
state parameter invalid
My application conf is:
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
<secure-deployment name="appWEB.war">
<realm>demo</realm>
<resource>app</resource>
<public-client>true</public-client>
<auth-server-url>http://localhost:8180/auth</auth-server-url>
<ssl-required>EXTERNAL</ssl-required>
</secure-deployment>
</subsystem>
Application URL is https://localhost:8443/app & redirect_url is https://localhost:8443/app/private.jsf.
When I use http, it works. But the error comes when I use same with https.
Any thoughts?
Here it can be many scenario which may failing with https
Keycloak running in https
Create self sign certification for keycloak.
Import this certificate to your local Java environment.SO handshake can be possible.
I hope you generate the certificates in keycloak you can find the the certificate inside keycloak/security/ssl.
We have a simple requirement where:
PS: https:/ === https://
When user hits https:/company_landing.company.com , they should be redirected to keycloak login page (at https:/ourcompany-keycloak.company.com). User enters his/her keycloak login credentials. Upon successful login to keycloak , they will be presented to the company_landing page.
The trouble is :
When User types - https:/company_landing.company.com
Keycloak tries to bring up the landing page but gives 500 Internal server error and says "Incorrect redirect uri" and in the browser I see this:
https:/ourcompany-keycloak.company.com/auth/realms/realm1/tokens/login?client_id=company_dev&state=aaaafffff-559d-4312-a8be-123412341234&redirect_uri=http%3A%2F%2Fcompany_landing.company.com%3A8081%2F%3Fauth_callback%3D1
If you observe the redirect uri above, I think the problem is that instead of https the redirect uri starts with http and http:/company-landing.company.com doesn't exist.
Settings:
keycloak settings: -
Realm --> settings --> login : Require SSL = all Requests (tried with "external" also)
Applications-->realm1-->settings-->Redirect URI = https://company_landing.company.com/*
AWS load balancer:
Port config: 443(https) forwarding to 8443
I am confused as to why it is stripping the SSL? The above works fine when testing on local environment(probably because its http://localhost) but this always gives an invalid redirect url when trying to access any link that is ssl encrypted.
-mm
You have to add the following property in the proxy configuration json file, (by default proxy.json) as an application attribute (same level as "adapter-config"):
"proxy-address-forwarding" : true,
This configuration attribute is not documented, however present in the sources of the proxy configuration: https://github.com/keycloak/keycloak/blob/master/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java
You don't need a certificate to be installed or use changes in adapter config.
This needs to be done in your standalone.xml, standalone-ha or domain.xml (as the case may be) as documented in the Keycloak document reverse proxy section https://www.keycloak.org/docs/latest/server_installation/index.html#_setting-up-a-load-balancer-or-proxy
Assuming that your reverse proxy doesn’t use port 8443 for SSL you also need to configure what port HTTPS traffic is redirected to.
<subsystem xmlns="urn:jboss:domain:undertow:4.0">
...
<http-listener name="default" socket-binding="http"
proxy-address-forwarding="true" redirect-socket="proxy-https"/>
...
</subsystem>
Add the redirect-socket attribute to the http-listener element. The value should be proxy-https which points to a socket binding you also need to define.
Then add a new socket-binding element to the socket-binding-group element:
<socket-binding-group name="standard-sockets" default-interface="public"
port-offset="${jboss.socket.binding.port-offset:0}">
...
<socket-binding name="proxy-https" port="443"/>
...
</socket-binding-group>