Skip to main content

OAuth2 & OpenID Connect

TL;DR

If you would like to skip the theory and dive right into configuration - scroll to the end of this article, there is a step-by-step list along with links to useful ressources.

OpenID Connect (OIDC) is the latest evolution of the widely adopted Internet Standard for identity management that enables developers to focus on building their application instead of re-inventing the wheel once more.

So this standard perfectly matches Hanko Identity's mission to provide simply the best and most secure authentication user experience currently available. Hanko Identity is fully OpenID Connect compliant, built only on certified libraries.

This document will introduce you to the general concepts of OpenID Connect with Hanko Identity. It will provide you with the vocabulary needed to understand the general scheme and what you need to implement if you are new to the show.

There are so many good articles out there which explain OpenID Connect in general, we will not go into every detail. If you would like to dig deep into the standard, we suggest you take the time and start with the primary source and base layer RFC 6749 "The OAuth 2.0 Authorization Framework" and move on to the official OpenID Connect specs afterwards. While not very appealing to the eye, the RFC and specs explain every detail quite extensively.

OpenID Connect: The Internet Identity Layer

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

https://openid.net/connect/

The standard defines several processes and protocols and it is maintained by the OpenID Foundation, a well known and respected non-profit organization.

Our scenario: user authentication and identification

To understand the principles a bit better and for the sake of simplicity we assume a focused scenario for a start: we have one classic webapp with the user base located in Hanko Identity and we would like to achieve a user login.

Later we can expand this scenario with multiple apps and the same user base - this is called Single Sign-On (SSO).

OAuth 2.0 deals with a lot more scenarios which quickly become misleading and irritating if all you would like to achieve is a secure and comfortable login. Of course Hanko Identity supports all current OAuth 2.0 and OpenID Connect standard use cases (except for the deprecated and/or insecure ones, but that is a different story).

Entities: Apps, Users and Hanko Identity

Based on the mature OAuth 2.0 standard, OpenID Connect evolves around three main entities:

  • the End-User (aka Resource Owner or Identity)
  • the Client (aka your app or "Relying Party" RP)
  • the Authorization Server (→ Hanko Identity)

These entities are involved to allow access to Protected Resources belonging to the Resource Owner - in our case the End-User. These protected resources live on a Resource Server.

In our scenario we want to authenticate and identify the person accessing our very own webapp (the End-User). Hanko Identity contains the user data and thus is the resource server, containing the protected resources "user data". Your app trusts Hanko Identity to properly authenticate and identify users. Access to an identities resources within your app is a different story and not scope of OpenID Connect.

Establishing Trust

As the authentication and identification in our scenario is delegated from the app to Hanko Identity, our webapp first needs to establish trust with the Authorization Server. This trusted relationship is established by a) configuring the app as a Client in Hanko Identity and b) using these credentials in your app.

In Hanko Identity you do this by creating a project. During configuration you receive a client_id and - if applicable - the client_secret. Your app will use these credentials to identify itself at your instance of Hanko Identity.

Additionally, in the project configuration all relevant URLs of your app are being pinned, especially the allowed URLs where to redirect after login and logout. This way we make sure that only trusted endpoints will receive any information from us and the end-user is redirected only to these trusted locations.

Automatic configuration: OpenID Provider Metadata

Next, your app needs to know how and where to access Hanko Identity. As the configuration of the authorization server on the client side can quickly become complex, the OIDC standard defines a way to discover the configuration (aka "OpenID Provider Metadata") automatically on the client side.

Hanko Identity of course supports this part of the standard to reduce the integration-effort as much as possible. Basically the client needs to call a standardized and predefined URL and process the result:

https://${YOUR_HANKO_IDENTITY_HOSTNAME}/.well-known/openid-configuration

In particular two endpoints need to be obtained here:

  • the authorization endpoint: this is where the end-user authentication takes place
  • the token endpoint: here your app can obtain and exchange tokens
Use a standard OIDC library!

Quite a few of the common and openly available software libraries for clients support this auto-configuration right out of the box. Please do yourself a favour and use one of those libs. We provide a curated list of libraries here. When you are using such a library, most of the time you just need to provide the base URL, client_id and client_secret to the lib and be done with it.

Application types and authentication flows

Today there are different application types commonly seen on the Internet. Related to these application types are specific processes, reflected as flows in the OpenID Connect Standard. These flows are based on OAuth 2.0 grant types.

To make this configuration as easy as possible we provide sensible defaults for the different application types.

Your OIDC client library in turn needs to know which settings to use. After you have selected your App type in the Console, the neccessary settings are being displayed.

We distinguish between the following application types for now:

App type
Classic webapp
Provides a backend to store secrets, typically written in PHP, Python, Node.js, Java, you name it
Native mobile app
iOS and Android that is; again, no secure storage is available

Although OAuth 2.0. and OpenID Connect describe various possible "grants" and "flows", there is only one flow that should really be used: Authorization Code, preferably with PKCE. If we are dealing with a mobile app, PKCE is mandatory for security reasons. All other flows and grant types are either legacy, discouraged or provide no advantage compared with the Authorization Code flow.

The basic process of the Authorization Code flow is simple: the end-user securely authenticates at Hanko Identity and comes back to your app with a code. Your app exchanges this code for tokens at Hanko Identity. These tokens contain the user's identity.

Server to server communication: Client credentials flow

Although our focus is on end-user authentication, you still can use Hanko Identity for machine-to-machine authentication. We do speak OAuth 2.0 after all.

Example: If machine A needs authenticated access to machine B via Rest API for example, machine A obtains an access token at Hanko Identity using the client_id and client_secret and presents the token to machine B. Machine B in turn validates the token with Hanko Identity and acts upon the result (e.g. process the request or deny access).

Managing identities through the Identity Admin API is an example of this client credentials flow. See here for more information.

DO NOT use the Implicit grant / flow

In the OpenID Connect standard there is a flow based on the OAuth "Implicit grant". This flow catered to the old times when Javascript could not access domains other than its origin. Subsequently, the access token was handed directly to the SPA as a part of the redirect URL. With today's technical reality there is no need for the Implicit flow anymore. Do not use it.

For reference: https://oauth.net/2/grant-types/implicit/

DO NOT use the resource owner password credentials grant type

In OAuth 2.0 there is a grant called "resource owner password credentials" where the app itself provides the login-form, receives username and password from the user and forwards it to the authentication server.

Although this case is still described in the standard for legacy (and political) reasons, its use is strongly discouraged, and we do not support it.

Token

During authorization with OpenID Connect, three so called tokens are passed around:

  • identity token
  • access token
  • refresh token

Identity token

Think of this one like a passport for the end-user. It contains various information about the user and the authentication that took place. This information is represented in the form of Claims.

The actual content is determined by a) the "scope" configuration of your App in Hanko Identity and b) the scope actually requested during authentication. The OpenID Connect standard defines a list of claims that are technically required. These claims can be extended with custom claims.

For example in Hanko Identity the identity token can contain the following claims:

ClaimScopeDescriptionExample data
emailemailE-Mail of the userjohn.doe@hanko.io
verifiedemailIs the e-mail verified?1
user_idprofileUser ID5eec7c62-7f08-449b-9bef-9872d988c802
first_nameprofileFirst name of the userJohn
last_nameprofileLast name of the userDoe
subopenidSubject Identifier = user id5eec7c62-7f08-449b-9bef-9872d988c802
ratopenidTime when the End-User authentication has been requested.1638354782
issopenidIssuer Identifierhttps://your-hanko-identity.hanko.io/
expopenidExpiration time on or after which the ID Token MUST NOT be accepted for processing.1638358412
iatopenidTime at which the JWT was issued.1638354812
auth_timeopenidTime when the End-User authentication occurred.1638354812
audopenidAudience(s) that this ID Token is intended for.List of audiences

You will receive this token through the library you use. The claims can be the base for your user session.

The identity token is represented as a signed JSON Web Token (JWT). It is the job of your OpenID Connect library to validate the contents according to the specs.

Access token

The access token basically is a string which represents the authorization of the end-user to obtain information and execute operations on her behalf.

