Obtain your Hanko API URL
Log in to Hanko Cloud and select your project.
Navigate to the Dashboard
.
Find your API URL
on the top of the dashboard.
Copy the URL to a .env
file.
HANKO_API_URL = https://f4****-4802-49ad-8e0b-3d3****ab32.hanko.io
Validate a session token
Upon a successful login, Hanko sends a cookie containing a JSON Web Token
(JWT ). You can use this JWT to authenticate requests on your backend.
See
here for more details on sessions
The steps required to validate a session JWT depend on whether sessions are configured to be stateful (server-side) or
stateless.
Stateful (server-side) Stateless
Validate the session using the sessions/validate
endpoint :
Use the session token to retrieve info about session validity, expiry, and user ID of the user the session
is associated with.
Validate the session using the sessions/validate
endpoint :
Use the session token to retrieve info about session validity, expiry, and user ID of the user the session
is associated with.
Retrieve the JSON Web Key Set (JWKS ): The JWKS has the public
keys to verify the JWT. Fetch it from the Hanko API’s .well-known/jwks.json
endpoint.
Verify the JWT: Use the JWKS to verify the JWT.
Examples
Express
In the following example, we demonstrate how to implement a custom middleware in an Express.js
application.
Stateful (server-side) Stateless const express = require ( "express" );
const cookieParser = require ( "cookie-parser" );
const dotenv = require ( "dotenv" ). config ();
const app = new Express ();
app . use ( cookieParser ());
async function validateToken ( req , res , next ) {
let token = null ;
if (
req . headers . authorization &&
req . headers . authorization . split ( " " )[ 0 ] === "Bearer"
) {
token = req . headers . authorization . split ( " " )[ 1 ];
} else if ( req . cookies && req . cookies . hanko ) {
token = req . cookies . hanko ;
}
if ( token === null || token . length === 0 ) {
res . status ( 401 ). send ( "Unauthorized" );
return ;
}
try {
response = await fetch ( ` ${ process . env . HANKO_API_URL } /sessions/validate` , {
headers: {
'Accept' : 'application/json' ,
'Content-Type' : 'application/json'
},
method: "POST" ,
body: JSON . stringify ({
session_token: token
})
});
if ( ! response . ok ) {
let error = await response . json ();
sendError ( res , error );
return ;
}
const session = await response . json ()
if ( ! session . is_valid ) {
sendError ( res , error );
return ;
}
} catch ( error ) {
sendError ( res , error )
return ;
}
next ();
}
function sendError ( res , cause ) {
let error = { message: "Invalid session token" }
if ( cause ) {
error . cause = cause ;
}
res . status ( 401 ). send ( error )
}
app . use ( validateToken );
app . get ( "/protected" , function ( req , res ) {
res . sendStatus ( 200 );
});
const express = require ( "express" );
const cookieParser = require ( "cookie-parser" );
const dotenv = require ( "dotenv" ). config ();
const app = new Express ();
app . use ( cookieParser ());
async function validateToken ( req , res , next ) {
let token = null ;
if (
req . headers . authorization &&
req . headers . authorization . split ( " " )[ 0 ] === "Bearer"
) {
token = req . headers . authorization . split ( " " )[ 1 ];
} else if ( req . cookies && req . cookies . hanko ) {
token = req . cookies . hanko ;
}
if ( token === null || token . length === 0 ) {
res . status ( 401 ). send ( "Unauthorized" );
return ;
}
try {
response = await fetch ( ` ${ process . env . HANKO_API_URL } /sessions/validate` , {
headers: {
'Accept' : 'application/json' ,
'Content-Type' : 'application/json'
},
method: "POST" ,
body: JSON . stringify ({
session_token: token
})
});
if ( ! response . ok ) {
let error = await response . json ();
sendError ( res , error );
return ;
}
const session = await response . json ()
if ( ! session . is_valid ) {
sendError ( res , error );
return ;
}
} catch ( error ) {
sendError ( res , error )
return ;
}
next ();
}
function sendError ( res , cause ) {
let error = { message: "Invalid session token" }
if ( cause ) {
error . cause = cause ;
}
res . status ( 401 ). send ( error )
}
app . use ( validateToken );
app . get ( "/protected" , function ( req , res ) {
res . sendStatus ( 200 );
});
This example uses the jose package for parsing and verifying JWTs.
const express = require ( "express" );
const cookieParser = require ( "cookie-parser" );
const jose = require ( "jose" );
const dotenv = require ( "dotenv" ). config ();
const app = new Express ();
app . use ( cookieParser ());
const JWKS = jose . createRemoteJWKSet (
new URL ( ` ${ process . env . HANKO_API_URL } /.well-known/jwks.json` )
);
async function validateToken ( req , res , next ) {
let token = null ;
if (
req . headers . authorization &&
req . headers . authorization . split ( " " )[ 0 ] === "Bearer"
) {
token = req . headers . authorization . split ( " " )[ 1 ];
} else if ( req . cookies && req . cookies . hanko ) {
token = req . cookies . hanko ;
}
if ( token === null || token . length === 0 ) {
res . status ( 401 ). send ( "Unauthorized" );
return ;
}
let authError = false ;
await jose . jwtVerify ( token , JWKS ). catch (( err ) => {
authError = true ;
console . log ( err );
});
if ( authError ) {
res . status ( 401 ). send ( "Authentication Token not valid" );
return ;
}
next ();
}
app . use ( validateToken );
app . get ( "/protected" , function ( req , res ) {
res . sendStatus ( 200 );
});
Try it yourself
Node and Express.js example (React frontend) Full source code available on our GitHub.
Node and Express.js example (Vue frontend) Full source code available on our GitHub.
Node and Express.js example (Svelte frontend) Full source code available on our GitHub.