Skip to content

Commit

Permalink
Revert "OAuth2 OpenId Connect Documentation (#201)"
Browse files Browse the repository at this point in the history
This reverts commit 1d7c733.
  • Loading branch information
josegar74 committed Dec 12, 2022
1 parent 0d8a524 commit 308bd3f
Showing 1 changed file with 1 addition and 318 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ However there are some other authentication mechanisms available:
- :ref:`authentication-ldap`
- :ref:`authentication-ldap-hierarchy`
- :ref:`authentication-cas`
- :ref:`authentication-openid`
- :ref:`authentication-keycloak`
- :ref:`authentication-shibboleth`

Expand Down Expand Up @@ -326,7 +325,7 @@ Before you start configuring, you will need to know;
Configuring LDAP Beans (Hierarchy)
==================================

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.
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.

.. 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`

Expand Down Expand Up @@ -511,322 +510,6 @@ You can configure your environment by updating the previous file or by defining
cas.login.url=${cas.baseURL}/login
cas.logout.url=${cas.baseURL}/logout?url=${geonetwork.https.url}/
.. _authentication-openid:

Configuring OAUTH2 OpenID Connect
---------------------------------

`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.

Basic Setup Steps:

#. Configure your IDP Server (i.e. Keycloak or Azure AD)

#. Ensure that the ID Token provides role/group information
#. Authorize your Geonetwork URLs for redirects (i.e. `http://localhost:8080/geonetwork/login/oauth2/code/geonetwork-oicd`)
#. Record the Client ID
#. Record the Client Secret
#. Get the Server's JSON metadata document

#. Configure Geonetwork via environment variables

#. `GEONETWORK_SECURITY_TYPE=openidconnect`
#. `OPENIDCONNECT_CLIENTSECRET=...` (from your IDP server)
#. `OPENIDCONNECT_CLIENTID=...` (from your IDP server)
#. `OPENIDCONNECT_SERVERMETADATA_JSON_TEXT='...'` (the text of your Server's JSON metadata document)
#. `OPENIDCONNECT_IDTOKENROLELOCATION=...` (location of the user's roles in the ID Token)



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.


Environment Variable and Meaning
================================

**GEONETWORK_SECURITY_TYPE**

Should be `openidconnect`.

**OPENIDCONNECT_CLIENTID**

The name of the client/application you configured on your OpenID server.

**OPENIDCONNECT_CLIENTSECRET**

The `client secret` you configured on your OpenID server.

**OPENIDCONNECT_SERVERMETADATA_CONFIG_URL**

URL to the external OIDC server's JSON metadata document. This is typically at `/.well-known/openid-configuration` on the IDP server.

.. note:: This will download the server's configuration everytime GeoNetwork starts up, which could be a security concern. For security, use a `https` URL.

**OPENIDCONNECT_SERVERMETADATA_JSON_TEXT**

Should be the text of your OpenID server's metadata configuration (JSON).

**OPENIDCONNECT_SERVERMETADATA_FNAME**

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``)

**OPENIDCONNECT_IDTOKENROLELOCATION**

Where, in the ID Token, are the users roles/groups stored (i.e. "groups", "roles", or "resource_access.gn-key.roles")

**OPENIDCONNECT_ROLECONVERTER**

This provides simple role conversion from the OpenID server to Geonetwork roles.

ie. `"GeonetworkAdmin=Administrator,GeonetworkEditor=Editor"`

This will convert "GeonetworkAdmin" (from the OpenID Server) to the Geonetwork "Administrator" role.

.. 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.

**OPENIDCONNECT_MINIMUMPROFILE**

Every user who authenticates against the OpenID server will be given this role.

Default is `"RegisteredUser"`.

**OPENIDCONNECT_USERPROFILEUPDATEENABLED**

When a user logs on, update their Geotwork profile from the OpenID server's ID Token.

Default is `"true"`.

**OPENIDCONNECT_USERGROUPUPDATEENABLED**

When a user logs on, update their Geotwork group/role permissions.

Default is `"true"`.

**OPENIDCONNECT_SCOPES**

Limit the requested scope access to the OpenID server.

Default "openid email profile", and "openid email profile offline_access" (for bearer tokens).

**OPENIDCONNECT_LOGINTYPE**

How Geonetwork deals with users who are not logged on.

