> For the complete documentation index, see [llms.txt](https://docs.fortifiedid.se/radiusclient/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fortifiedid.se/radiusclient/readme.md).

# RadiusClient

## Introduction

The RadiusClient module sends RADIUS Access-Request messages to a RADIUS server and returns the result (Accept, Reject, or Challenge) to the caller.

Each module instance targets a single RADIUS server. To connect to multiple servers, configure multiple module instances with different names. Two transport modes are supported:

* **PAP/UDP** — classic RADIUS over UDP using a shared secret (RFC 2865)
* **RadSec/TCP+TLS** — RADIUS over a persistent TLS connection (RFC 6614)

{% hint style="info" %}
RadSec clients reuse a single TLS connection across all requests in accordance with RFC 6614 §2.6.4. A new connection is established automatically if the existing one is lost.
{% endhint %}

## Configuration

{% hint style="info" %}
**Module name:** `RadiusClient`
{% endhint %}

{% tabs %}
{% tab title="Properties" %}

<table><thead><tr><th width="220">Name</th><th width="300">Description</th><th>Default</th><th data-type="checkbox">Mandatory</th></tr></thead><tbody><tr><td><code>name</code></td><td>Destination name. Unique identifier for this module instance. Must be unique across all RadiusClient configurations.</td><td><code>"default"</code></td><td>false</td></tr><tr><td><code>host</code></td><td>Hostname or IP address of the RADIUS server.</td><td></td><td>true</td></tr><tr><td><code>port</code></td><td>UDP or TCP port of the RADIUS server.</td><td><code>1812</code> (PAP), <code>2083</code> (RadSec)</td><td>false</td></tr><tr><td><code>radsec</code></td><td>Enable RadSec mode (RADIUS over TCP+TLS). When <code>false</code>, PAP/UDP is used.</td><td><code>false</code></td><td>false</td></tr><tr><td><code>secret</code></td><td>Shared secret used to authenticate and encrypt PAP/UDP packets. Not used in RadSec mode (the shared secret is always <code>"radsec"</code> per RFC 6614).</td><td></td><td>true</td></tr><tr><td><code>timeout_ms</code></td><td>Time in milliseconds to wait for a response before the request fails.</td><td><code>5000</code></td><td>false</td></tr><tr><td><code>request_attrs</code></td><td>Optional array of additional RADIUS attributes to include in every Access-Request. See <a href="#request-attributes">Request attributes</a>.</td><td></td><td>false</td></tr></tbody></table>
{% endtab %}

{% tab title="Example (PAP/UDP)" %}

```json
{
  "name": "RadiusClient",
  "config": {
    "name": "default",
    "host": "radius.example.com",
    "port": 1812,
    "secret": "sharedsecret",
    "timeout_ms": 5000,
    "request_attrs": [
      { "type": 32, "value": "gw-01" },
      { "type": 6,  "value": "2", "value_type": "integer" }
    ]
  }
}
```

{% endtab %}

{% tab title="Example (RadSec)" %}

```json
{
  "name": "RadiusClient",
  "config": {
    "name": "default",
    "host": "radius.example.com",
    "port": 2083,
    "radsec": true,
    "ssl_truststore": { "path": "/etc/fortified/ssl/ca.p12", "password": "trustpass" },
    "ssl_keystore":   { "path": "/etc/fortified/ssl/client.p12", "password": "storepass" },
    "ssl_verify_host": true,
    "timeout_ms": 5000
  }
}
```

{% endtab %}
{% endtabs %}

### Request attributes

The `request_attrs` array lets the operator include additional RADIUS attributes in every Access-Request — for example `NAS-Identifier` (type 32) or `Service-Type` (type 6).

{% hint style="warning" %}
Attribute types 1 (`User-Name`) and 2 (`User-Password`) are reserved and cannot be used in `request_attrs`.
{% endhint %}

{% tabs %}
{% tab title="Properties" %}

<table><thead><tr><th width="160">Name</th><th width="340">Description</th><th>Default</th><th data-type="checkbox">Mandatory</th></tr></thead><tbody><tr><td><code>type</code></td><td>RADIUS attribute type code (integer, 3–255).</td><td></td><td>true</td></tr><tr><td><code>value</code></td><td>Attribute value as a string.</td><td></td><td>true</td></tr><tr><td><code>value_type</code></td><td>Encoding of the value. One of: <code>string</code> (UTF-8), <code>integer</code> or <code>time</code> (4-byte big-endian), <code>ipaddr</code> (dotted-decimal IPv4), <code>ipv6addr</code> (IPv6), <code>octets</code> (hex-encoded raw bytes).</td><td><code>"string"</code></td><td>false</td></tr></tbody></table>
{% endtab %}

{% tab title="Example" %}

```json
"request_attrs": [
  { "type": 32, "value": "fortifiedid-gw-01" },
  { "type": 6,  "value": "2",   "value_type": "integer" },
  { "type": 5,  "value": "1812","value_type": "integer" }
]
```

{% endtab %}
{% endtabs %}

### SSL/TLS (RadSec)

RadSec requires a TLS connection. The following options control the TLS configuration.

{% tabs %}
{% tab title="Properties" %}

<table><thead><tr><th width="240">Name</th><th width="320">Description</th><th>Default</th><th data-type="checkbox">Mandatory</th></tr></thead><tbody><tr><td><code>ssl_truststore</code></td><td>Truststore object: <code>path</code> (PKCS12 file), <code>password</code>. Used to verify the server certificate. If omitted, the default Java truststore is used.</td><td></td><td>false</td></tr><tr><td><code>ssl_keystore</code></td><td>Keystore object: <code>path</code> (PKCS12 file), <code>password</code> (opens the store), optional <code>key_password</code> (private key entry — defaults to <code>password</code>), optional <code>alias</code> (key entry alias — defaults to first alias in the store). Used for mutual TLS (client certificate).</td><td></td><td>false</td></tr><tr><td><code>ssl_verify_host</code></td><td>Whether to verify that the server certificate hostname matches <code>host</code>.</td><td><code>true</code></td><td>false</td></tr><tr><td><code>ssl_trust_all</code></td><td>Disable all SSL certificate validation. Not recommended for production.</td><td><code>false</code></td><td>false</td></tr></tbody></table>
{% endtab %}

{% tab title="Example" %}

```json
{
  "name": "RadiusClient",
  "config": {
    "name": "radsec-prod",
    "host": "radius.example.com",
    "port": 2083,
    "radsec": true,
    "ssl_truststore": { "path": "/etc/fortified/ssl/ca.p12", "password": "trustpass" },
    "ssl_keystore":   { "path": "/etc/fortified/ssl/client.p12", "password": "storepass", "key_password": "keypass", "alias": "client" },
    "ssl_verify_host": true,
    "timeout_ms": 5000
  }
}
```

{% endtab %}
{% endtabs %}

## Multi-step authentication (Challenge/Response)

Some RADIUS servers implement multi-factor authentication using Access-Challenge responses. When a challenge is received the caller must include the `state` value returned in the challenge as part of the next Access-Request.

```
1. Caller → Access-Request (username + password)
2. RADIUS → Access-Challenge (state + optional Reply-Message)
3. Caller → Access-Request (username + OTP + state)
4. RADIUS → Access-Accept / Access-Reject
```

The `state` attribute (type 24) is surfaced as a top-level field in the response alongside the response type:

```json
{ "type": "CHALLENGE", "state": "a1b2c3d4", "attrs": [...] }
```

The caller includes it in the next request:

```json
{ "username": "alice", "password": "123456", "state": "a1b2c3d4" }
```

## Response attributes

All RADIUS response attributes are returned in the `attrs` array, encoded as hex strings. The caller is responsible for decoding the attributes it cares about.

```json
{
  "type": "ACCEPT",
  "attrs": [
    { "type": 18, "hex": "57656c636f6d6521" },
    { "type":  8, "hex": "0a000001"         }
  ]
}
```

| Field  | Description                                 |
| ------ | ------------------------------------------- |
| `type` | RADIUS attribute type code (integer, 1–255) |
| `hex`  | Attribute value encoded as a hex string     |

## Troubleshooting

To enable detailed logging, add the following to `log4j2.xml`:

```xml
<!-- Handler-level logs (request received, response type, errors) -->
<AsyncLogger name="foss.platform.modules.radius.impl.RadiusRequestHandler" level="DEBUG"/>

<!-- RadSec connection lifecycle (connect, disconnect, reconnect) -->
<AsyncLogger name="foss.platform.modules.radius.impl.TcpTlsRadiusClient" level="DEBUG"/>

<!-- PAP/UDP request lifecycle -->
<AsyncLogger name="foss.platform.modules.radius.impl.UdpRadiusClient" level="DEBUG"/>
```

Required level by message type:

* `INFO`
  * Module start — transport mode, host, port, timeout, number of configured `request_attrs`
* `DEBUG`
  * Access-Request sent (username, module name)
  * Response received (type: ACCEPT / REJECT / CHALLENGE)
  * RadSec connect / disconnect / reconnect
  * Late or unknown response identifier ignored
* `WARN`
  * `ssl_verify_host: false` — hostname verification disabled
  * `ssl_trust_all: true` — all certificate validation disabled
* `ERROR`
  * Request failed (with full stack trace)
  * RadSec packet write failure
  * Invalid packet length received


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.fortifiedid.se/radiusclient/readme.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