Security warning!

As this token represents access privileges it is good practice to keep it securely stored in the backend at all times.

You need to provide this token to any service where you would like to act in the name of the user.

Obtaining related user information

The token can be used to obtain user information from Hanko Identity's /userinfo endpoint. This way you have always access to up-to-date user information, e.g. for display purposes. The /userinfo endpoint also validates the provided token and rejects the request if it is invalid or expired

Default TTL of access tokens

The default TTL of an access token is 1 hour at Hanko Identity.

Single app vs. access token

While the access token concept is only of limited use when you are dealing with a single application only, as soon as you have a distributed system consisting of multiple services or interacting with services outside your application this token makes much more sense.

If you are interested in the details and technical content of an access token you can find the related spec at https://datatracker.ietf.org/doc/html/rfc6750.

Refresh token

To get the concept of refresh tokens we first need to talk about access tokens a bit more: As an access token represents privileges, is transmitted over the internet multiple times and potentially stored in several locations, it needs to expire at some point to mitigate potential damage of token loss for example.

After an access token has expired it cannot be used for authenticated calls anymore. Token introspection will fail and you also cannot request information at the /userinfo endpoint. To receive a new access token there are two ways:

  • re-authenticate the user
  • use a refresh token

Re-authentication is always possible if a user is actively accessing your services - just redirect the end-user to the authentication endpoint once again and she will return with a fresh set of tokens. If the session at Hanko Identity is still valid, she does not even need to actively do anything, it's just a fully automated chain of redirects that take only milliseconds in total.

The refresh token can be obtained along with the access token after authentication. It represents the authorization to obtain new access tokens. Good only for a one-time-use, they are used by a Client (e.g. your app) to obtain a new access token once the old one has expired. This way you can have short-lived access tokens for security reasons without sacrificing user experience.

Again, in our "user authentication and identification" scenario there is no immediate need for the use of refresh tokens.

Putting it all together

How to authenticate a user

To authenticate a user with Hanko Identity, using the OpenID Connect protocol and following the Authorization Code (with PKCE) flow, these steps are neccessary:

  1. Your app sends an authentication request to Hanko Identity, receiving an URL where the end-user needs to authenticate
  2. Your app redirects the end-user to the returned URL, Hanko Identity handles authentication of the end-user
  3. Hanko Identity redirects the end-user back to your app with an authorization code
  4. Your app requests the access and identity token using the authorization code at Hanko Identity's token endpoint
  5. Your app receives the identity token and access token in the response body
  6. Your app validates the identity token and retrieves the end-user's subject identifier (sub) and any other fields needed for further processing
note

Once more we would like to point out: use a ready-made, battle-proven library to handle this process.

What you need to do

Library, SDK or plugin?

  • If you are developing an application, you need to chose a suitable OpenID Connect client library for your programming language of choice.
  • If you are using a CMS, an e-commerce system or some other software where standard plugins/extensions exist or you cannot implement functionality yourselves, you need to lookout for an OpenID Connect Plugin. Choose a certified one if possible.

We provide a curated list of libraries and plugins in this documentation. Please feel free to contact us if you need support with this.

Then you need to provide (or locate) the authentication endpoint in your app to handle the process. If you are using a plugin or extension, that endpoint should be mentioned in the documentation. This endpoint should be a dedicated route (like http://www.example.com/login) that also needs to be configured in the Hanko Console as a redirect_url.

note

For security reasons Hanko Identity will redirect your users only to the endpoint specified here.

Configuration

Wether you are implementing a library yourselves or setting up a ready-made plugin, you need to configure some settings. This includes:

  • IDP URL - Hanko Identity tenant's URL
  • Credentials (client_id and client_secret)
  • OpenID Connect scope (see above, must contain at least openid)
  • Response type (defaults to code)
  • Token endpoint authentication method (defaults to client_secret_basic)
note

You can get a comprehensive list of all parameters tailored to your client in the Hanko Console!

Implementation

You can find implementation code samples in the "Guides" section of this documentation. Even if your specific language is not available, you can still read up the steps to take and adopt them. If you are stuck - let us know and we help you out!