Default is "LINK" - users can click on the "login" link on the main page.

"AUTOLOGIN" - No login form provided which will automatically login the user when possible.

**OPENIDCONNECT_LOGSENSITIVE_INFO**

"true" or "false" (default)

Logs: CODE, ACCESS TOKEN, ID TOKEN, userinfo endpoint result, and calculated GeoNetwork authorities.

LOGGING THIS INFORMATION IS PROBABLY A SECURITY AND PERSONAL INFORMATION RISK.
DO NOT TURN THIS ON IN A SYSTEM THAT IS ACTUALLY BEING USED.

We try not to log very sensitive information - we don't log the full access or id token (just the claims part).
We log the single-use CODE, but it should have already been deactivated by the server before we log it.

The access token, userinfo, and id token contain sensitive information (i.e. real names, email address, etc...)

Configuration for a Keycloak Server
===================================


It's outside the scope of this document to fully describe the steps to configure keycloak, but this should serve as a guide.

This will configure keycloak backed by **another OpenID IDP** (for example, by an Azure AD). In keycloak:

#. Create a realm (i.e. `myrealm`)
#. Create an openid client (i.e. `myclient`). This is your ClientID.

#. Root URL: `http://localhost:7777/geonetwork` (this is the GN root URL)
#. Valid Redirect URIs: `http://localhost:7777/geonetwork/*`
#. Access Type: Confidential
#. On the `Credentials` tab, get the secret (this is your Client Secret)
#. On the `Roles` tab, create some roles: Administrator, Editor, Reviewer, RegisteredGuest

#. Create your backing Identity Provider (i.e. to another OpenID server). Or you can configure users directly in keycloak.

#. At the bottom of the page, choose "import from URL" and import the backing server's configuration location.
#. Add the Client Secret (from the backing service)
#. Add the Client ID (from the backing service)
#. set "Client Authentication" to "Client secret sent as post"

#. Configure role translation

#. Edit the "Identity Provider" you just created, and go to the "Mappers" tab.
#. Press "Create" and and add a "Claim to Role".
#. Set Sync Mode Override to "Force"
#. Claim: `roles`
#. Claim Value: `name of the administrator role in the backing IDP`
#. Role: choose the "Administrator" role from the `myclient` client.
#. Repeat the above for Administrator, Editor, Reviewer, and RegisteredGuest

#. Configure details for your backing IDP

