RADIUS authentication AuthStates
Introduction and overview
RADIUS is a secure authentication protocol that enables access to various common authentication services. nevisAuth implements both a generic RADIUS client as well a specialized AuthState for RSA SecurID integration with the RSA ACE/Server.
RadiusAuthState
The RadiusAuthState is used to make a generic RADIUS request and to internalize and react to the corresponding response.
The RadiusAuthState uses TinyRadius clients for backend access. TinyRadius is an open source library under the LGPL license. Find more details here:
Description
The following table and chapters describe the characteristics of the AuthState.
Topic | Description |
---|---|
Class | ch.nevis.esauth.auth.states.radius.RadiusAuthState |
Logging | RADIUS |
Auditing | none |
Marker | RADIUS:extern |
Methods | authenticate, stepup, unlock, logout |
Properties
connection.N
(string, required)One or several connection strings may be configured with postfixes of the form
.N
(N being a consecutive numbering). The connection string is a comma-separated list of key/value pairs. The following keys are supported:host
Host name of the RADIUS server (required)authPort
Port for authentication requests. Default: 1812acctPort
Port for accounting requests. Default: 1813secret
Shared secret required to communicate with the server (required). Use nevisCred (with the neviscred://... syntax) to protect the value in the configuration.timeout
Server communication time-out in milliseconds. Default: 10000 (10 seconds)
This AuthState uses the UDP protocol to send messages to backend servers. It is thus susceptible to SOCKS proxies, as described in the chapter Configuring proxies.
poolingMode
({failover,load balancing}, failover)Defines the handling of multiple configured connections.
discardInterval
(duration in seconds, 10)Sets the interval during which a backend service will not be connected to when connectivity problems occurred.
retryDiscardedResources
(boolean, false)When all configured connections are blocked by the
discardInterval
, enabling this setting will have the AuthState retry connections before thediscardInterval
has passed. The next connection to retry will be selected according to the pooling mode configured.request.type
(string {Access-Request,Accounting-Request}, required)The RADIUS RequestType that shall be sent to the server.
Note that Access-Request has a special behavior:
- If no User-Name attribute is configured: the
loginId
or${inargs:isiwebuserid}
will be set (if applicable). - If no User-Password attribute is configured:
${inargs:isiwebpasswd}
will be set (if applicable). - If no State attribute is configured: The state received in the last RADIUS response (
${sess:radius.State}
) will be set (if applicable).
- If no User-Name attribute is configured: the
request.attributes
(comma-separated list, -)The RADIUS attributes to send in the request packet. Each attribute must be specified in the form
<attr-type>=<attr-value-expression>
. Example:User-Name=${request:userId}, User-Password=${inargs:passwd},State=${}
authenticateOn
(string, -)RADIUS ResponseType that signals authentication. If the server responds with this type of packet, the AuthState will signal authentication with the user ID that was used in the request.
scope
(string {outargs, notes, session, inctx, inargs, roles}, "outargs")Variable scope where attributes of incoming response are stored.
Input
none
Transitions
<ResponseType>
Use Response-Types as transitions to react to specific responses of the RADIUS server.
Output
radius*
The RADIUS attributes of the received response are placed in the configured scope with the prefix radius..`
Errors
lasterror=99
lasterrorinfo=communication failure or unexpected response
Notes
none
Example
<AuthState name="RadiusWeak"
class="ch.nevis.esauth.auth.states.radius.RadiusAuthState">
<ResultCond name="Access-Challenge" next="RadiusStrong"/>
<Response value="AUTH_CONTINUE">
<Gui name="AuthUidPwDialog" label="login.radius.label">
<GuiElem name="lasterror" type="error" label="${notes:lasterrorinfo}"
value="${notes:lasterror}"/>
<GuiElem name="lastmsg" type="info" label="login.uidpw.text"
value="${notes:radius.Reply-Message}"/>
<GuiElem name="userid" type="text" label="userid.label"
value="${request:loginid}"/>
<GuiElem name="passwd" type="pw-text" label="login.password.label"/>
<GuiElem name="submit" type="button" label="login.button.label"
value="login"/>
</Gui>
</Response>
<property name="connection.1"
value="host=radius1.server.host.company.com, secret=changeit"/>
<property name="connection.2"
value="host=radius2.server.host.company.com, secret=changeit"/>
<property name="scope" value="session"/>
<property name="request.attributes"
value="User-Name=${inargs:user}, User-Password=${inargs:passwd}"/>
</AuthState>
<AuthState name="RadiusStrong"
class="ch.nevis.esauth.auth.states.radius.RadiusAuthState">
<ResultCond name="Access-Accept" next="AuthDone" authLevel="auth.strong"/>
<Response value="AUTH_CONTINUE">
<Gui name="Radius-OTP" label="login.uidpw.label">
<GuiElem name="lasterror" type="error" label="${notes:lasterrorinfo}"
value="${notes:lasterror}"/>
<GuiElem name="info" type="info" label="${sess:radius.Reply-Message}"/>
<GuiElem name="otp" type="pw-text" label="login.otp.label"/>
<GuiElem name="submit" type="button" label="submit.button.label"
value="login"/>
</Gui>
</Response>
<propertyRef name="RadiusInit"/>
<property name="request.type" value="Access-Request"/>
<property name="request.attributes" value="User-Name=${request:loginId}, State=${sess:radius.State}, User-Password=${inargs:otp}"/>
<property name="authenticateOn" value="Access-Accept"/>
</AuthState>
SecuridAuthenticateState
The SecureidAuthenticateState uses JRadius clients for backend access. JRadius is an open source library under the LGPL license. Find more details here:
This AuthState authenticates users with RSA SecurID tokens. It connects to RSA's ACE/Server and requests validation of the authentication data provided by the user. For this AuthState to work, the following requirements must be met:
- A RADIUS server must be available (e.g., the RADIUS extension to the RSA SecurID server or a SafeWord server).
- The host on which nevisAuth runs must be registered as an authorized client.
For the description below, the following wording is used:
- tokencode (1st factor): One-time password (OTP), the number displayed on the OTP device.
- PIN (2nd factor): Password or number, selected by the user or administrator along with the SecurID token. On some devices, the PIN can be entered on the device and is not sent to the server (nevisAuth, RADIUS backend).
- passcode: PIN and tokencode or secret_device_function (PIN, tokencode) if the PIN is entered on the device.
- password: SecurID would support an additional password mechanism (password managed on the SecurID server along with the user's account). This mechanism is not supported by this AuthState (usually unused mechanism).
Description
The following table and chapters describe the characteristics of the AuthState.
Topic | Description |
---|---|
Class | ch.nevis.esauth.auth.states.radius.SecuridAuthenticateState |
Logging | RADIUS |
Marker | SecurID:token |
Methods | authenticate, stepup, unlock |
Auditing
The following entries are generated (because instruction messages for the user are communicated via a transition and not by using errors):
- Next tokencode: in case the user's token clock needs to be synchronized
- Next passcode
- PINs do not match: in case of invalid password
- New PIN: if the user is in new pin mode
- Reenter PIN: if the back-end server needs a new pin confirmation
- PIN rejected: if the password was not accepted
- unknown transition: if the server returns a message that this AuthState could not understand
- Custom transition: if the server returns a message that matches a custom transition
Properties
host
(string, "localhost")A comma- or space-separated list of hostnames to be used as backend servers. Load balancing is not supported. Fail-safety to the next server in the list is done upon any (technical) failures. The last backend successfully used is remembered.
This AuthState uses the UDP protocol to send messages to backend server. It is thus susceptible to SOCKS proxies, as described in the chapter Configuring proxies.
authPort
(number, 1812)Port of the authentication server.
secret
(string, -)Shared secret required to communicate with the server. The secret must be generated on the ACE server using the administration tools of the ACE installation.
Use nevisCred (with the neviscred://... syntax) to protect the value in the configuration.
timeout
(number [sec], 60)Server communication time-out in seconds.
retryTime
(number [sec], 120)This period defines how long a failed back-end server is ignored before it is used again for failover.
retryCount
(number, 3)Specifies the number of retries before aborting. Retries are not done on the failed back-end server but on the next host in the list (round-robin failover). Retries are aborted if all servers in the list have been tried.
userIdMapper
(string, "${inargs.isiwebuserid}")This attribute allows to change the input argument sent by the user.
passwordMapper
(string, "${inargs.isiwebpasswd}${inargs.tokencode}")This attribute allows to specify the value used as passcode.
propagateResponse
(string, -)A list of response attribute names that should be propagated to the notes. If set to all, all RADIUS response attributes will be propagated. Disabled by default.
customTransitionMessagePattern_[0-n]
(string, -)A message template (a pattern) that is matched against the AccessChallenge reply-message delivered by the server. If it matches, the result will be set to
customTransition_[0-n]
. The pattern must be a Java regular expression.
Input
isiwebuserid
(user, required)The login-ID of the user, as defined on the back-end server. Note: The input argument can be renamed using the
useridMapper
property.isiwebpasswd
(user, optional)This argument may contain the (separated) password of the SecurID user. If omitted, only the
tokencode
is used as is (which may contain the password, pre-pended by the user).tokencode
(user, required)This argument contains the one-time password (OTP) the user entered. The password may be pre-pended or sent separately with the
isiwebpasswd
argument.
Transitions
ok
The user was authenticated successfully.
nextTokencode
,nextPasscode
The user's token clock needs to be synchronized with the server. The user must wait for the next token code.
newPin
The users account is in new PIN mode, i.e., the user has to choose a new password.
Reject
The user has entered an incorrect PIN/passcode. Therefore, the PIN/password is rejected.
reenterPin
Confirm the new password for verification.
nonmatchingPins
User entered a non-matching PIN and needs to start over.
rejectedPin
The password selected by the user was not accepted by the backend. The user should receive a message about the PIN policy.
unknownChallenge
Internal compatibility problem with the server. The server sends messages we cannot understand.
customTransition_[0-n]
selected if the server replies with an AccessChallenge reply-message matching
customTransitionMessagePattern_[0-n]
. If the reply-message matches thecustomTransitionMessagePattern
, this transition prevails over the others.
Output
none
Errors
lasterror=1
lasterrorinfo=invalid passcode (PIN or tokencode)
Modes are handled via the ${notes:transition}
variable and the current step is visualized via the GUI title and/or optional information texts.
Notes
replymsg
Contains the response message of the RADIUS server, usable for error message display.
loginid
Verified login-ID for use by post-processing states.
transition
Used to address different literal dictionary entries with a single AuthState instance (see example below).
Example
<AuthState name="SecurId"
class="ch.nevis.esauth.auth.states.radius.SecuridAuthenticateState">
<ResultCond name="ok" next="AuthDone"/>
<ResultCond name="newPin" next="SecurId"/>
<ResultCond name="reenterPin" next="SecurId"/>
<ResultCond name="nextTokencode" next="SecurId"/>
<ResultCond name="nextPasscode" next="SecurId"/>
<ResultCond name="reject" next="SecurId"/>
<ResultCond name="rejectedPin" next="SecurId"/>
<ResultCond name="nonmatchingPins" next="SecurId"/>
<ResultCond name="unknownChallenge" next="SecurId"/>
<ResultCond name="default" next="SecurId"/>
<Response value="AUTH_CONTINUE">
<Gui name="AuthUidPwDialog" label="login.radius.label">
<GuiElem name="lasterror" type="error" label="${notes:lasterrorinfo}"
value="${notes:lasterror}"/>
<GuiElem name="lastmsg" type="info" label="${notes:replymsg}"
value="${notes:replymsg}"/>
<GuiElem name="isiwebuserid" type="text" label="userid.label"
value="${request:loginId}"/>
<GuiElem name="isiwebpasswd" type="pw-text" label="login.radius.tokencode.label"/>
<GuiElem name="submit" type="button" label="login.button.label"
value="login"/>
</Gui>
<Gui name="pinChangeDialog" label="login.radius.label">
<GuiElem name="lasterror" type="error" label="${notes:lasterrorinfo}"
value="${notes:lasterror}"/>
<GuiElem name="lastmsg" type="info" label="login.radius.replymsg.${notes:transition}"
value="login.radius.replymsg.${notes:transition}"/>
<GuiElem name="isiwebuserid" type="hidden" label="userid.label"
value="${request:loginId}"/>
<GuiElem name="isiwebpasswd" type="pw-text" label="login.radius.tokencode.${notes:transition}"/>
<GuiElem name="submit" type="button" label="login.button.label"
value="login"/>
</Gui>
</Response>
<property name="host" value="radius.server.host.company.com"/>
<property name="authPort" value="1812"/>
<property name="acctPort" value="1813"/>
<property name="timeout" value="60"/>
<property name="secret" value="neviscred://password-alias"/>
<property name="customTransitionMessagePattern_0" value="Test .*"/>
</AuthState>
This example also demonstrates the use of different GUI descriptors in a single AuthState instance. The implementation sets the dialog name pinChangeDialog if a new PIN is required and the user ID does not need to be entered any more (hidden input argument, verified in the server too). |