Skip to content

Commit 4da5ec2

Browse files
davidblasbydavid-blasby
authored andcommitted
OAuth2 OpenId Connect Documentation (#201)
* wip: openid connect dox * for OPENIDCONNECT_ROLECONVERTER, changed format from ':' to '=' as separator * add doc for oidc bearer tokens * feedback from jose * add doc for OPENIDCONNECT_LOGINTYPE * add info about OPENIDCONNECT_SERVERMETADATA_CONFIG_URL * update doc for default scopes * add doc for OPENIDCONNECT_LOGSENSITIVE_INFO Co-authored-by: david.blasby <[email protected]>
1 parent 4a6b273 commit 4da5ec2

File tree

1 file changed

+318
-1
lines changed

1 file changed

+318
-1
lines changed

source/administrator-guide/managing-users-and-groups/authentication-mode.rst

Lines changed: 318 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ However there are some other authentication mechanisms available:
1010
- :ref:`authentication-ldap`
1111
- :ref:`authentication-ldap-hierarchy`
1212
- :ref:`authentication-cas`
13+
- :ref:`authentication-openid`
1314
- :ref:`authentication-keycloak`
1415
- :ref:`authentication-shibboleth`
1516

@@ -325,7 +326,7 @@ Before you start configuring, you will need to know;
325326
Configuring LDAP Beans (Hierarchy)
326327
==================================
327328

328-
GeoNetwork comes with a sample LDAP configuration that you can use in Apache Directory Studio to create the same LDAP server used in the test cases. There is also a sample GeoNetwork configuration that connects to this LDAP server. Please see the `README.md <https://github.com/geonetwork/core-geonetwork/blob/master/core/src/test/resources/org/fao/geonet/kernel/security/ldap/README.md>`_ or the `video developer chat <https://www.youtube.com/watch?v=f8rvbEdnE-g>`_ for instructions.
329+
GeoNetwork comes with a sample LDAP configuration that you can use in Apache Directory Studio to create the same LDAP server used in the test cases. There is also a sample GeoNetwork configuration that connects to this LDAP server. Please see :repo:`core-geonetwork/blob/master/core/src/test/resources/org/fao/geonet/kernel/security/ldap/README.md` or the `video developer chat <https://www.youtube.com/watch?v=f8rvbEdnE-g>`_ for instructions.
329330

330331
.. note:: To use this configuration, uncomment the "<import resource="config-security-ldap-recursive.xml"/>" line in `web/src/main/webapp/WEB-INF/config-security/config-security.xml`
331332

@@ -510,6 +511,322 @@ You can configure your environment by updating the previous file or by defining
510511
cas.login.url=${cas.baseURL}/login
511512
cas.logout.url=${cas.baseURL}/logout?url=${geonetwork.https.url}/
512513
514+
515+
.. _authentication-openid:
516+
517+
Configuring OAUTH2 OpenID Connect
518+
---------------------------------
519+
520+
`OAUTH2 OpenID Connect <https://openid.net/connect/>`_ is an authentication and authorization system based on OAUTH2. Geonetwork's OpenID Connect plugin has been tested with `Keycloak <https://keycloak.org>`_ and `Azure AD <https://azure.microsoft.com/en-ca/services/active-directory/>`_, but should work with any provider.
521+
522+
Basic Setup Steps:
523+
524+
#. Configure your IDP Server (i.e. Keycloak or Azure AD)
525+
526+
#. Ensure that the ID Token provides role/group information
527+
#. Authorize your Geonetwork URLs for redirects (i.e. `http://localhost:8080/geonetwork/login/oauth2/code/geonetwork-oicd`)
528+
#. Record the Client ID
529+
#. Record the Client Secret
530+
#. Get the Server's JSON metadata document
531+
532+
#. Configure Geonetwork via environment variables
533+
534+
#. `GEONETWORK_SECURITY_TYPE=openidconnect`
535+
#. `OPENIDCONNECT_CLIENTSECRET=...` (from your IDP server)
536+
#. `OPENIDCONNECT_CLIENTID=...` (from your IDP server)
537+
#. `OPENIDCONNECT_SERVERMETADATA_JSON_TEXT='...'` (the text of your Server's JSON metadata document)
538+
#. `OPENIDCONNECT_IDTOKENROLELOCATION=...` (location of the user's roles in the ID Token)
539+
540+
541+
542+
Geonetwork's Open ID Connect plugin has a lot of configuration options - please see the ``WEB-INF/config-security/config-security-openidconnect.xml`` and ``WEB-INF/config-security/config-security-openidconnect-overrides.properties`` files.
543+
544+
545+
Environment Variable and Meaning
546+
================================
547+
548+
**GEONETWORK_SECURITY_TYPE**
549+
550+
Should be `openidconnect`.
551+
552+
**OPENIDCONNECT_CLIENTID**
553+
554+
The name of the client/application you configured on your OpenID server.
555+
556+
**OPENIDCONNECT_CLIENTSECRET**
557+
558+
The `client secret` you configured on your OpenID server.
559+
560+
**OPENIDCONNECT_SERVERMETADATA_CONFIG_URL**
561+
562+
URL to the external OIDC server's JSON metadata document. This is typically at `/.well-known/openid-configuration` on the IDP server.
563+
564+
.. note:: This will download the server's configuration everytime GeoNetwork starts up, which could be a security concern. For security, use a `https` URL.
565+
566+
**OPENIDCONNECT_SERVERMETADATA_JSON_TEXT**
567+
568+
Should be the text of your OpenID server's metadata configuration (JSON).
569+
570+
**OPENIDCONNECT_SERVERMETADATA_FNAME**
571+
572+
Instead of putting the OpenID server's metadata configuration as text in a variable (`OPENIDCONNECT_SERVERMETADATA_JSON_TEXT`), you can put the JSON contents in a file and reference it with this variable (ie. ``/WEB-INF/config-security/openid-configuration.json``)
573+
574+
**OPENIDCONNECT_IDTOKENROLELOCATION**
575+
576+
Where, in the ID Token, are the users roles/groups stored (i.e. "groups", "roles", or "resource_access.gn-key.roles")
577+
578+
**OPENIDCONNECT_ROLECONVERTER**
579+
580+
This provides simple role conversion from the OpenID server to Geonetwork roles.
581+
582+
ie. `"GeonetworkAdmin=Administrator,GeonetworkEditor=Editor"`
583+
584+
This will convert "GeonetworkAdmin" (from the OpenID Server) to the Geonetwork "Administrator" role.
585+
586+
.. note:: Like the keycloak plugin, you can use role/group names of the form "group:role" to assign a user to Geonetwork group and permission level.
587+
588+
**OPENIDCONNECT_MINIMUMPROFILE**
589+
590+
Every user who authenticates against the OpenID server will be given this role.
591+
592+
Default is `"RegisteredUser"`.
593+
594+
**OPENIDCONNECT_USERPROFILEUPDATEENABLED**
595+
596+
When a user logs on, update their Geotwork profile from the OpenID server's ID Token.
597+
598+
Default is `"true"`.
599+
600+
**OPENIDCONNECT_USERGROUPUPDATEENABLED**
601+
602+
When a user logs on, update their Geotwork group/role permissions.
603+
604+
Default is `"true"`.
605+
606+
**OPENIDCONNECT_SCOPES**
607+
608+
Limit the requested scope access to the OpenID server.
609+
610+
Default "openid email profile", and "openid email profile offline_access" (for bearer tokens).
611+
612+
**OPENIDCONNECT_LOGINTYPE**
613+
614+
How Geonetwork deals with users who are not logged on.
615+
616+
Default is "LINK" - users can click on the "login" link on the main page.
617+
618+
"AUTOLOGIN" - No login form provided which will automatically login the user when possible.
619+
620+
**OPENIDCONNECT_LOGSENSITIVE_INFO**
621+
622+
"true" or "false" (default)
623+
624+
Logs: CODE, ACCESS TOKEN, ID TOKEN, userinfo endpoint result, and calculated GeoNetwork authorities.
625+
626+
LOGGING THIS INFORMATION IS PROBABLY A SECURITY AND PERSONAL INFORMATION RISK.
627+
DO NOT TURN THIS ON IN A SYSTEM THAT IS ACTUALLY BEING USED.
628+
629+
We try not to log very sensitive information - we don't log the full access or id token (just the claims part).
630+
We log the single-use CODE, but it should have already been deactivated by the server before we log it.
631+
632+
The access token, userinfo, and id token contain sensitive information (i.e. real names, email address, etc...)
633+
634+
Configuration for a Keycloak Server
635+
===================================
636+
637+
638+
It's outside the scope of this document to fully describe the steps to configure keycloak, but this should serve as a guide.
639+
640+
This will configure keycloak backed by **another OpenID IDP** (for example, by an Azure AD). In keycloak:
641+
642+
#. Create a realm (i.e. `myrealm`)
643+
#. Create an openid client (i.e. `myclient`). This is your ClientID.
644+
645+
#. Root URL: `http://localhost:7777/geonetwork` (this is the GN root URL)
646+
#. Valid Redirect URIs: `http://localhost:7777/geonetwork/*`
647+
#. Access Type: Confidential
648+
#. On the `Credentials` tab, get the secret (this is your Client Secret)
649+
#. On the `Roles` tab, create some roles: Administrator, Editor, Reviewer, RegisteredGuest
650+
651+
#. Create your backing Identity Provider (i.e. to another OpenID server). Or you can configure users directly in keycloak.
652+
653+
#. At the bottom of the page, choose "import from URL" and import the backing server's configuration location.
654+
#. Add the Client Secret (from the backing service)
655+
#. Add the Client ID (from the backing service)
656+
#. set "Client Authentication" to "Client secret sent as post"
657+
658+
#. Configure role translation
659+
660+
#. Edit the "Identity Provider" you just created, and go to the "Mappers" tab.
661+
#. Press "Create" and and add a "Claim to Role".
662+
#. Set Sync Mode Override to "Force"
663+
#. Claim: `roles`
664+
#. Claim Value: `name of the administrator role in the backing IDP`
665+
#. Role: choose the "Administrator" role from the `myclient` client.
666+
#. Repeat the above for Administrator, Editor, Reviewer, and RegisteredGuest
667+
668+
#. Configure details for your backing IDP
669+
670+
#. Edit the "Identity Provider" you just configured
671+
#. On the Mappers tab, "Add Builtin" and tick "client roles (User Client Role)" then "Add selected"
672+
#. Edit the "client roles" mapper and make sure "Add to ID token" and "Add to userinfo" are on
673+
674+
675+
676+
You should have Keycloak's Client id ("myclient") and the client secret. The configuration JSON is available at `https://YOUR_KEYCLOAK_HOST/realms/{YOUR REALM NAME}/.well-known/openid-configuration```
677+
678+
Your environment variables will looks like this:
679+
680+
.. code-block:: properties
681+
682+
GEONETWORK_SECURITY_TYPE=openidconnect
683+
OPENIDCONNECT_CLIENTSECRET='...'
684+
OPENIDCONNECT_CLIENTID='...'
685+
OPENIDCONNECT_SERVERMETADATA_JSON_TEXT='...big json text...'
686+
OPENIDCONNECT_IDTOKENROLELOCATION='resource_access.{your client id}.roles'
687+
688+
689+
Azure AD Configuration
690+
======================
691+
692+
There are two ways to setup Azure AD. The first is with user and groups (a more traditional LDAP method) or with Application Roles.
693+
694+
With Users and Groups
695+
``````````````````````
696+
697+
Setup the Azure Application:
698+
699+
#. Create a new `App Registration`
700+
#. use "http://localhost:8080/geonetwork/login/oauth2/code/geonetwork-oicd" as a redirect URIs
701+
#. On the "Certificates & Secrets" add a new secret and record it (make sure you get the secret value and NOT the object id)
702+
#. Make sure the groups are in the ID token - on the "Manifest" tab, edit the JSON so that "groupMembershipClaims": "SecurityGroup" is set
703+
#. On the summary page, get the Application (client) ID
704+
#. On the summary page, choose "Endpoints" (at the top) and get the JSON text from the "OpenID Connect metadata document" Endpoints
705+
706+
Setup users and groups:
707+
708+
#. In Azure AD, go to groups
709+
#. Add new Groups - "geonetworkAdmin", "geonetworkReviewer", etc... Record the name and the group's **Object ID**
710+
#. Edit a User, and choose Groups, and add them to appropriate group.
711+
712+
713+
Your environment variables will looks like this:
714+
715+
.. code-block:: properties
716+
717+
GEONETWORK_SECURITY_TYPE=openidconnect
718+
OPENIDCONNECT_CLIENTSECRET='...'
719+
OPENIDCONNECT_CLIENTID='...'
720+
OPENIDCONNECT_SERVERMETADATA_JSON_TEXT='...big json text...'
721+
OPENIDCONNECT_IDTOKENROLELOCATION='groups'
722+
OPENIDCONNECT_ROLECONVERTER='3a94275f-7d53-4205-8d78-11f39e9ffa5a=Administrator,d93c6444-feee-4b67-8c0f-15d6796370cb=Reviewer'
723+
724+
725+
.. note:: The roles are in the "roles" part of the ID Token.
726+
727+
728+
.. note:: The OPENIDCONNECT_ROLECONVERTER converts the Azure AD Group's Object ID to a Geonetwork Role.
729+
730+
731+
With Application Roles
732+
``````````````````````
733+
734+
Setup the Azure Application:
735+
736+
#. Create a new Enterprise application
737+
#. use "http://localhost:8080/geonetwork/login/oauth2/code/geonetwork-oicd" as a redirect URIs
738+
#. On the "Certificates & Secrets" add a new secret and record it (make sure you get the secret value and NOT the object id)
739+
#. Make sure the groups are in the ID token - on the "Manifest" tab, edit the JSON so that "groupMembershipClaims": "ApplicationGroup" is set
740+
#. On the summary page, get the Application (client) ID
741+
#. On the summary page, choose "Endpoints" (at the top) and get the JSON text from the "OpenID Connect metadata document" Endpoints
742+
743+
Setup Application Roles:
744+
745+
#. In Application you created, go to "App Roles".
746+
#. Add new Groups - "Editor", "Reviewer", etc...
747+
748+
Assign Users:
749+
750+
#. Go to Azure AD, Enterprise Application, then the application you created
751+
#. Choose "Assign users and groups"
752+
#. Press the "Add user/group" (top)
753+
#. Press "None Selected" (under Users) and choose some users
754+
#. Press "None Selected" (Under Select a Role) and choose some roles
755+
#. Configure all your users with roles
756+
757+
758+
Your environment variables will looks like this:
759+
760+
.. code-block:: properties
761+
762+
GEONETWORK_SECURITY_TYPE=openidconnect
763+
OPENIDCONNECT_CLIENTSECRET='...'
764+
OPENIDCONNECT_CLIENTID='...'
765+
OPENIDCONNECT_SERVERMETADATA_JSON_TEXT='...big json text...'
766+
OPENIDCONNECT_IDTOKENROLELOCATION='roles'
767+
768+
.. note:: The roles are in the "roles" part of the ID Token.
769+
770+
771+
.. note:: You don't typically have to do any role conversion since the role name will be used in the ID Token.
772+
773+
.. _OIDC Bearer Tokens:
774+
775+
OIDC Bearer Tokens
776+
==================
777+
778+
Bearer Tokens are also supported - you can attach the JWT Bearer token to any request by setting the HTTP header like this:
779+
780+
.. code-block:: properties
781+
782+
Authorization: Bearer: <JWT token>
783+
784+
Bearer Tokens are mostly used for automated (desktop or application) API calls - real users should just login normally using OIDC.
785+
786+
#. Setup your OIDC configuration (see :ref:`authentication-openid`)
787+
#. Setup the OIDC Bearer token configuration (see :ref:`Bearer Token Configuration`)
788+
#. Obtain a Bearer token from the OIDC server. This is the hard part and there are several ways to do this. One way that is used is via the OAuth 2.0 Device Authorization Grant ("Device Flow") workflow.
789+
#. Attach it to your request headers (see :ref:`OIDC Bearer Tokens`)
790+
#. Make protected requests to the Geonetwork API
791+
792+
This has been tested with Keycloak and with Azure AD. It should work with other JWT-based OIDC services.
793+
794+
Validation
795+
``````````
796+
797+
The token is validated in three major ways:
798+
799+
#. The bearer token will be used to access the `userinfo` ("token validation") endpoint specified in the OIDC configuration. This means the IDP validates the token (at the very least its signature and expiry).
800+
#. The bearer token (JWT) will be checked that the audience for it is the same as our configurated OIDC configuration. This will ensure that someone isn't getting a token from a different service and attempting to use it here. See `AudienceAccessTokenValidator.java`
801+
#. The bearer token (JWT) will be checked that the subject of the JWT and the `userinfo` (returned from the IDP) are the same. This shouldnt be a problem in our use-case, but the OAUTH2 specification recommends this check. See `SubjectAccessTokenValidator.java`
802+
803+
.. _Bearer Token Configuration:
804+
805+
Configuration
806+
`````````````
807+
808+
Configure OIDC as above - ensure this is working.
809+
810+
Instead of using ``GEONETWORK_SECURITY_TYPE=openidconnect``, use ``GEONETWORK_SECURITY_TYPE=openidconnectbearer``.
811+
812+
Inside ``WEB-INF/config-security/config-security-openidconnectbearer.xml``:
813+
814+
#. If you are using keycloak (configured with Groups in the `userinfo` response), then uncomment the `UserInfoAccessTokenRolesResolver` bean and comment out the `MSGraphUserRolesResolver` bean.
815+
#. If you are using Azure AD (MS Graph API for the user's groups), then then uncomment the `MSGraphUserRolesResolver` bean and comment out the `UserInfoAccessTokenRolesResolver` bean.
816+
817+
The easiest way to test is to obtain a Bearer Token, and then use a browser plugin to add the `Authorization: Bearer <token>` header to all requests. When you visit the Geonetwork website, you should see yourself logged in with the appropriate permissions.
818+
819+
Other Providers
820+
```````````````
821+
822+
This has been tested with Azure AD (groups in the MS Graph API) and KeyCloak (groups in the `userinfo`).
823+
824+
For other IDP, you might have to make some modifications.
825+
826+
#. Make sure the `AudienceAccessTokenValidator` and `SubjectAccessTokenValidator` work correctly for your JWT bearer tokens.
827+
#. Make sure that the user's groups are available - see the `UserRolesResolver` interface and its two implementations - `UserInfoAccessTokenRolesResolver` and `MSGraphUserRolesResolver`.
828+
829+
513830
.. _authentication-keycloak:
514831

515832
Configuring Keycloak

0 commit comments

Comments
 (0)