#. Edit the "Identity Provider" you just configured
#. On the Mappers tab, "Add Builtin" and tick "client roles (User Client Role)" then "Add selected"
#. Edit the "client roles" mapper and make sure "Add to ID token" and "Add to userinfo" are on



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```

Your environment variables will looks like this:

.. code-block:: properties
GEONETWORK_SECURITY_TYPE=openidconnect
OPENIDCONNECT_CLIENTSECRET='...'
OPENIDCONNECT_CLIENTID='...'
OPENIDCONNECT_SERVERMETADATA_JSON_TEXT='...big json text...'
OPENIDCONNECT_IDTOKENROLELOCATION='resource_access.{your client id}.roles'
Azure AD Configuration
======================

There are two ways to setup Azure AD. The first is with user and groups (a more traditional LDAP method) or with Application Roles.

With Users and Groups
``````````````````````

Setup the Azure Application:

#. Create a new `App Registration`
#. use "http://localhost:8080/geonetwork/login/oauth2/code/geonetwork-oicd" as a redirect URIs
#. On the "Certificates & Secrets" add a new secret and record it (make sure you get the secret value and NOT the object id)
#. Make sure the groups are in the ID token - on the "Manifest" tab, edit the JSON so that "groupMembershipClaims": "SecurityGroup" is set
#. On the summary page, get the Application (client) ID
#. On the summary page, choose "Endpoints" (at the top) and get the JSON text from the "OpenID Connect metadata document" Endpoints

Setup users and groups:

#. In Azure AD, go to groups
#. Add new Groups - "geonetworkAdmin", "geonetworkReviewer", etc... Record the name and the group's **Object ID**
#. Edit a User, and choose Groups, and add them to appropriate group.


Your environment variables will looks like this:

.. code-block:: properties
GEONETWORK_SECURITY_TYPE=openidconnect
OPENIDCONNECT_CLIENTSECRET='...'
OPENIDCONNECT_CLIENTID='...'
OPENIDCONNECT_SERVERMETADATA_JSON_TEXT='...big json text...'
OPENIDCONNECT_IDTOKENROLELOCATION='groups'
OPENIDCONNECT_ROLECONVERTER='3a94275f-7d53-4205-8d78-11f39e9ffa5a=Administrator,d93c6444-feee-4b67-8c0f-15d6796370cb=Reviewer'
.. note:: The roles are in the "roles" part of the ID Token.


.. note:: The OPENIDCONNECT_ROLECONVERTER converts the Azure AD Group's Object ID to a Geonetwork Role.


With Application Roles
``````````````````````

Setup the Azure Application:

#. Create a new Enterprise application
#. use "http://localhost:8080/geonetwork/login/oauth2/code/geonetwork-oicd" as a redirect URIs
#. On the "Certificates & Secrets" add a new secret and record it (make sure you get the secret value and NOT the object id)
#. Make sure the groups are in the ID token - on the "Manifest" tab, edit the JSON so that "groupMembershipClaims": "ApplicationGroup" is set
#. On the summary page, get the Application (client) ID
#. On the summary page, choose "Endpoints" (at the top) and get the JSON text from the "OpenID Connect metadata document" Endpoints

Setup Application Roles:

#. In Application you created, go to "App Roles".
#. Add new Groups - "Editor", "Reviewer", etc...

Assign Users:

#. Go to Azure AD, Enterprise Application, then the application you created
#. Choose "Assign users and groups"
#. Press the "Add user/group" (top)
#. Press "None Selected" (under Users) and choose some users
#. Press "None Selected" (Under Select a Role) and choose some roles
#. Configure all your users with roles


Your environment variables will looks like this:

.. code-block:: properties
GEONETWORK_SECURITY_TYPE=openidconnect
OPENIDCONNECT_CLIENTSECRET='...'
OPENIDCONNECT_CLIENTID='...'
OPENIDCONNECT_SERVERMETADATA_JSON_TEXT='...big json text...'
OPENIDCONNECT_IDTOKENROLELOCATION='roles'
.. note:: The roles are in the "roles" part of the ID Token.


.. note:: You don't typically have to do any role conversion since the role name will be used in the ID Token.

.. _OIDC Bearer Tokens:

OIDC Bearer Tokens
==================

Bearer Tokens are also supported - you can attach the JWT Bearer token to any request by setting the HTTP header like this:

.. code-block:: properties
Authorization: Bearer: <JWT token>
Bearer Tokens are mostly used for automated (desktop or application) API calls - real users should just login normally using OIDC.

#. Setup your OIDC configuration (see :ref:`authentication-openid`)
#. Setup the OIDC Bearer token configuration (see :ref:`Bearer Token Configuration`)
#. 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.
#. Attach it to your request headers (see :ref:`OIDC Bearer Tokens`)
#. Make protected requests to the Geonetwork API

This has been tested with Keycloak and with Azure AD. It should work with other JWT-based OIDC services.

Validation
``````````

The token is validated in three major ways:

#. 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).
#. 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`
#. 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`

.. _Bearer Token Configuration:

Configuration
`````````````

Configure OIDC as above - ensure this is working.

Instead of using ``GEONETWORK_SECURITY_TYPE=openidconnect``, use ``GEONETWORK_SECURITY_TYPE=openidconnectbearer``.

Inside ``WEB-INF/config-security/config-security-openidconnectbearer.xml``:

#. If you are using keycloak (configured with Groups in the `userinfo` response), then uncomment the `UserInfoAccessTokenRolesResolver` bean and comment out the `MSGraphUserRolesResolver` bean.
#. 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.

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.

Other Providers
```````````````

This has been tested with Azure AD (groups in the MS Graph API) and KeyCloak (groups in the `userinfo`).

For other IDP, you might have to make some modifications.

#. Make sure the `AudienceAccessTokenValidator` and `SubjectAccessTokenValidator` work correctly for your JWT bearer tokens.
#. Make sure that the user's groups are available - see the `UserRolesResolver` interface and its two implementations - `UserInfoAccessTokenRolesResolver` and `MSGraphUserRolesResolver`.


.. _authentication-keycloak:

Configuring Keycloak
Expand Down

0 comments on commit 308bd3f

Please sign in to comment.