Skip to content
Vasiliy edited this page Jul 11, 2021 · 4 revisions

Radius WebAuthn authentication

NodeJS Example: WebAuthnJSExample

Keycloak Configuration

  1. Register WebAuthn Required action
  2. Copy a Browser Flow
  3. Modify a new browser Flow to use WebAuthn . Alternative you can modify a new browser Flow to use both Password and WebAuthn
  4. Binding browser flow to WebAuthn browser Flow alternative you can binding inside your webauthn security client
  5. Create webauthn security client
  6. added builtin "Session Radius Password" mapper
  7. create a new user

Get radius password from code:

Parse access_token JWT token. and get parameter "s" from payload:

eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJUaERoczc1bWdzYmVQUzAxTHNnakg5SkpNUm5FWnJKWjZtdE4xNjUydkhBIn0.eyJleHAiOjE2MjYwMjcwOTgsImlhdCI6MTYyNjAyNjc5OCwiYXV0aF90aW1lIjoxNjI2MDI2Mzk4LCJqdGkiOiIyZWZlMTJmMS1mMDcwLTQ1MjUtYjM0ZS0zZmUxNjc5YTI3OTYiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwOTAvYXV0aC9yZWFsbXMvd2ViYXV0aG4iLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiNWE1YTdhMWMtNzc3Mi00NjdhLWI3YzUtNTQxMThjMWNjOWUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoid2ViYXV0aG4tY2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6IjM0ZDBkNTE4LTQxYmQtNDlkMi1iMTAxLWY3NzExODE0YWQ1ZSIsImFjciI6IjAiLCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCIsIm5wIjoicyIsInMiOiJFR3htcTU4c1R5OU5hdCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6IlJhZGl1cyBVc2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidXNlciIsImdpdmVuX25hbWUiOiJSYWRpdXMiLCJmYW1pbHlfbmFtZSI6IlVzZXIiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJuIjoicHJlZmVycmVkX3VzZXJuYW1lIn0.FC5Xj_E7L7fyfBGcbkq_Gy8FZgjhGf48WWldBqgMZCtFg5CGZ-4ye0HOb_1YlKxCQ4rpfqFh0bZvV2fXy7jtVSuc88bIpP7gRhHh4JVZaMnMj7Fj5-nreFpupiIkEgrXnqzNntetsv2wfvdQSZRWyzZwdxqwWtwU3goA6ac9v3HlNRaqAZNRBnP0Tq8_ZuavvfXa0daXwkMexCt8FpD3FxN6Bme0GviT2YuNmSFs5so2UtZwMEHlEY4eiyKjtL3KsEbdGUD9LS3E5GQwsV6V-pmgKtOZIfA5UWm0I5oauPKgMMLvwx48AyFnNHp_aUGy85_UPMFciqd-G_sNDNWUOQ

parsed payload

{
  "exp": 1626027098,
  "iat": 1626026798,
  "auth_time": 1626026398,
  "jti": "2efe12f1-f070-4525-b34e-3fe1679a2796",
  "iss": "http://localhost:8090/auth/realms/webauthn",
  "aud": "account",
  "sub": "5a5a7a1c-7772-467a-b7c5-54118c1cc9e2",
  "typ": "Bearer",
  "azp": "webauthn-client",
  "session_state": "34d0d518-41bd-49d2-b101-f7711814ad5e",
  "acr": "0",
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "openid profile email",
  "np": "s",
  "s": "EGxmq58sTy9Nat",
  "email_verified": false,
  "name": "Radius User",
  "preferred_username": "user",
  "given_name": "Radius",
  "family_name": "User",
  "email": "user@example.com",
  "n": "preferred_username"
}

where

  • s - temporary radius password (valid until your access token expires)

NodeJS example for getting temporary Radius password

// index.js
const express = require('express');
const Keycloak = require('keycloak-connect');
var session = require('express-session');
const bodyParser = require('body-parser');

const memoryStore = new session.MemoryStore();

const keycloak = new Keycloak({
    store: memoryStore
});

const app = express();

app.use(bodyParser.urlencoded({extended: true}));

app.use(session({
    secret: 'mySecret',
    resave: false,
    saveUninitialized: true,
    store: memoryStore
}));

app.use(keycloak.middleware({
    logout: '/logout',
}));

function getTemporaryRadiusPassword(request, response) {
    const accessToken = request.kauth.grant.access_token.content;
    return accessToken.s;
}

app.get('/getPassword', keycloak.protect(), (request, response) => {
    response.json({password: getTemporaryRadiusPassword(request, response)})
});