Keycloak SSO
Embedded Radius Server inRun radius server inside keycloak. features:
- Embedded radius server in keycloak
- use keycloak authentication and authorization for the embedded RADIUS server
- radius oidc password
- radius OTP password (TOTP/HOTP via Google Authenticator or FreeOTP)
- use Keycloak user credentials, if radius access-request protocol is PAP Otherwise is using Keycloak Radius credentials or OTP
- use Kerberos/ldap credentials(only if Radius client use PAP authorization)
- can work as radius proxy
- support Radsec Protocol (Radius over TLS)
- Map Keycloak authorization , Role, Group and User Attributes to Radius Attributes
- conditional attributes for authorization/Role/Group/User
- reject attribute for authorization/Role/Group/User
- dynamically assign attributes based on keycloak policies(Role, javascript, Time, User)
- start/stop Keycloak Session
- BackChannel logout(Disconnect-message request)
- Mikrotik plugin
- Cisco plugin (thanks vbkunin)
- Chillispot plugin
- Social Hotspot Login
- PPTP VPN with Radsec
- L2TP IPSec VPN with Radius and Radsec
Examples
- Assign attributes dynamically using javascript policy
- Reject and Accept condition example
- Radius and OIDC integration example
- OTP Password example
- Specify Realm in username: username@realm
- Default Realm example(if the radius client does not support realm attribute)
Release Setup
- Download keycloak-radius.zip asset from github releases
- unzip release
unzip keycloak-radius.zip -d keycloak-radius
- 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
- open http://localhost:8090
- initialize keycloak master realm
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
requirements: keycloak 12.0.2
- setup radius-plugin
${KEYCLOAK_PATH}/bin/jboss-cli.sh --command="module add --name=keycloak.plugins.radius --resources=${SOURCE}/keycloak-plugins/radius-plugin/target/radius-plugin-1.3.4-SNAPSHOT.jar --dependencies=org.jboss.logging,org.keycloak.keycloak-core,org.keycloak.keycloak-services,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,org.apache.commons.io,javax.activation.api,javax.servlet.api,org.jboss.resteasy.resteasy-jaxrs,javax.ws.rs.api,com.fasterxml.jackson.core.jackson-databind,org.keycloak.keycloak-common,com.fasterxml.jackson.core.jackson-core,javax.transaction.api,org.hibernate,io.netty,org.slf4j,javax.xml.bind.api,org.apache.commons.codec,org.apache.commons.lang3"
- setup rad-sec plugin
${KEYCLOAK_PATH}/bin/jboss-cli.sh --command="module add --name=keycloak.plugins.rad.sec --resources=${SOURCE}/keycloak-plugins/rad-sec-plugin/target/rad-sec-plugin-1.3.4-SNAPSHOT.jar --dependencies=org.jboss.logging,org.keycloak.keycloak-core,org.keycloak.keycloak-services,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,org.apache.commons.io,javax.activation.api,com.fasterxml.jackson.core.jackson-databind,org.keycloak.keycloak-common,com.fasterxml.jackson.core.jackson-core,javax.transaction.api,org.hibernate,io.netty,org.slf4j,javax.xml.bind.api,org.apache.commons.codec,keycloak.plugins.radius,org.apache.commons.lang3"
- setup mikrotik plugin
${KEYCLOAK_PATH}/bin/jboss-cli.sh --command="module add --name=keycloak.plugins.radius.mikrotik --resources=${SOURCE}/keycloak-plugins/mikrotik-radius-plugin/target/mikrotik-radius-plugin-1.3.4-SNAPSHOT.jar --dependencies=org.jboss.logging,org.keycloak.keycloak-core,org.keycloak.keycloak-services,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,org.apache.commons.io,javax.activation.api,com.fasterxml.jackson.core.jackson-databind,org.keycloak.keycloak-common,com.fasterxml.jackson.core.jackson-core,javax.transaction.api,org.hibernate,io.netty,org.slf4j,javax.xml.bind.api,org.apache.commons.codec,keycloak.plugins.radius,org.apache.commons.lang3"
- setup cisco plugin
${KEYCLOAK_PATH}/bin/jboss-cli.sh --command="module add --name=keycloak.plugins.radius.cisco --resources=${SOURCE}/keycloak-plugins/cisco-radius-plugin/target/cisco-radius-plugin-1.3.4-SNAPSHOT.jar --dependencies=org.jboss.logging,org.keycloak.keycloak-core,org.keycloak.keycloak-services,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,org.apache.commons.io,javax.activation.api,com.fasterxml.jackson.core.jackson-databind,org.keycloak.keycloak-common,com.fasterxml.jackson.core.jackson-core,javax.transaction.api,org.hibernate,io.netty,org.slf4j,javax.xml.bind.api,org.apache.commons.codec,keycloak.plugins.radius,org.apache.commons.lang3"
- setup chillispot plugin
${KEYCLOAK_PATH}/bin/jboss-cli.sh --command="module add --name=keycloak.plugins.radius.chillispot --resources=${SOURCE}/keycloak-plugins/chillispot-radius-plugin/target/chillispot-radius-plugin-1.3.4-SNAPSHOT.jar --dependencies=org.jboss.logging,org.keycloak.keycloak-core,org.keycloak.keycloak-services,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,org.apache.commons.io,javax.activation.api,com.fasterxml.jackson.core.jackson-databind,org.keycloak.keycloak-common,com.fasterxml.jackson.core.jackson-core,javax.transaction.api,org.hibernate,io.netty,org.slf4j,javax.xml.bind.api,org.apache.commons.codec,keycloak.plugins.radius,org.apache.commons.lang3"
- setup radius-disconnect plugin
${KEYCLOAK_PATH}/bin/jboss-cli.sh --command="module add --name=keycloak.plugins.radius.dm --resources=${SOURCE}/keycloak-plugins/radius-disconnect-plugin/target/radius-disconnect-plugin-1.3.4-SNAPSHOT.jar --dependencies=org.jboss.logging,org.keycloak.keycloak-core,javax.ws.rs.api,org.keycloak.keycloak-services,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,org.apache.commons.io,javax.activation.api,com.fasterxml.jackson.core.jackson-databind,org.keycloak.keycloak-common,com.fasterxml.jackson.core.jackson-core,javax.transaction.api,org.hibernate,io.netty,org.slf4j,javax.xml.bind.api,org.apache.commons.codec,keycloak.plugins.radius,org.keycloak.keycloak-model-jpa,javax.persistence.api,org.hibernate,org.apache.commons.lang3"
- setup proxy-radius plugin
${KEYCLOAK_PATH}/bin/jboss-cli.sh --command="module add --name=keycloak.plugins.radius.proxy --resources=${SOURCE}/keycloak-plugins/proxy-radius-plugin/target/proxy-radius-plugin-1.3.4-SNAPSHOT.jar --dependencies=org.jboss.logging,org.keycloak.keycloak-core,org.keycloak.keycloak-services,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,org.apache.commons.io,javax.activation.api,com.fasterxml.jackson.core.jackson-databind,org.keycloak.keycloak-common,com.fasterxml.jackson.core.jackson-core,javax.transaction.api,org.hibernate,io.netty,org.slf4j,javax.xml.bind.api,org.apache.commons.codec,keycloak.plugins.radius,org.apache.commons.lang3"
- setup radius theme
${KEYCLOAK_PATH}/bin/jboss-cli.sh --command="module add --name=keycloak.plugins.radius.theme --resources=${SOURCE}/keycloak-radius-plugin/keycloak-plugins/radius-theme/target/radius-theme-1.3.4-SNAPSHOT.zip
- run script for standalone
${KEYCLOAK_PATH}/bin/jboss-cli.sh --file=${SOURCE}/cli/radius.cli
- run script for standalone-ha where
${KEYCLOAK_PATH}/bin/jboss-cli.sh --file=${SOURCE}/cli/radius-ha.cli
- KEYCLOAK_PATH - Path where you are unpacked keycloak-12.0.2.zip
- SOURCE - Path where you checked out the code and built the project
Configuration
Radius server config file
-
create file ${KEYCLOAK_PATH}config/radius.config
-
example
where{ "sharedSecret": "radsec", "authPort": 1812, "accountPort": 1813, "numberThreads": 8, "useUdpRadius": true, "otp": false, "radsec": { "privateKey": "config/private.key", "certificate": "config/public.crt", "numberThreads": 8, "useRadSec": true }, "coa":{ "port":3799, "useCoA":true } }
-
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
Run Keycloak Locally
#!/usr/bin/env bash
set -e
cd keycloak-12.0.2
public_ip=`ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' -m 1`
sh bin/standalone.sh -c standalone-ha.xml -b 0.0.0.0 -Djboss.bind.address.management=0.0.0.0 -Djboss.bind.address.private=${public_ip} -Djboss.node.name=${public_ip} -Djgroups.bind.address=${public_ip} --debug 8190 -Djboss.http.port=8090
Keycloak Client with Radius Protocol
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 | Yes |
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
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"
The role will only be applied if the NAS server address is 192.168.88.1 or 192.168.88.2.
Example)
Role 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:
REJECT_NAS-IP-Address = "192.168.88.2"
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"
Example)
Role 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:
ACCEPT_NAS-IP-Address = "192.168.88.1"
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
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
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"
Enable Authorization on Radius Client
Create Resource
Assign Attributes to Resource
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 Proxy
Keycloak Radius credentials
- Setup Radius Credentials during first time login
Otp Password
- enable Otp Password on Keycloak side. https://www.keycloak.org/docs/latest/server_admin/
- password in request must contain the password and otp.
- 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
- PAP password: