Skip to content

Authentication and Authorization

Gene Panel Builder (GPB) uses TSD's OpenID Connect (OIDC) service to handle authentication (authn). OIDC is a layer on top of of OAuth2, which:

[E]nables Clients to verify the identity of the End-User based on the authentication performed by and Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

OIDC/OAuth 2.0 can handle more than just authn, for instance it can handle authorization (authz) based on user roles, or single signon.

In GPB, we only use a small subset of OIDC features, i.e. authentication, to know if users are who they claim to be. When a user has authenticated with OIDC provider, we create and manage a session with the user info from the provider and then persist the token to a key/value store. The keys on the session store are timestamp signed and used as session IDs, utilizing an encryption key and salt. The session id is set as a session cookie on the browser, with a time to live of 6 hours.

Implementation

Backend

The oauth part of the backend consists of:

  • FastAPI router instance providing endpoints for login, oauth callback, session verification, user info querying, and logout
  • Session kv-store built with sqlitedict python package

Front End

  • A session context exists on the frontend for determining whether a user is authenticated or not, as well as fetching user info upon authenticated.
  • Logging out makes a request to the backend to expire the session, effectively deleting the session key and value from the session store and the browser session cookie.

Login Flow

Every time a user visits the front end, and there is no gpbuilder session cookie present, or the session cookie has expired, the user is redirected to oauth login screen (TSD). After a user has authenticated with TSD, an authorization code is exchanged between the back end and OIDC service provider, resulting in an ID token and person info being handed back from TSD.

When the front end performs queries against the back end REST service, validity of user session if checked, and if invalid, session cookie is deleted and user redirected to the oauth login.

sequenceDiagram
    actor User

    participant fe as frontend
    participant be as backend
    participant oa as OIDC provider

    User->>fe: Open GPB
    fe->>be: GET /api/auth/verify

    alt is authenticated
        rect rgba(102, 208, 102, 0.25)
        be->>fe: 200
    end
    else is not authenticated
        rect rgba(208, 102, 102, 0.25)
        be->>fe: 401 Unauthorized
        end
        fe->>be: GET /api/auth/login
        be->>oa: Request login form
        oa->>User: Present login form
        User->>oa: Provide credentials
        oa->>be: Redirect to callback endpoint
        be->>oa: Exchange authentication code to get id token
        oa->>be: Return id token
        be->>be: Create session ID, and store id token
        be->>fe: Set gpb_session cookie value to session ID
        fe->>be: GET /api/auth/verify
        be->>fe: 200
        fe->>be: GET /api/auth/userinfo
        be->>fe: {user: "test", email: "test@example.com", name: "Test"}
    end

All REST endpoints pertaining to CRUD operations on genepanel data depend on a authenticated function, injected into FastAPI definitions, that checks the validity of the aforementioned session ID, such that if the ID is no longer valid, an HTTP exception is returned, together with a header to delete the session cookie from the browser, thereby forcing a redirection to the OIDC login form.

Note

When running GPB in development mode, authentication is bypassed.

Requirements

To run the oauth login flow, it is necessary to provide a configuration file secrets/oauth.prod.env:

SESSION_FILE =  <LOCATION_OF_SESSION_STORE_DB_FILE>
CALLBACK_ROUTE = <CALLBACK_ENDPOINT_REGISTERED_WITH_PROVIDER>
OIDC_CLIENT_ID = <OIDC_CLIENT_ID>
OIDC_CLIENT_SECRET = <OIDC_CLIENT_SECRET>
CONF_URL = <OIDC_WELL_KNOWN_CONFIGURATION_URL>
SCOPE = <SCOPES>
DEFAULT_SCOPE = <DEFAULT_SCOPES>
LOGIN_REDIRECT_URL = <URL_WHERE_USER_LOGS_IN>

Explanation of environment variables

  • SESSION_FILE: The file path to the session key value store file (sqlite). This will be mounted into the container, which makes it easy to debug locally if need be
  • CALLBACK_ROUTE: This is the callback endpoint registered with OAuth provider, e.g. /api/auth/callback
  • OIDC_CLIENT: The client id registered with the provider
  • OIDC_CLIENT_SECRET: The client secret registered with the provider
  • CONF_URL: The configuration URL of the provider, typically https://<domain>/.well-known
  • SCOPE: Used t: Default scopes
  • DEFAULT_SCOPE
  • LOGIN_REDIRECT_URL: URL to where the user agent logs in, e.g. https://<backend>/api/auth/login

Running in production

Authentication is enabled by default when running production build, but can be turned off by setting environvent variable USE_OAUTH to false when starting containers, e.g. USE_OAUTH=False docker compose -f docker-compose-prod.yml up -d