Skip to main content

OpenID Connect (server side)

Oneki.js supports the Open ID Connect (OIDC) authorization code flow where the authorization code is exchanged for an access token via a server. This is the most common and secure way to retrieve an access token

In settings.ts, when the "idp type" is "oidc_server", Oneki.js implements the following scenario:

To authenticate against an OpenID Connect Identity Provider (OIDC IDP), you have to create four pages/routes:

  • login: this page is displayed following a click on a link or a redirect following a 401 HTTP Error
  • login callback: this route is called by the OIDC IDP (e.g: Google) after a successfull authentication
  • logout: this page is displayed following a click on a logout link or if there is no activity for x minutes (configurable via settings)
  • logout callback: this route is called by the OIDC IDP after a successfull logout

The code is the same for a NextJS App or a Create React App

Examples

Login with Google
This example describes how to redirect the user to Google so he can enter his username and password. This step is performed by GoogleLoginPage.tsx (/auth/login/google)
Redirects to: https://accounts.google.com/o/oauth2/v2/auth?scope=openid%20email%20profile
&client_id=519201240542-gk79ts8svme25ve4sfuoksjvdupv7fhe.apps.googleusercontent.com&response_type=code
&redirect_uri=https://examples.oneki.net/auth/login/google/callback
&state=b3f4f525792470ca73732b4f4681809ed769e3429d782298037c63dfec92cfda
&code_challenge=mt2n-8AucWai57be_wj6L0iScRrZoXO3t9EevEYLvw0
&code_challenge_method=S256

Once the user is authenticated, Google redirects the user to the page handled by LoginCallbackPage.tsx (/auth/login/google/callback) and provides an authorization code as a query parameter.

Redirects to: https://examples.oneki.net/auth/login/google/callback?authuser=0
&state=363be2fcb87af1f01cc45d6d7df0e73f0986b1ef3c4d77e5e635e2d452301957
&code=4%2F0Adeu5BUgbCt1aswdkBfCC0WxoKk8Fj8TaJwPdD5DAwHOcuxAfTwPY_kimKgBTgwL0yRldA
&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile
&prompt=none
LoginCallbackPage.tsx exchanges the authorization code to an JWT access token by calling a backend API
POST /api/oauth2/google/token
Host: https://examples.oneki.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 451

grant_type=authorization_code&
client_id=519201240542-gk79ts8svme25ve4sfuoksjvdupv7fhe.apps.googleusercontent.com&
redirect_uri=https%3A%2F%2Fexamples.oneki.net%2Fauth%2Flogin%2Fgoogle%2Fcallback&
code=4%2F0Adeu5BUgbCt1aswdkBfCC0WxoKk8Fj8TaJwPdD5DAwHOcuxAfTwPY_kimKgBTgwL0yRldA&
scope=openid%20email%20profile&code_verifier=vfPr9~ZNJ1msSAaMdC-xvymeXoAYJ.6QWRTw~.0-79UXRE11kOqfcegLLXzmpJ6-GO1RtVCD91_GdyvGgmiSWw9LnhX7__PtjHfwE2Kjasit0se_~h0Om-hpiwzgoL

The response contains the access and id tokens

{
"access_token": "ya29.a0AfB_byA6ryWtal5OpY....mDLi_QZeBBQ8-anlgA0165",
"expires_in": 3597,
"scope": "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid",
"token_type": "Bearer",
"id_token": "eyJhbGciOiJSUzI1NiIsImt....wlZltc2dpTuSMvnvFgGURbgUTWg"
}

The JWT token is stored in the local storage because settings.ts contains the following configuration: idp.google.persist: 'localStorage' (Defaults to: stored only in the global state)

examples/cra-examples/src/auth/login/google/IndexPage.tsx
loading...
Logout (external logout with callback)
examples/cra-examples/src/auth/logout/IndexPage.tsx
loading...
import React from "react";
import { useLoginService } from "onekijs";

