Skip to content

vzakharchenko/keycloak-radius-plugin

Repository files navigation

Embedded Radius Server in Keycloak SSO

CircleCI Java CI with Maven Node.js Examples Coverage Status [Maven Central] BCH compliance

Run radius server inside keycloak. features:

Examples

Donate

Donate

Release Setup

  1. Download keycloak-radius.zip asset from github releases
  2. unzip release
    unzip keycloak-radius.zip -d keycloak-radius
  3. run keycloak
    sh keycloak-radius/bin/standalone.sh  -c standalone.xml -b 0.0.0.0 -Djboss.bind.address.management=0.0.0.0 --debug 8190 -Djboss.http.port=8090
  4. open http://localhost:8090
  5. initialize keycloak master realm

Docker Container

Run inside Docker Container

Manual Setup

build project

requirements: java jdk 11 and above, maven 3.5 and above

  • cd keycloak-plugins
  • mvn clean install

Configure Keycloak (based on Quarkus)

requirements: keycloak 21.0.0

cp ${SOURCE}/keycloak-plugins/radius-plugin/target/radius-plugin-1.5.0-SNAPSHOT.jar ${KEYCLOAK_PATH}/providers/radius-plugin-1.5.0-SNAPSHOT.jar
cp ${SOURCE}/keycloak-plugins/rad-sec-plugin/target/rad-sec-plugin-1.5.0-SNAPSHOT.jar ${KEYCLOAK_PATH}/providers/rad-sec-plugin-1.5.0-SNAPSHOT.jar
cp ${SOURCE}/keycloak-plugins/mikrotik-radius-plugin/target/mikrotik-radius-plugin-1.5.0-SNAPSHOT.jar ${KEYCLOAK_PATH}/providers/mikrotik-radius-plugin-1.5.0-SNAPSHOT.jar
cp ${SOURCE}/keycloak-plugins/cisco-radius-plugin/target/cisco-radius-plugin-1.5.0-SNAPSHOT.jar ${KEYCLOAK_PATH}/providers/cisco-radius-plugin-1.5.0-SNAPSHOT.jar
cp ${SOURCE}/keycloak-plugins/chillispot-radius-plugin/target/chillispot-radius-plugin-1.5.0-SNAPSHOT.jar ${KEYCLOAK_PATH}/providers/chillispot-radius-plugin-1.5.0-SNAPSHOT.jar
cp ${SOURCE}/keycloak-plugins/radius-disconnect-plugin/target/radius-disconnect-plugin-1.5.0-SNAPSHOT.jar ${KEYCLOAK_PATH}/providers/radius-disconnect-plugin-1.5.0-SNAPSHOT.jar
cp ${SOURCE}/keycloak-plugins/proxy-radius-plugin/target/proxy-radius-plugin-1.5.0-SNAPSHOT.jar ${KEYCLOAK_PATH}/providers/proxy-radius-plugin-1.5.0-SNAPSHOT.jar
cp ${SOURCE}/keycloak-radius-plugin/keycloak-plugins/radius-theme/target/radius-theme-1.5.0-SNAPSHOT.zip ${KEYCLOAK_PATH}/providers/radius-theme-1.5.0-SNAPSHOT.jar

where

Environment Variables

Variable Name Variable Value Config file Location
KEYCLOAK_PATH Path where you are unpacked keycloak ${KEYCLOAK_PATH}/config/radius.config
RADIUS_CONFIG_PATH Path where you store radius.config ${RADIUS_CONFIG_PATH}/radius.config

Examples:

export RADIUS_CONFIG_PATH= /opt/keycloak/radius/config

or

export KEYCLOAK_PATH= /opt/keycloak/

Configuration

