Login

DraftAccessible

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

Introduction

HDS Login components include React context, components and hooks for handling user authorisation, API tokens, session polling and graphQL queries. 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 Helsinki Profile, 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.

For Login UI components see Header.Login on Header component page. For more information on how HDS Login and Header.Login components are meant to work together see Login pattern page.

Requirements

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

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.

Consents for storing data

The data of the authenticated user is stored in the session storage. Users must give consent to storing data in the session storage, just like cookie consents. You can use the ready-made consents in the common Helsinki cookies.

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 four modules to handle the user's needs:

  • Oidc client for user data.
  • Api tokens client for acquiring backend tokens.
  • Session poller for checking if the user's session is still valid at the Oidc provider.
  • GraphQL module for fetching data from a graphQL server. Fetching can be automatically linked to the Api Tokens client.

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.

GraphQL module

This module was added to make it easier to use the login system with authenticated graphQL queries. The GraphQL module waits for api tokens and automatically picks a token and uses it in queries.

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.

GraphQL module is not automatically added, but it's setup is simple.

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 Helsinki Profile, 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 },
};