Open JoseSanchezMoralesIDOX opened 1 year ago
Hi,
I've been unable to reproduce your issue.
I created a jetty HTTPS:
a. follow this answer https://stackoverflow.com/a/31241196
b. You will need to change the
Then, mvn jetty:run ...
(as normal) and go to https://localhost:8443/geonetwork/
when I click on the "signin" link, it gets (correctly) redirected to https://localhost:8443/geonetwork/signin
This will then redirect you to your OIDC provider with the correct redirect_uri=https://localhost:8443/geonetwork/login/oauth2/code/geonetwork-oicd
.
The http/https detection is provided by your application container (i.e. jetty), and is handled inside spring.
signin
url (i.e. https://localhost:8443/geonetwork/signin). The response will be a redirect to your OIDC provider.
b. request to your OIDC provider. You should see a redirect_uri=https://localhost:8443/geonetwork/login/oauth2/code/geonetwork-oicd
in the URL.Also, make sure that you access your GN with "https" and not "http" (if you have both configured).
RE: OPENIDCONNECT_IDTOKENROLELOCATION
From the documentation (https://geonetwork-opensource.org/manuals/4.0.x/en/administrator-guide/managing-users-and-groups/authentication-mode.html#authentication-openid):
Where, in the ID Token, are the users roles/groups stored (i.e. “groups”, “roles”, or “resource_access.gn-key.roles”)
In MS Azure (groups-based), it is "groups"
In MS Azure (roles-based), it is "roles"
In KeyCloak, it is "resource_access.gn-key.roles" (where gn-key
is your client name).
Basically, look at your ID token (provided by your OIDC) system and find the list of roles in it. OPENIDCONNECT_IDTOKENROLELOCATION
will be the path to that list.
Here is an example ID Token (from azure);
{
"aud": "b9e8d05a-08b6-48a5-81c8-9590a0f550f3",
"iss": "https://login.microsoftonline.com/87f91494-c0dc-493e-83c3-9226c111850a/v2.0",
...
"email": "david.blasby@geocat.net",
"groups": [
"d93c6444-feee-4b67-8c0f-15d6796370cb",
"3a94275f-7d53-4205-8d78-11f39e9ffa5a",
"a9c82c77-dc4d-48a0-8286-22dcb992f18d",
"fced5395-6be6-436c-a7f9-5c638cbdeb20"
],
"name": "david blasby",
...
"preferred_username": "david.blasby at geocat.net",
"roles": [
"Administrator"
],
...
}
This ID token is setup with roles and groups. If your roles are in the roles
section, use OPENIDCONNECT_IDTOKENROLELOCATION=roles
, if its in the groups section, use OPENIDCONNECT_IDTOKENROLELOCATION=groups
.
NOTE: for azure (with groups), you have to use something like OPENIDCONNECT_ROLECONVERTER=3a94275f-7d53-4205-8d78-11f39e9ffa5a=Administrator
because azure stores groups as UUIDS instead of group names.
If your ID token has the roles/groups nested inside other objects, you can navigate into sections of the token with ".". This is needed for keycloak because it put the roles 3 levels deep (resource_access.gn-key.roles
) in the ID token.
Thanks,
1.- Accessing GN using 'https' in the browser works, it is the sign in (authentication)
2.- We are using Jetty, no Maven, no Tomcat, and a docker-compose file to launch GN, Kibana, NGNIX and Elastic Search all together.
3.- I have found the pom.xml into the /var/lib/jetty/webapps/geonetwork/META-INF/maven/org.geonetwork-opensource/gn-web-app
folder, but inside the pom.xml file the piece of code to replace is missing.
4.- Version is 4.2.2
5.- The variables: GEONETWORK_SECURITY_TYPE (openidconnect), OPENIDCONNECT_CLIENTSECRET, OPENIDCONNECT_CLIENTID, OPENIDCONNECT_SERVERMETADATA_CONFIG_URL and OPENIDCONNECT_IDTOKENROLELOCATION are configured inside the docker-compose file
6.- Again, the redirect param displays:
redirect_uri=http://<domain>/geonetwork/login/oauth2/code/geonetwork-oicd&nonce=xxx......
However, if I copy the requested url in a new browser tab, and manually replace http by https, I got this error:
7.- We are using a linux ec2 machine, where the https port (443) is open for inbound connections
are you using NGIX as a reverse proxy?
If you try to re-use the code (in the url), the login will fail - its a one-time-use code. So, your error is expected.
I've tested this with jetty 9.4 and it was working - how are you using NGIX in your configuration?
My instructions were for running GN4 from the command line (i.e. from source code).
are you using NGIX as a reverse proxy?
If you try to re-use the code (in the url), the login will fail - its a one-time-use code. So, your error is expected.
I've tested this with jetty 9.4 and it was working - how are you using NGIX in your configuration?
My instructions were for running GN4 from the command line (i.e. from source code).
My ngnix.conf:
events { }
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name <domain.com>;
return 301 https://<domain.com>$request_uri;
}
server {
listen 443 ssl;
server_name <domain.com>;
ssl_certificate /ssl/<cert_name>.crt;
ssl_certificate_key /ssl/<cert_name>.key;
access_log /var/log/nginx/data-access.log combined;
location / {
proxy_pass http://geonetwork:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect http://geonetwork:8080/ $scheme://$http_host/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 20d;
proxy_buffering off;
}
}
}
Then, the ngnix part within the docker-compose:
www:
image: nginx:latest
ports:
- 80:80
- 443:443
# environment:
# # Only used for / redirect to default webapp
# - NGINX_PUBLIC_HOST=195.201.225.214
# #- NGINX_PUBLIC_HOST=apps.titellus.net
# - NGINX_HOST=195.201.225.214
# - NGINX_PORT=80
volumes:
- /opt/nginx/conf.d:/etc/nginx/conf.d
- /opt/nginx/nginx.conf:/etc/nginx/nginx.conf
- /usr/local/share/ca-certificates:/ssl/
depends_on:
- geonetwork
networks:
- gn-network
The idea of using NGNIX was simply because of a viable way of using the SSL certificates. And actually it is in the official examples for launching GN as part of a docker-compose with other services.
I hope the above helps, really appreciate your input, thanks
If you are using NGNIX to handle the SSL certificate, you are likely using it as a reverse proxy. That means that GN only sees http
connections - thats how its getting http
as the url schema.
Currently, GN uses the request (which will be a http
- NOT https
- in your case) to form the redirect URL. I think a redirect-override configuration to GN would be required.
At least, that's my interpretation....
I am leaving out the openid issue for now, and concentrating in the https/ssl one. So, I am back to the default authentication method in Geonetwork.
At the moment, the site loads under https in the browser, but the internal URLs can fail (i.e. signing out)
Interestingly, if I use this in the nginx.conf:
proxy_redirect http://geonetwork:8080/ $scheme://$http_host/;
The associated URL to the Sign out button becomes:
https://domain.com/geonetwork/signout?redirectUrl=https://domain.com/geonetwork/srv
which doesn't work, as gives time-out in the browser while re-converting itself into:
http://domain.com/geonetwork/?node=srv
On the other hand, if I do:
proxy_redirect off;
the Sign out button encapsulates the same URL, so it doesn't make sense, does it?:
https://domain.com/geonetwork/signout?redirectUrl=https://domain.com/geonetwork/srv
Perhaps, the above redirectUrl is internal to GN configuration, not related to NGinx?
I am wondering what is failing in my NGINX SET UP.
This is my nginx.conf:
events { }
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name domain.com;
return 301 https://domain$request_uri;
}
server {
listen 443 ssl;
server_name domain.com;
ssl_certificate /ssl/domain.crt;
ssl_certificate_key /ssl/domain.key;
access_log /var/log/nginx/data-access.log combined;
location / {
proxy_pass http://geonetwork:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off; #http://geonetwork:8080/ $scheme://$http_host/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 20d;
proxy_buffering off;
}
}
}
@davidblasby I'm trying to deploy a GeoNetwork server with OAuth (Azure AD) using the modified default Geonetwork docker-compose.yml
. I have added SSL handling in NGINX, but GN still redirects to an HTTP URL.
Do you have an idea of how to deploy GN properly? NGINX seems to be a pain in the ass with the HTTP handling for GN.
My current hypothesis is that since we use the default GN image container, it comes in a Jetty image that does not support the HTTPS request nor properly handle the HTTP into HTTPS redirect (as you explained); thus, URLs are not properly handled.
Is there a way to inject configuration to Jetty in the docker image?
Is there anything that can be configured in the Docker container for Jetty to use https callback url for OIDC?
Not that I know of right now. My guess would be to inject a new configuration at the Jetty using the volumes in the docker entrypoint. But not sure how to do this.
I have the same issue: GN redirects under HTTP instead of HTTPS. Is there any update on this thread?
The redirect URI is formed from the last request (not the original request to your proxy) received by the Jetty server. As @davidblasby mentioned, GN uses this request, either HTTP or HTTPS, to form the redirect URI.
The GN official docker image (v4.4.x or v4.2.x) relies on Jetty with HTTP at default port 8080. To enable HTTPS for Jetty 9.4, you can, 1) Enable modules by adding ssl.ini (--module=ssl) and https.ini (--module=https) files to /var/lib/jetty/start.d/ 2) Import your SSL certificate into your keystore. 3) Update ports, path, password, etc., in your ssl.ini.
I updated official image with a self-signed certificate, jingking/geonetwork-hnap:4.2.8 Then set up nginx as reverse proxy,
proxy_pass "https://localhost:8443";
The redirect URI works as expected.
Is there anything that can be configured in the Docker container for Jetty to use https callback url for OIDC?
I managed to get this working by enabling Jetty's http-forwarded module. I have geonetwork behind an Apache reverse proxy which sets X-Forwarded HTTP headers:
RemoteIPHeader X-Forwarded-For
RequestHeader set "X-Forwarded-Proto" "https"
ProxyPass /geonetwork/ http://geonetwork:8080/geonetwork/
ProxyPassReverse /geonetwork/ http://geonetwork:8080/geonetwork/
For my Docker container build I created an http-forwarded.ini file (copied content from ini-template section of container file /usr/local/jetty/modules/http-forwarded.mod, then added the --module line):
# ---------------------------------------
# Module: http-forwarded
# Adds a forwarded request customizer to the HTTP Connector
# to process forwarded-for style headers from a proxy.
# ---------------------------------------
--module=http-forwarded
### ForwardedRequestCustomizer Configuration
## If true, only the RFC7239 Forwarded header is accepted
# jetty.httpConfig.forwardedOnly=false
## if true, the proxy address obtained from X-Forwarded-Server or RFC7239 is used as the request authority.
# jetty.httpConfig.forwardedProxyAsAuthority=false
## if true, the X-Forwarded-Port header applies to the authority, else it applies to the remote client address
# jetty.httpConfig.forwardedPortAsAuthority=true
# jetty.httpConfig.forwardedHeader=Forwarded
# jetty.httpConfig.forwardedHostHeader=X-Forwarded-Host
# jetty.httpConfig.forwardedServerHeader=X-Forwarded-Server
# jetty.httpConfig.forwardedProtoHeader=X-Forwarded-Proto
# jetty.httpConfig.forwardedForHeader=X-Forwarded-For
# jetty.httpConfig.forwardedPortHeader=X-Forwarded-Port
# jetty.httpConfig.forwardedHttpsHeader=X-Proxied-Https
# jetty.httpConfig.forwardedSslSessionIdHeader=Proxy-ssl-id
# jetty.httpConfig.forwardedCipherSuiteHeader=Proxy-auth-cert
...then added http-forwarded.ini in my Dockerfile:
FROM geonetwork:4.4.2
COPY http-forwarded.ini /var/lib/jetty/start.d/http-forwarded.ini
OAuth2 OpenID Connect now works using https redirect URL.
After successfully implemented the install of SSL certificates in the server, Geonetwork can now be accessed through https://domain/geonetwork
However, when clicking on the 'Sign in' button, an error is displayed on the screen showing the following URL:
http://domain/geonetwork/login/oauth2/code/geonetwork-oicd
So, the above URL is using http instead, not https, not sure why, or if this misconfiguration is causing the OpenID Connect to fail.
I have changed in the database the values for
system/server/port
andsystem/server/protocol
but these ones do not seem to have any effect in the above error.Besides, the parameter:
OPENIDCONNECT_IDTOKENROLELOCATION
not sure how to configure it, where could I find an example of this value?Thanks,