Authentication processing AuthStates and state flow
In nevisAuth, the authentication operations configured are modeled as a state flow. A new user session is associated with a starting state by the dispatching algorithm (see Initial request-dispatching. The session will then progress from one state to another, as defined by configured transitions (see AuthState results and transitions). In turn, each state is processed and returns one of a known list of possible results: identifiers that trigger either the flow to another state or remain in the same state.
State may also be configured to send a response to the user under specific circumstances. In some cases, the processing of the state will be skipped entirely and a response will be sent right away or a transition to another state will be made (see The final flag and Input processing). The following chapters explain the underlying mechanism in detail.
Initial request-dispatching
The client addresses the domain dispatcher by providing the authentication domain that should be used to validate authentication requests.
For this purpose, nevisProxy sends the Realm attribute value configured in the IdentityCreationFilter.
The dispatcher selects the matching authentication domain (or uses the default domain if none can be found) and selects the AuthState to invoke as follows. The dispatcher
- Checks the authentication session for the next AuthState to process. It is stored when stateful dispatching is used (see Authentication processing) and a previous authentication request processing triggered a transition to this other AuthState.
- Selects the AuthState based on the current authentication method (
authenticate
,stepup
,logout
, ...) and the most specific URL selector (selector="/resource"
). By default, the URL selector checks the initial request resource (i.e., the URL that was requested during the authentication operation). This default behavior can be changed by specifying the attribute resource or by changing the default expression via JAVA_OPTS:-Dch.nevis.esauth.dispatch.resource=\${request:currentResource}
- Selects the AuthState, based on the current authentication method and an input argument, provided by the login-renderer or user (
selector="${inargs:takeAlternateLoginPath}"
). - Selects the AuthState, based on the current authentication method.
The following list shows the configuration attributes for the Domain
element:
Domain
required multiple are configurablename
(String, required, -)The name used to address this domain.
default
(Boolean, optional)Default value:
true
If set to true, incoming requests with no matching domain will be dispatched by this domain.
infoPay attention to the following:
- Only one domain may be configured as default domain.
- If no domain is configured as default domain, then the first domain configured will act as default domain.
inactiveInterval
(Integer, optional, 3601)Default value:
3601
Inactivity interval hint (in seconds) to send to nevisProxy. If this interval elapses without user interaction, the authentication will be revoked.
reauthInterval
(Integer, optional, 1801)Default value:
1801
Re-authentication interval hint (in seconds) to send to nevisProxy. If this interval elapses without user interaction, the authentication will be locked and the next user request will trigger an unlocking procedure.
statelessAuth
(Boolean, optional, false)Default value:
false
If set to
true
, all user sessions will be dropped after each response. This behavior may be used for one-pass, non-interactive authentications where no follow-up processes are needed and explicit logouts are not expected. This is typically used in combination with the WS-Trust authentication facades.infoUsing this attribute in conventional domains may result in miscommunication between nevisAuth and nevisProxy. The issue is that there are certain properties of the SecToken which are expected by nevisProxy, but not necessarily populated by nevisAuth in a statelessAuth domain. Such an example is the property domain in the SecToken. To get around this - in domains where statelessAuth is set to true -, it is recommended to create a TokenAssembler for the domain and hardcode the domain value there, to make sure it is included in the SecToken.
Example configuration<TokenAssembler name="StatelessToken">
<Selector default="false" domain="StatelessRealm" />
<TokenSpec ttl="28800">
<field src="const" key="StatelessRealm" as="domain"/>
...
</TokenSpec>
<Signer key="Signer_StatelessToken"/>
</TokenAssembler>issueToken
(Boolean, optional, true)Default value:
true
When disabled, nevisAuth will not generate a SecToken when an authentication operation has been completed successfully. Use this option to improve performance in cases where the client does not need a SecToken. Setting
issueToken
tofalse
probably only makes sense ifstatelessAuth
is enabled.resetAuthenticationCondition
(String, -)Default value: not set
Condition for resetting all authentication-relevant values of the session and restarting of the state dispatching. See the section about Authentication conversations.
selector
(String, -)Configures the selector that should be used to decide which domain to use. Usually specifies a URL path, e.g., /nevis/login, but could also be an expression, e.g.,
${inargs:SAMLResponse}
. When the URL path is used, the path is checked against a resource expression The default resource expression is${request:resource}
. It can be changed globally with the system propertych.nevis.esauth.dispatch.resource
or locally by specifying the attribute resource, e.g.,resource="${request:currentResource}"
.resource
(String, -)Locally defines the resource expression used for path dispatching. The default is
${request:resource}
if not specified otherwise with the system propertych.nevis.esauth.dispatch.resource
.
The final flag
The final attribute of an AuthState can be activated to ensure that the defined GUI is always displayed first when transitioning into the AuthState. In this case, inputValidation and processing of the state are skipped entirely.
The final flag has no impact on the initial AuthState of a domain dispatching. An initial AuthState will always pass through inputValidation and, if successful, will always be processed, even if final="true"
is configured.
The purpose of presenting the defined GUI is to request interaction from the user, e.g., awaiting user data sent through an HTML form. When the engine receives the subsequent request, it continues its execution at the state that displayed the GUI, or, if resumeState
is set to false
, at a previous state. If this state has its resumeState
flag set to false
, subsequent requests will continue at a previous state stored in the session. The flag resumeState
is set to true
by default.
Input processing
The input processing of nevisAuth provides a basic integrity check and validation for user requests. This enables an early detection of input errors and can help to prevent the submission of malicious data through form parameters. The input processing itself involves the following stages:
Input parameter check
When a request is received, the input validation reads the name of the incoming form and compares it to the configured GUI element in the esauth4.xml. In this stage, nevisAuth ensures that all mandatory fields are present.
Transition handling
If a dispatching type is found, e.g., a checkbox, radio button, submit or reset button, the transition is set to the GUI element name or to
${GUI element name}-${received value}
, but only if the value is equal to the value of the checkbox that was sent in the last response. This prevents false transitions through input value manipulation. For details about the dispatching, see the section Defining transitions through buttons and checkboxes.Input validation
Next, the content of the input is validated. Three attributes can be configured in the GUI element to allow input validation:
length
,format
andvalidation
.
Input validation
The input validation of nevisAuth for GuiElements
consists of three parts, which can be configured with the length
, format
, and validation
attribute. See also the following table.
length
(Integer, optional, 255)Example:
100
The maximum length of an input value; the default maximum length is 255 characters.
format
(String, optional, -)Example:
E-mail:^[a-zA-Z.0-9+_%-.]@[a-zA-Z0-9+_%-.]+\.[a-zA-Z0-9_%-.]+$
A regex that must be matched before the input value gets processed.
validation
(String, optional, -)return parseInt(this.value) > 0
this.value != this.defaultValue
this.value == this.form.elements['email'].valueA JavaScript expression that validates the user input on client and server side.
The JavaScript evaluation has to return a boolean indicating whether the validation was successful or not. Expressions without an explicit return statement (i.e., this.value != this.defaultValue) get automatically wrapped into a JavaScript function:
var res = function() {
return this.value != this.defaultValue;
}.call(doc.forms.theGui.email);Optionally, further JavaScript libraries can be made available through the following JAVA_OPTS parameter:
-Dch.nevis.esauth.JavaScript.libs
In case of a validation error, nevisAuth behaves as follows:
- Stores the validation error in the notes scope *input.
<input-name>.invalid
For example:notes:input.isiwebuserid.invalid = true
- Sets the transition to
<input-name>-validation-failed
. For example:isiwebuserid-validation-failed
. If such a transition is not configured, nevisAuth continues with the next step. - Sets the transition to
validation-failed
. If such a transition is not configured, nevisAuth continues with the next step. - Generates and displays the GUI with appropriate warn messages in the browser. The attribute
validationMessage
enables an individual configuration of this message.
- Stores the validation error in the notes scope *input.
AuthState results and transitions
Having passed inputValidation, the AuthState itself is executed. The engine will call the process method. If it is not overloaded by an implementation in the AuthState class, then the base AuthState class will call the method.
The process method of the base AuthState class will dispatch calls to the methods authenticate, logout, stepup, stepdown and unlock, depending on what the entry method of the request was. Those methods can be overloaded by the specific AuthState. If the AuthState itself does not contain an implementation for the method, the base AuthState class will throw an exception indicating that the method is not implemented, or it will delegate to another method (e.g., unlock delegates to authenticate).
<AuthState name="MyLogin" class=".." final="false">
<ResultCond name="ok" next="AuthDone" authLevel="auth.weak"/>
<Response value="AUTH_ERROR">
<Gui name="MyDialog" label="MyDialog.title">
<GuiElem name="error" type="text" label="${notes:lasterrorinfo}"
value="${notes:lasterror}"/>
<GuiElem name="loginid" type="text" label="MyDialog.loginid.label"/>
<GuiElem name="password" type="text" label="MyDialog.password.label"/>
</Gui>
<Arg name="my.outarg" value="${inargs:loginid}"/>
</Response>
<property name="myprop" value="${sess:a.value}"/>
</AuthState>
The order of the AuthStates parameters in the XML configuration has no influence on the parsing order and the value evaluation. It is not guaranteed that the system parses the configuration parameters of AuthStates in the order they are represented in the XML configuration.
After processing an authentication request in an AuthState, the result (set by the AuthState implementation) is used to make a transition to the next AuthState to process (if non-final) or generate (the GUI, if final). These transitions are configured as with the ResultCond
element, and additional qualifiers may be specified.
Example: If an AuthState sets the result ok
(signaling successful processing of the authentication request), transitions can be configured as follows:
ok
Unconditional transition for the specified result.
ok:/resource
Conditional transition, if the request is processed in the context of the specified resource (e.g., the URL the user accesses).
ok:SSO1
Conditional transition, if the request is processed in the context of the specified domain (authentication realm). This is helpful to reduce redundancy if multiple authentication domains are implemented in a single nevisAuth instance. Understanding a configuration like this is more challenging.
ok:${sess:user.email}
Conditional transition, if the request can evaluate the expression to a string that is non-empty and not equal to
"false"
.authenticate:ok
Conditional transition, if the authentication method is authenticate.
SOAP:ok
Conditional transition, if an AuthState is used by users (via a browser) and technical clients (e.g., a web-service client) at the same time and, e.g., the technical client is not able to perform additional authentication steps or the error handling is solved differently. The SOAP condition triggers when a client sends the HTTP
SOAPAction
header.
The list shows the attributes of the AuthState
element and its subelements.
AuthState
optional element, multiple are configurableName to use for addressing in the
Domain
andResultCond
elements.class
requiredClass extending AuthState that handles processing (and optionally inputValidation and session finishing) for this AuthState. AuthStates are described in Authentication Plug-ins (AuthStates).
authLevel
(String, optional, -)If the AuthState is processed, this authentication level is set before doing the transition to the next AuthState (only if the level was not set by the implementation already).
cautionSetting the
authLevel
in this manner (on an AuthState) is discouraged. It is difficult for the AuthEngine to guess if the result of an AuthState represents success or failure and whether the configuredauthLevel
should be set or not. In some cases, using this syntax can result in users receiving wrongauthLevel
.final
(Boolean, optional, true)Default value: true
See the sections The final flag and Authentication conversations.
classPath
(String, optional, -)Colon-separated list of paths that forms the ClassPath in which the AuthState is loaded and executed. If left undefined, the ClassPath of the AuthEngine is used. See also Classpath configuration.
classLoadStrategy
(String, optional, -)Default value:
PARENT_FIRST
One of
PARENT_FIRST
,PARENT_LAST
ClassLoading strategy for the ClassLoader specific to the AuthState. This specifies whether the parent ClassLoader (the ClassLoader of the AuthEngine) is to be consulted before or after the AuthState ClassLoader. See also Classpath configuration.
Transition limit
To prevent infinite loops due to misconfiguration, the AuthEngine limits the number of transitions that can be made when executing an AuthState method (authenticate, logout, stepup, stepdown or unlock). The limit is set at 100 transitions (including self-targeted transitions). When this limit is reached, the AuthEngine halts the execution.
The transition counter is reset for every call to nevisAuth (on every HTTP request). So if an authentication flow requires multiple subsequent calls to nevisAuth, the transition limit is scoped to every individual call and not to the sum of all of them.
Defining transitions through buttons and checkboxes
It is possible to define transitions through submit, reset and radio buttons or checkboxes. During the input validation, nevisAuth checks whether the transitions ${gui_element_name}-${value}
(only for radio buttons and checkboxes) or ${gui_element_name}
exist. Suppose you configured a GuiElement
<GuiElem name="submit" type="submit" label="submit.button.label" value="Continue"/>
then your AuthState may contain a ResultCond
element:
<ResultCond name="submit" next="IdmGetPropertiesState"/>
If a user clicks on Continue, the submit transition will be triggered.
For radio buttons and checkboxes, transition handling is similar. If the following GuiElements
are configured:
<GuiElem name="loginMethod" type="radio" label="Login with Password" value="PW"/>
<GuiElem name="loginMethod" type="radio" label="Login with Certificate" value="CERT"/>
Then the AuthState may contain the following Result elements:
<ResultCond name="loginMethod-PW" next="LoginPassword"/>
<ResultCond name="loginMethod-CERT" next="LoginX509Certificate"/>
Depending on whether the user checked the first or the second radio button, the first or second transition will be triggered. Checkboxes work similar to radio buttons. However, if multiple checkboxes were selected and multiple checkboxes contain transitions to other AuthStates, only the transition configured for the first checkbox will be triggered.
Response generation
The following table lists the attributes of the Response
element and its subelements.
Response
required, exactly onevalue
(String, required)The value specifies what authentication status is valid after generating the response. It signals to the client, if the authentication continues or is finished:
AUTH_CONTINUE
Ask further input from the client and continue processing authentication requests.
AUTH_ERROR
Terminate authentication operation with a failure and signal startover to the client (nevisProxy clears the authentication state when receiving this. The authentication resets).
AUTH_DONE
Authentication operation is finished successfully. The client should establish an authenticated context.
Gui
optional, multiple are configurablename
(String, required, -)An AuthState may just set a GUI name to be used for input. The content of the GUI is configured. The name can be tagged to support the selection of different GUI descriptors for different context. These tags are:
<method:>GuiName
Authentication method selector (one of authenticate, unlock, stepup, ...)SOAP:GuiName
The client is a web service client.CERT:GuiName
The client has used an X509 certificate for authentication.GuiName:/resource
The client was intercepted on the URL/resource. Note that /resource and /resource/ are treated as different resources.GuiName:<domain>
The authentication is performed in the specified authentication domain.
label
(String, optional, -)Can be used by the login renderer to render a title. See Language support for further details.
GuiElem
optional, multiple are configurablename
(String, required, -)The name of the input field which the AuthState expects for further processing.
type
(String, required, -)The type of the GUI element which the login renderer should display to the user:
error
,info
: Information or error text to be displayed to the user. No input required.text
: Normal input field$pw-text
: Input field with obfuscationhidden
: Hidden context to be sent back by the clientcheckbox
,radio
,select
: Selection input fieldsbutton
,submit
,reset
: Command buttonsimage
: Image link where value denotes the image location
label
(String, optional, -)Can be used by the login renderer to render a title. See Language support for further details.
The label attribute supports Java EL expressions.
value
(String, optional, -)Default value for the GUI element. This value can contain a constant or an expression. See Configuration expressions.
checked
(Boolean, optional, false)Default value:
false
Default state for selection elements (radio and checkbox).
optional
(Boolean, optional, false)Default value:
false
Specifies if an input value is optional or required.
length
(Integer, optional, 255)Default value:
255
Maximum length of the user input, checked during input validation.
format
(String, optional, -)RegularExpression that is used to validate the input for this
GuiElem
.escapeXSS
(Boolean, optional, false)Default value:
false
Set to
true
to apply basic XML/HTML-escaping to the value of theGuiElem
. This is a protection against XSS attacks targeting login form fields.validation
(String, optional, -)A JavaScript expression that is used on both the server-side and, optionally, the client-side to validate the value of the
GuiElem
.validationMessage
(String, optional, -)A message or label to display if the input validation has failed.
renderElement
(String, optional, true)Default value:
true
Defines whether the
GuiElem
will be rendered as HTML element. This controls whether the HTML element will be shown at all. If the value evaluates tofalse
the element will not be sent to nevisLogRend. The attribute supports Java EL expressions.Note that if the value evaluates to any other value than
false
, the element will be rendered.Examples<GuiElem name="render" type="text" label="render me" value="1" renderElement="true"/>
<GuiElem name="donotrender" type="text" label="don't render me" value="2" renderElement="false"/>
<GuiElem name="renderbasedoncomparision" type="text" label="render me based on inargs values" value="3" renderElement="#{inargs.get('value1') == inargs.get('value2')}"/>
<GuiElem name="renderbasedoninargs" type="text" label="render me if inargs not empty" value="4" renderElement="#{not empty inargs.get('value1')}"/>
GuiGroup
optional, multiple are configurableDefines a gui group. As it shares common attributes with
GuiElem
, refer toGuiElem
for additional details.name
(String, required, -)type
(String, required, "select")label
(String, optional, -)format
(String, optional, -)renderElement
(String, optional, true)validation
(String, optional, -)validationMessage
(String, optional, -)multiple
(Boolean, optional, false)Defines if multiple option elements can be selected, this will lead to either Radio buttons or checkboxes being rendered.
Arg
optional, multiple are configurablename
(String, required, -)Output argument name to be sent to the client. Usually, output is only meaningful on
AUTH_DONE
. The corresponding output can be used by nevisProxy to propagate authentication data to the application back end (see DelegationFilter).value
(String, required, -)The value for this argument. The content is a string that may contain variables. See Configuration expressions