Skip to content

Add support for token validation using JWKS

Kristian Harju requested to merge 2-implement-support-for-jwks-based-auth into main

Implemented MVP version of the JSON Web Key set (JWKS) based authentication and authorization to support Azure (Microsoft Entra ID) custom API token and groups/roles based permissions with Cognito and Keycloak.

  • Added JWKS based auth support
  • Userinfo endpoint based auth is still supported and works as before
  • Added Entra ID (Azure) Docker Compose configuration for testing (some env variables must be provided)
  • Added cache config to default nginx.conf file for external request going to userinfo or JWKS endpoints
  • Added simplified handling of roles based on claim values

Test authentication with one or more of the identity providers below

Note that you can also change the environment variables used in Docker compose files and use your own identity provider settings.

GitLab and userinfo endpoint based auth:

  • Starting up with GitLab auth docker compose --file=docker-compose-gitlab.yml up --build
  • Open the GeoWeb frontend at http://localhost:5400/ and try to login (should succeed)
  • To stop the containers and cleanup everything run docker compose --file=docker-compose-gitlab.yml down --volumes

Local Keycloak server running in Docker and JWKS based auth:

  • Starting up with Keycloak auth docker compose --file=docker-compose-keycloak.yml up --build
  • Open the GeoWeb frontend at http://localhost:5400/ and try to login
  • Try to create a new user (select "Register") and login with the created account (should succeed)
  • To stop the containers and cleanup everything including the created user run docker compose --file=docker-compose-keycloak.yml down --volumes

Open Cognito and JWKS based auth:

  • Create a new Cognito test user in AWS console. Use your intlgeoweb account to login to AWS console.
  • Starting up with Cognito auth docker compose --file=docker-compose-cognito.yml up --build
  • Open the GeoWeb frontend at http://localhost:5400/ and try to login with your test user (should succeed)
  • To stop the containers and cleanup everything run docker compose --file=docker-compose-cognito.yml down --volumes

[FMI ONLY] Entra ID and userinfo endpoint based auth:

  • Create .env file and add all the required environment variables (replace <application_id> and <tenant_id>)
GW_AUTH_CLIENT_ID=<application_id>
GW_AUTH_LOGIN_URL="https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/authorize?client_id={client_id}&response_type=code&scope=email+openid+profile&redirect_uri={app_url}/code&state={state}&code_challenge={code_challenge}&code_challenge_method=S256"
GW_AUTH_LOGOUT_URL="https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/logout?post_logout_redirect_uri={app_url}"
GW_AUTH_TOKEN_URL="https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token"
OAUTH2_USERINFO="https://graph.microsoft.com/oidc/userinfo"
  • Starting up with Entra ID auth docker compose --file=docker-compose-entraid.yml up --build
  • Open the GeoWeb frontend at http://localhost:5400/ and try to login (should succeed)
  • To stop the containers and cleanup everything run docker compose --file=docker-compose-entraid.yml down --volumes

To test roles

See the section Using roles in the readme. You can test roles for example with Keycloak. Add for example "presets-admin" role in the admin UI http://localhost:8082/admin and assign the role to the user you have created.

  • Starting up with Keycloak docker compose --file=docker-compose-keycloak.yml up --build
  • Login to the Keycloak admin UI http://localhost:8082/admin
  • Select "geoweb" realm
  • Select "Realm roles" and create role called "presets-admin"
  • Select "Users" and user you have created
  • Select "Role mappings" and "Assign role" button, select "presets-admin" role and assign it to the user

JWT payload should now include:

... 
 {
   "realm_access": {
     "roles": [
       "offline_access",
       "default-roles-geoweb",
       "uma_authorization",
       "presets-admin"
     ]
   },
 }
...
  • You can decode your access token here https://jwt.io/
  • Set GEOWEB_ROLE_CLAIM variable value to GEOWEB_ROLE_CLAIM="realm_access.roles=presets-admin"
  • Stop/start or restart all containers docker compose --file=docker-compose-keycloak.yml restart
  • Open the GeoWeb frontend at http://localhost:5400/ and login
  • Nginx should pass the "Geoweb-Role" header to the presets-backend with the value "admin"
  • If the user has not the required role "presets-admin", Nginx should pass the "Geoweb-Role" header with the value "user"
  • Check the Nginx container logs docker logs --tail 1000 -f nginx-auth-backend to see the debug messages

To test permissions

See the section Configuration in the readme. You can use for example Open Cognito. Create couple of test users and some group. You can configure permissions using the environment variables GEOWEB_REQUIRE_READ_PERMISSION and GEOWEB_REQUIRE_WRITE_PERMISSION.

  • Login to AWS console. Use your intlgeoweb account.
  • Create a new user account geoweb and add it to a group called internal
  • Create a new user account external
  • Set ALLOW_ANONYMOUS_ACCESS="FALSE"
  • Set GEOWEB_REQUIRE_READ_PERMISSION="username=geoweb,external"
  • Set GEOWEB_REQUIRE_WRITE_PERMISSION="username=geoweb"
  • Starting up with Cognito auth docker compose --file=docker-compose-cognito.yml up --build
  • Guest user should not be able to list presets
  • User external should be able to list presets, but not to create new presets
  • User geoweb should be able to list presets and create presets

To test Nginx caching

  • Check nginx container cache paths to see cache files and timestamps
  • Run docker exec -it nginx-auth-backend ls -la /var/cache/nginx/userinfo or docker exec -it nginx-auth-backend ls -la /var/cache/nginx/jwks
  • To actually test the cache, the easiest way is to log in to the frontend, get access token from the browsers network tab, use the token to access the backend url (using for example curl or postman), close the internet connection and try again

Closes #2 (closed)

Edited by Kristian Harju

Merge request reports