OpenID Connect (client 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 the access token
In settings.js, 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
- Login
- Login Callback
- Logout
- Logout Callback
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
}
import React from "react";
import { useLoginCallbackService } from "onekijs";
export default React.memo(() => {
const idpName = 'google';
const options = {};
const [error] = useLoginCallbackService(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 the login is successfull -- The default redirects the user from the calling page
onSuccess: func
// 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
}
import React from "react";
import { useLogoutService } from "onekijs";
export default React.memo(() => {
const options = {};
const [error] = useLogoutService(options);
if (error) {
return <div>{error.payload.message} <span onClick={() => error.remove()}>X</span></div>
}
return null;
}
Parameters
Inputs
// [Optional] options object -- defaults to {}
options: {
// a callback function triggered when an error is thrown -- defaults to send error on topic "logout-error"
onError: func
}
Outputs
error: {
payload: {
// description of the error
message: string,
// code of the error
code: string,
}
// remove the error
remove: func
}
import React from "react";
import { useLoginCallbackService } from "onekijs";
export default React.memo(() => {
const options = {};
const [error] = useLogoutCallbackService(options);
if (error) {
return <div>{error.payload.message} <span onClick={() => error.remove()}>X</span></div>
}
return null;
}
Parameters
Inputs
// [Optional] options object -- defaults to {}
options: {
// a callback function triggered when an the logout is successfull -- The default redirects the user to the home page
onSuccess: func
// a callback function triggered when an error is thrown -- defaults to send error on topic "logout-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
Key | Type | Description |
---|---|---|
authorizeEndpoint | string | function(context) | Can be
|
clientId | string | the client_id created on the IDP (identity provider) |
logoutEndpoint | string | function(context) | Can be
|
tokenEndpoint | string | function(grant_type, context) | Can be
|
type | string | must be "oidc_server" |
userinfoEndpoint | string | function (context) | Can be:
|
Optional attributes
Key | Type | Description | Default |
---|---|---|---|
callback | function(response, context): [token,userInfo] | Callback called at the end of the authentication for extracting the token and the userInfo from the response. Inputs
| null |
codeChallengeMethod | string | Method that was used to derive an authorization code challenge | S256 |
jwksEndpoint | string | function(token, context) | jwksEndpoint is mandatory if validate = true. Can be
| null |
loginCallbackRoute | string | a relative or absolute URL called by the OIDC server after a successfull login. | [loginRoute]/callback |
logoutCallbackRoute | string | a 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 |
pkce | boolean | flag to indicate if the PKCE extension is applied. Recommended | true |
nonce | boolean | flag to indicate if the nonce in the id_token is validated on the client side. Should be done on the server side | false |
postLoginRedirectKey | string | When calling the authorize endpoint, postLoginRedirectKey represents the name of the parameter to indicate the redirect URI | redirect_uri |
postLogoutRedirectKey | string | When calling the logout endpoint, postLoginRedirectKey represents the name of the parameter to indicate the redirect URI | post_logout_redirect_uri |
responseType | string | only code is supported right now | code |
scope | string | the value of the parameter "scope" sent to the authorize endpoint. Should generally be redefined | openid |
state | boolean | flag to indicate if the javascript client send a state to the IDP. Recommended for mitigating attacks | true |
validate | boolean | flag to indicate if the id_token and the access_token are validated. Should generally be done on the server side | false |
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
}
}
}