I am running a JEE app on a Wildfly server behind an Apache reverse proxy. Using the keycloak-client-adapter it connects to a Keycloak server also behind a apache reverse proxy. Both reverse proxies terminate the SSL connecion and connect to the Wildfly server by http.
When I am opening the JEE app, I am redirected to Keycloak and after I have entered my password I am also redirect to my app - all on SSL through the reverse proxy. But then I get a 403 - the reason for this: The App Wildfly tries to connect to Keycloak to validate the token on http. This is neither allowed ("ssl-required": "all" in keycloak.json and setup in realm) nor is http active at all.
From the app wildfly server.log
Adapter requires SSL. Request: http://www.domain.tld/myapp/
I have setup the reverse proxy of Keycloak according to the documentation, .well-known/openid-configuration looks good - all URLs are https
keycloak.json
{
"realm": "myrealm",
"auth-server-url": "https://sso.domain.tld/auth",
"ssl-required": "all",
"resource": "myresource",
"verify-token-audience": true,
"credentials": {
"secret": "secret"
},
"use-resource-role-mappings": true,
"confidential-port": 443,
"policy-enforcer": {}
}
Settings of the reverse proxy for the app
ProxyPreserveHost On
ProxyPass /myapp http://127.0.0.1:8080/myapp
ProxyPassReverse /myapp https://www.domain.tld/myapp
Anyone an idea how to force https on the validation? That should be the last step to get the setup running.
Related
This is related to keycloak clients. My frontend is connected to public client and backend is connected to confidential client.
I am able to login, get the code, as I am using response_type=code by turning on "Standard Flow Enabled".
This code redirects and returns me Idtoken, refreshtoken and token.
Now I need to communicate with backend which is confidential, I would like to authenticate user using some of the values which I have received from the frontend client.
How can I do that?
Here is my frontend and backend conf
FRONTEND
{
"realm": "xyz",
"auth-server-url": "http://localhost:8333/auth/",
"ssl-required": "external",
"resource": "frontend-app",
"public-client": true,
"confidential-port": 0,
"enable-cors": true
}
BACKEND
keycloak.auth-server-url=http://localhost:8333/auth
keycloak.realm=xyz
keycloak.resource=backend-app
keycloak.principal-attribute=preferred_username
keycloak.bearer-only=true
keycloak.credentials.secret=xxx-xxx-xxx
this is from realm setting
This might help somebody.
My backend service which is springboot project with spring security keycloakAuthenticationProvider does authenticate the token received from the frontend public client.
Call from frontend
axios({
method: 'GET',
url: '/api/authenticate',
headers:{'Authorization': 'Bearer '+keycloak.token+''}
}).then((r) => {
console.log("response",r)
})
Call to backend
#GetMapping("/api/authenticate")
public ResponseEntity<SecureUserDto> authenticate() {
String username = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
User user = userRepository.findWithPrivilegesByUsername(username);
return ResponseEntity.ok();
}
But i still was not able to get it right on postman at ../token end point provided by keycloak server.
Anyways my work is done.
I have the following allowed redirect uri set for my client: exp://192.168.2.212:19000
After a code exchange using the following URL:
GET /auth/realms/xxxxx/protocol/openid-connect/auth?code_challenge=m71Cl...D4hw&redirect_uri=exp%3A%2F%2F192.168.2.212%3A19000&client_id=3B03...
X-Forwarded-For: 178.84.x.x
X-Forwarded-Host: oidc.production.my.domain.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 09918a799a23
X-Real-Ip: 178.84.x.x
I get a HTTP/1.1 302 Found with the following Location field:
Location: exp://192.168.2.212?state=T0pvzPyHF6&session_state=b1cf16ad-b.....
The port is missing. My (Expo) client in android emulator then barfs about not being able to connect to 192.168.2.212 port 80. Naturally.
I am using the docker hub images 11.0.0
How can I prevent this? Is it a bug?
(The iOS version of my app uses a different redirect_uri (exp://127.0.0.1:19000), but although Keycloak strips the port there as well and it receives a Location: exp://127.0.0.1?state=T0p... it does connect to port 19000 and works fine for some reason.)
EDIT: Note that authentication works fine on iOS, and I run exactly the same Keycloak settings in iOS as Android (It's a React Native application).
Keycloak logs no error, and the following debug message:
13:24:33,365 DEBUG [org.keycloak.events] (default task-47) type=LOGIN, realmId=neemop, clientId=3B03FD35, userId=28619cd3-c51d-4756-9d06-fb47********, ipAddress=178.84.x.x, auth_method=openid-connect, auth_type=code, response_type=code, redirect_uri=exp://192.168.2.212:19000, consent=no_consent_required, code_id=a0faa4d4-6826-4c2f-9243-*******, response_mode=query, username=ron.arts#mydomain.com, authSessionParentId=a0faa4d4-6826-4c2f-9243-*******, authSessionTabId=-Pn******
shows the redirect_uri is parsed correctly. It's just that in the actual HTTP response the Location: header omits the port. Which imho should not happen.
Seems like a bug: https://issues.redhat.com/browse/KEYCLOAK-9405?_sscc=t
Tested on 12.0.4 and it still occurs. It appears to be an issue with any non-http(s) protocol
another bug has been submitted to keycloak team:
https://issues.redhat.com/browse/KEYCLOAK-17141
a fix is available in keycloak version >= 13.0.0
I have two projects, one with documentation and one as the actual app.
When I access http://localhost:3000/docs my webpack setup is redirecting me to another server which is on http://localhost:4000 and where the documentation lives.
The redirect is happening but when it tries to load dependencies (.js, .css) the request is made on the original port (3000) and not the port 4000.
How can I redirect the server requests for the second website?
My webpack setup:
proxy: {
"/docs/**": {
target: "http://localhost:8080",
pathRewrite: { "^/docs": "" },
changeOrigin: true,
secure: false,
}
}
I have one problem when i am configuring 2 way SSL (client certificate) with mod_cluster on wildfly 9.0.2
-Direct connection on wildfly on port 8443 (like https://wildflyserver:8443/context) is working,
-AJP connector connection between apache and wildfly and mod_cluster is not working
-There is no HTTPS connector ?
<mod-cluster-config advertise-socket="modcluster" proxies="mc-proxy1" advertise="false" connector="http-default">
<dynamic-load-provider>
<load-metric type="cpu"/>
</dynamic-load-provider>
<ssl key-alias="aofweb" password="XXXXXX" certificate-key-file="${jboss.domain.config.dir}/keystoreWeb.jks" cipher-suite="ALL" protocol="TLSv1" ca-certificate-file="${jboss.domain.config.dir}/keystoreWeb.jks"/>
</mod-cluster-config>
-When i am using http redirect to https with web.xml configuration and redirect-socket binding the URL changes from https://apacheserver/context to https://wildflyserver:8443/context, if i had a directive preserveProxyhost it does'nt work too,
anybody have a solution ?
i manage to do it , i configure "ajp" connection , in listener scheme https,
in case of in httpd listener certificate-forwarding=true and redirection on https,
in web.xml auth-method to CLIENT-CERT and transport-guarantee to CONFIDENTIAL,
and then the most important in apache, client verification mandatory and forward cert data :
SSLHonorCipherOrder on
SSLVerifyClient require
SSLVerifyDepth 10
#THE CA USED TO GENERATE CLIENT CERTIFICATE
SSLCACertificateFile /etc/httpd/certs/cacert.pem
SSLOptions +ExportCertData
SSLOptions +StdEnvVars
Require all granted
tell me if you have problem :
widlfy 9.0
apache 2.4
mod_proxy_ajp
mod_ssl
mod_proxy
modcluster 1.3.1
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>