Skip to content

elkman/keycloak-radius-plugin

 
 

Repository files navigation

Embedded Radius Server in Keycloak SSO

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

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 17 and above, maven 3.5 and above

  • cd keycloak-plugins
  • mvn clean install

Configure Keycloak (based on Quarkus)

requirements: keycloak 24.0.5

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

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",
    "otpWithoutPassword": [ ],
    "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
  • otpWithoutPassword - allow OTP without password for the supplied protocols (CHAP, MSCHAPV2, PAP), e.g. "otpWithoutPassword": [ "chap", "mschapv2", "pap" ]
  • otp - deprecated, ignored if otpWithoutPassword is defined, otherwise "otp":true is interpreted for backward compatibility as "otpWithoutPassword": [ "chap", "mschapv2" ]
  • externalDictionary - path to the dictionary file in freeradius format

Run Keycloak Locally

#!/usr/bin/env bash
set -e
cd keycloak-24.0.5
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 without password
PAP Yes Yes Yes Yes Yes Yes Yes *1
CHAP No No No No Yes Yes Yes
MSCHAPV2 No No No No Yes Yes Yes

*1) In contrast to CHAP and MSCHAPV2, an OTP token must be registered with the account for PAP and OTP without a password. This prevents authentication from being successful with the password only, even if the user does not yet have a token. An OTP token code is always required as a second factor (password plus code or code without password).

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 concatenated with OTP token code .
  3. Structure Password in request:
    • PAP password: <Keycloak Password/RADIUS Password><OTP>, example: testPassword123456, where testPassword is password, 123456 is OTP
    • MSCHAPV2/CHAP: <RADIUS Password><OTP>, example: testPassword123456, where testPassword is password, 123456 is OTP
    • PAP password with OTP without password (if config file contains "otpWithoutPassword": [ "pap", ... ]): <OTP> or <RADIUS Password/Keycloak Password/RADIUS Password><OTP>, example: 123456, where 123456 is OTP
    • MSCHAPV2/CHAP password with OTP without password (if config file contains "otpWithoutPassword": [ "chap", "mschapv2", ... ]): <OTP> or <RADIUS Password><OTP> or <RADIUS Password> if no OTP token is registered, 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

About

Make the radius server as part of keycloak SSO

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 73.5%
  • JavaScript 16.8%
  • HTML 8.6%
  • Other 1.1%