export default React.memo(() => {
const idpName = 'google';
const options = {};
const [error] = useLoginService(idpName, options);
if (error) {
return <div>{error.payload.message} <span onClick={() => error.remove()}>X</span></div>
}
return null;
}


Parameters

Inputs

// [Optional] the name of the IDP used for the login -- defaults to "default"
idpName: string

// [Optional] options object -- defaults to {}
options: {

// a callback function triggered when an error is thrown -- defaults to send error on topic "login-error"
onError: func
}

Outputs

error: {
payload: {
// description of the error
message: string,

// code of the error
code: string,
}

// remove the error
remove: func
}

Configuration

useLoginService, useLoginCallbackService, useLogoutService, useLogoutCallbackService are fully configured in settings.js
The configuration must be defined under the key "idp/:idpName". For example, if idpName=google, the config must look like this:

const settings = {
idp: {
google: {
type: "oidc_server",
...
}
}
}


Mandatory attributes

KeyTypeDescription
authorizeEndpointstring |
function(context)
Can be
  • a string (relative or absolute URL)
  • or a function returning the URL
if it's a relative URL, it's prefixed by the server.baseUrl from settings.js
clientIdstringthe client_id created on the IDP (identity provider)
logoutEndpointstring |
function(context)
Can be
  • A relative or absolute URL
  • A function returning the URL
if it's a relative URL, it's prefixed by the server.baseUrl from settings.js
tokenEndpointstring |
function(grant_type, context)
Can be
  • a relative or absolute URL
  • A function that does an AJAX POST request to the token endpoint and returns a object of type "Token"
if it's a relative URL, it's prefixed by the server.baseUrl from settings.js
typestringmust be "oidc_server"
userinfoEndpointstring |
function (context)
Can be:
  • A relative or absolute URL
  • A function that returns an object that represents the userInfo. For example a object like this: {email: 'foo@example.com', roles: ['ADMIN']}}
if it's a relative URL, it's prefixed by the server.baseUrl from settings.js


Optional attributes

KeyTypeDescriptionDefault
callbackfunction(response, context): [token,userInfo]Callback called at the end of the authentication for extracting the token and the userInfo from the response.

Inputs
  • response: the response from the authentication server
  • context: an object containing the configuration of the IDP used, the redux store, the router, the settings and i18n infos
Outputs
  • token: the oauth2 token
  • userInfo: the securityContext of the user
null
codeChallengeMethodstringMethod that was used to derive an authorization code challengeS256
jwksEndpointstring |
function(token, context)
jwksEndpoint is mandatory if validate = true.

Can be
  • A relative or absolute URL
  • A function that returns a public key
if it's a relative URL, it's prefixed by the server.baseUrl from settings.js
null
loginCallbackRoutestringa relative or absolute URL called by the OIDC server after a successfull login.[loginRoute]/callback
logoutCallbackRoutestringa relative or absolute URL called by the OIDC server after a successfull logout. Should be used to remove the cookie on the server side[logoutRoute]/callback
pkcebooleanflag to indicate if the PKCE extension is applied. Recommendedtrue
noncebooleanflag to indicate if the nonce in the id_token is validated on the client side. Should be done on the server sidefalse
postLoginRedirectKeystringWhen calling the authorize endpoint, postLoginRedirectKey represents the name of the parameter to indicate the redirect URIredirect_uri
postLogoutRedirectKeystringWhen calling the logout endpoint, postLoginRedirectKey represents the name of the parameter to indicate the redirect URIpost_logout_redirect_uri
responseTypestringonly code is supported right nowcode
scopestringthe value of the parameter "scope" sent to the authorize endpoint. Should generally be redefinedopenid
statebooleanflag to indicate if the javascript client send a state to the IDP. Recommended for mitigating attackstrue
validatebooleanflag to indicate if the id_token and the access_token are validated. Should generally be done on the server sidefalse


Configuration example

const settings = {
idp: {
google: {
type: 'oidc_server',
clientId: '1eb5cq6p7d8dm8g4q9jk6qdve5', // id given by Google
authorizeEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth', // URL given by Google. Will be called by the client
tokenEndpoint: '/api/oauth2/token', // URL of a service exposed by your server that exchanges the authorization code for an access token by calling the Google /token endpoint
userinfoEndpoint: '/api/oauth2/userinfo', // URL of a service exposed by your server that returns the details about the logged-in user
logoutEndpoint: '/api/oauth2/logout', // URL exposed by your server which call the IDP logout URL and then removes the cookie
scope: 'openid email profile', // ask to Google the profile and the email of the user
}
}
}