Backend guide
After a successful login Hanko issues a cookie containing a JSON Web Token
(JWT). You can use this JWT to authenticate
requests on your backend. To do so, first retrieve the JSON Web Key Set
(JWKS)
containing the public keys used to verify the JWT from the Hanko API's .well-known/jwks.json
endpoint.
Then use the JWKS to verify the JWT using a library for the programming language of your choice.
- Go
- Node.js
This is an example of a custom middleware in a Go-based backend using Echo and the lestrrat-go/jwx package:
import (
"context"
"fmt"
"log"
"net/http"
"github.com/labstack/echo/v4"
"github.com/lestrrat-go/jwx/v2/jwk"
"github.com/lestrrat-go/jwx/v2/jwt"
)
func SessionMiddleware() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
cookie, err := c.Cookie("hanko")
if err == http.ErrNoCookie {
return c.Redirect(http.StatusTemporaryRedirect, "/unauthorized")
}
if err != nil {
return err
}
// replace "hankoApiURL" with your API URL
set, err := jwk.Fetch(
context.Background(),
fmt.Sprintf("%v/.well-known/jwks.json", hankoApiURL)
)
if err != nil {
return err
}
token, err := jwt.Parse([]byte(cookie.Value), jwt.WithKeySet(set))
if err != nil {
return c.Redirect(http.StatusTemporaryRedirect, "/unauthorized")
}
log.Printf("session for user '%s' verified successfully", token.Subject())
c.Set("token", cookie.Value)
c.Set("user", token.Subject())
return next(c)
}
}
}
This is an example of using a custom middleware in an express-based backend using the express-jwt and jwks-rsa packages:
const Express = require('express');
const { expressjwt: jwt } = require("express-jwt");
const jwksRsa = require('jwks-rsa');
const cookieParser = require('cookie-parser');
const jwksHost = process.env.HANKO_API_URL;
const app = new Express();
app.use(cookieParser())
app.use(jwt({
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 2,
jwksUri: `${jwksHost}/.well-known/jwks.json`
}),
algorithms: [ 'RS256' ],
getToken: function fromCookieOrHeader(req) {
if (
req.headers.authorization &&
req.headers.authorization.split(" ")[0] === "Bearer"
) {
return req.headers.authorization.split(" ")[1];
} else if (req.cookies && req.cookies.hanko) {
return req.cookies.hanko;
}
return null;
}
}));
// The decoded JWT is available through the `req.auth` property (the exact property
// making it available can be customized through the `requestProperty` option on
// middleware creation).
// see: https://github.com/auth0/express-jwt#api
app.get("/protected", function (req, res) {
if (!req.auth.sub) return res.sendStatus(401);
res.sendStatus(200);
}
);