Radius server config file

  • create file ${KEYCLOAK_PATH}config/radius.config or ${RADIUS_CONFIG_PATH}/radius.config

  • example

    {
    "sharedSecret": "radsec",
    "authPort": 1812,
    "accountPort": 1813,
    "numberThreads": 8,
    "useUdpRadius": true,
    "externalDictionary": "/opt/dictionary",
    "otp": false,
    "radsec": {
    "privateKey": "config/private.key",
    "certificate": "config/public.crt",
    "numberThreads": 8,
    "useRadSec": true
    },
    "coa":{
    "port":3799,
    "useCoA":true
    }
    }
    
    where

  • sharedSecret - Used to secure communication between a RADIUS server and a RADIUS client.

  • authPort - Authentication and authorization port

  • accountPort - Accounting port

  • useUdpRadius - if true, then listen to authPort and accountPort

  • radsec - radsec configuration

  • privateKey - private SSL key (https://netty.io/wiki/sslcontextbuilder-and-private-key.html)

  • certificate - certificates chain

  • useRadSec - if true, then listen radsec port

  • numberThreads - number of connection threads

  • coa - CoA request configuration

  • port - CoA port (Mikrotik:3799, Cisco:1700)

  • useCoA - use CoA request

  • otp - use OTP without password

  • externalDictionary - path to the dictionary file in freeradius format

Run Keycloak Locally

#!/usr/bin/env bash
set -e
cd keycloak-21.0.0
sh bin/kc.sh --debug 8190 start-dev --http-port=8090

Keycloak Client with Radius Protocol

radiusProtocol

Mapping Radius Password to Keycloak Credentials

Radius Protocol Keycloak credentials Keycloak credentials with OTP Kerberos credentials Ldap credentials Keycloak Radius credentials Keycloak Radius credentials with OTP Keycloak OTP(if config file contains "otp":true)
PAP Yes Yes Yes Yes Yes Yes NO
CHAP No No No No Yes Yes Yes
MSCHAPV2 No No No No Yes Yes Yes

Assign Radius Attributes to Role

NOTE: Composite roles supported

RoleAttributes

Role Conditional Attributes

if conditional Attribute is present and has valid value then all other attributes will be applied. (Example: apply role attributes only if NAS-IP-Address= 192.168.88.1)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    COND_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example:

COND_NAS-IP-Address = "192.168.88.1, 192.168.88.2"

ConditionalRole The role will only be applied if the NAS server address is 192.168.88.1 or 192.168.88.2.

Role REJECT Attributes (Example)

if reject Attribute is present and has valid value then access request will be rejected. (Example: reject user request if access request contains attribute NAS-IP-Address= 192.168.88.1)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    REJECT_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example:

REJECT_NAS-IP-Address = "192.168.88.2"

reject_conditional The role will only be applied if the NAS server address is not 192.168.88.2, otherwise request will be rejected

Role REJECT WITHOUT CONDITION

If Reject Attribute is present then access request will be rejected. Structure of Attribute: REJECT_RADIUS=<ANY VALUE> Example:

REJECT_RADIUS = "true"

Role ACCEPT Attributes (Example)

if accept Attribute is present and has valid value then access request will be accepted, otherwise rejected. (Example: accept user request if access request contains attribute NAS-IP-Address= 192.168.88.1,192.168.88.2)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    ACCEPT_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example:

ACCEPT_NAS-IP-Address = "192.168.88.1"

acceptConditional The role will only be applied if the NAS server address is not 192.168.88.2, otherwise request will be rejected

Assign Radius Attributes to Group

NOTE: SubGroups supported groupAttributes

Group Conditional Attributes

if conditional Attribute is present and has valid value then all other attributes will be applied. (Example: apply group attributes only if NAS-IP-Address= 192.168.88.1)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    COND_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role Conditional Attributes/README.md:1

Group REJECT Attributes

if reject Attribute is present and has valid value then access request will be rejected. (Example: reject user request if access request contains attribute NAS-IP-Address= 192.168.88.1)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    REJECT_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role REJECT Attributes

Group REJECT WITHOUT CONDITION

If Reject Attribute is present then access request will be rejected. Structure of Attribute: REJECT_RADIUS=<ANY VALUE> Example:

REJECT_RADIUS = "true"

Group ACCEPT Attributes

if accept Attribute is present and has valid value then access request will be accepted, otherwise rejected. (Example: accept user request if access request contains attribute NAS-IP-Address= 192.168.88.1,192.168.88.2)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    ACCEPT_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role ACCEPT Attributes

Assign Radius Attributes to User

userAttributes

User Conditional Attributes

if conditional Attribute is present and has valid value then all other attributes will be applied. (Example: apply user attributes only if NAS-IP-Address= 192.168.88.1)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    COND_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role Conditional Attributes/README.md:1

User REJECT Attributes

if reject Attribute is present and has valid value then access request will be rejected. (Example: reject user request if access request contains attribute NAS-IP-Address= 192.168.88.1)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    REJECT_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role REJECT Attributes

User ACCEPT Attributes

if accept Attribute is present and has valid value then access request will be accepted, otherwise rejected. (Example: accept user request if access request contains attribute NAS-IP-Address= 192.168.88.1,192.168.88.2)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    ACCEPT_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role ACCEPT Attributes

Assign Radius Attributes to Authorization Resource

Change admin theme to "Radius"

radiusTheme

Enable Authorization on Radius Client

Authorization

Authorization

assignAttributesToResource

Create policy and permissions

Resource Conditional Attributes

if conditional Attribute is present and has valid value then all other attributes will be applied. (Example: apply user attributes only if NAS-IP-Address= 192.168.88.1)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    COND_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role Conditional Attributes/README.md:1

Resource REJECT Attributes

if reject Attribute is present and has valid value then access request will be rejected. (Example: reject user request if access request contains attribute NAS-IP-Address= 192.168.88.1)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    REJECT_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role REJECT Attributes

Resource REJECT without condition

If Reject Attribute is present then access request will be rejected. Structure of Attribute: REJECT_RADIUS=<ANY VALUE> Example:

REJECT_RADIUS = "true"

Resource ACCEPT Attributes

if accept Attribute is present and has valid value then access request will be accepted, otherwise rejected. (Example: accept user request if access request contains attribute NAS-IP-Address= 192.168.88.1,192.168.88.2)

Structure of Attribute:

<PREFIX><ATTRIBUTE_NAME>=<values>

  • PREFIX =
    ACCEPT_
  • ATTRIBUTE_NAME attribute name from access-request
  • VALUES Comma-separated list of attribute values

Example: Role ACCEPT Attributes

Hotspot Example (with Facebook login)

Hotspot Example (with Facebook login)

Example CoA Configuration

Radius Disconnect Message

Radius Proxy

Radius Proxy Module

Keycloak Radius credentials

  • Setup Radius Credentials during first time login
    1. set Action "Update Radius Password" (or send this event to user be email) updateRadiusPassword
    2. User sets his own Radius password RadiusUserPassword

Otp Password

  1. enable Otp Password on Keycloak side. https://www.keycloak.org/docs/latest/server_admin/ impersonateUserExample3 impersonateUserExample4
  2. password in request must contain the password and otp.
  3. Structure Password in request:
    • PAP password: <Keycloak Password/RADIUS Password><OTP> example: testPassword123456, where testPassword is password, 123456 is otp
    • MSCHAP/CHAP: <RADIUS Password><OTP> example: testPassword123456, where testPassword is password, 123456 is otp
    • PAP password with Otp (if config file contains "otp":true) : <OTP> example: 123456, where 123456 is otp

OTP Password example

WebAuthn Authentication

wiki page

Add custom Radius Dictionary(example for Fortinet)

  • create dictionary Fortinet.dictionary:
VENDOR		12356   Fortinet

VENDORATTR	12356 Fortinet-Group-Name			1	string
VENDORATTR	12356 Fortinet-Client-IP-Address		2	ipaddr
VENDORATTR	12356 Fortinet-Vdom-Name			3	string
VENDORATTR	12356 Fortinet-Client-IPv6-Address		4	octets
VENDORATTR	12356 Fortinet-Interface-Name			5	string
VENDORATTR	12356 Fortinet-Access-Profile			6	string
  • run as docker container
  docker run -p 8090:8080 -e  -server -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true" -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -e RADIUS_DICTIONARY=/opt/dictionary -v `pwd`/Fortinet.dictionary:/opt/dictionary   vassio/keycloak-radius-plugin

Development

wiki page