Login

DraftAccessible

Login components include React components, context and hooks for handling user authorisation, api tokens and session polling.

A work in progress!
The HDS Login system is a set of components the HDS team is currently making. This means that this component is subject to change, and we don't recommend using it in production.

Introduction

HDS Login components include React context, components and hooks for handling user authorisation, API tokens and session polling. React is not a requirement, but currently, no plain JavaScript UI components exist.

Implementation requires an OIDC provider, which is a server for user authorization. The City of Helsinki uses Tunnistamo, but HDS login components can be used with any compatible OIDC provider. Read more about OpenID Connect (OIDC).

In the OIDC login process, the browser window is redirected to the OIDC provider. Authentication is fully handled by the server. That is why HDS does not provide login or registration forms.

When the user has been authenticated, the OIDC server redirects back to the service. HDS provides components to handle the authentication process initiation and responses.

Requirements

Your service must be registered with an OIDC provider, like Tunnistamo.

To use the OIDC provider with login components, you need

  • Client id.
  • Authority.
  • URL of the OIDC provider.

Important

The HDS Oidc client stores data in session storage for security reasons. Session storage is not shared across browser windows or tabs, so the user must log in separately for each window.

HDS Login components cannot support SSR at the moment because of the session storage requirement.

Silent session renewal requires a dedicated HTML file that redirects to the OIDC provider "silently" in an iframe.

Example Usage

// Actual properties are omitted from this example to keep it simple
const providerProperties = {...}
const SayHelloIfUserExists = () => {
const user = useAuthenticatedUser();
if ( user ) {
return <p>Hello, { user.name }!</p>
} else {
return (
<>
<p>You are not logged in.</p>
<LoginButton errorText="Login failed. Try again!">Log in</LoginButton>
</>
)
}
}
<LoginProvider {...providerProperties}>
<SayHelloIfUserExists />
</LoginProvider>

Components

HDS Login components include

  • A React context that exposes user data and other modules to React hooks and components.
  • Login buttons with error handling.
  • A callback handler for parsing the authentication response.
  • Wrappers that conditionally render their children depending on authentication status.

There is no component for logout. It is just a redirection link and any button can be used for it. No error handling is required.

Detailed documentation can be found in the components section of the Usage page.

Hooks

HDS Login hooks enable to

  • Check login status.
  • Get user data.
  • Add listeners.
  • Login and logout.
  • Get API tokens.
  • Get modules.

Detailed documentation is in the hooks section of the Usage page.

Modules

There are three modules to handle the user's needs:

If a module is not needed, it can be dropped with settings. Custom modules can also be added. All modules can be used without React and without each other. But a valid user object is required to get API tokens and poll the session.

Modules emit signals to communicate with other modules. For example, the Api tokens client module refreshes its tokens when user tokens in the Oidc client module have been refreshed.

Detailed information is in the modules section of the Usage page.

Oidc client module

This module handles the login process and parses tokens from the login response. It also renews tokens and handles token storage and removal. Logout is also handled by this module.

Api tokens client module

This module exchanges the user's tokens for API tokens. API tokens are used for querying data from backend servers. The module renews the tokens if the user's tokens change.

Session poller module

This module polls the user's session from the Oidc provider and signals an error if polling returns an unauthorized response. If you have logged in with the same user in multiple browser windows, this module detects when the user is logged out in any browser window.

Custom modules

Other modules can be added. Detailed information is in the custom modules section.

Signals

Modules communicate with signals. A module emits signals and listener functions are triggered by them. Listeners can be added by modules, components or plain Javascript. Components can listen to signals with hooks.

The signal emitter is called a Beacon. Usually, only error signals should be monitored. Data updates are handled automatically.

Detailed information is in the signals section of the Usage page.

Common settings for localhost

Every service must have its own client_id and scope, but these settings can be used for testing. They only work in http://localhost:3000. Make sure you have redirect_uri, silent_redirect_uri and post_logout_redirect_uri registered at the OIDC server.

const loginProviderProps: LoginProviderProps = {
userManagerSettings: {
authority: 'https://tunnistamo.dev.hel.ninja/',
client_id: 'exampleapp-ui-dev',
scope: 'openid profile email https://api.hel.fi/auth/helsinkiprofiledev https://api.hel.fi/auth/exampleappdev',
redirect_uri: `YOUR_REGISTERED_REDIRECT_URL`,
silent_redirect_uri: `URL_TO_YOUR_REGISTERED_LOCAL_SILENT_RENEW.HTML`,
post_logout_redirect_uri: `YOUR_REGISTERED_LOGOUT_URL`,
},
apiTokensClientSettings: { url: 'https://tunnistamo.dev.hel.ninja/api-tokens/' },
sessionPollerSettings: { pollIntervalInMs: 10000 },
};

If you are using Keycloak, then use these settings:

const loginProviderProps: LoginProviderProps = {
userManagerSettings: {
authority: 'https://tunnistus.dev.hel.ninja/auth/realms/helsinki-tunnistus',
client_id: 'exampleapp-ui-dev',
scope: 'openid profile',
redirect_uri: `YOUR_REGISTERED_REDIRECT_URL`,
silent_redirect_uri: `URL_TO_YOUR_REGISTERED_LOCAL_SILENT_RENEW.HTML`,
post_logout_redirect_uri: `YOUR_REGISTERED_LOGOUT_URL`,
},
apiTokensClientSettings: {
url: 'https://tunnistus.dev.hel.ninja/auth/realms/helsinki-tunnistus/protocol/openid-connect/token',
queryProps: {
grantType: 'urn:ietf:params:oauth:grant-type:uma-ticket',
permission: '#access',
},
audiences: ['exampleapp-api-dev', 'profile-api-dev'],
},
sessionPollerSettings: { pollIntervalInMs: 10000 },
};