TAN authentication plug-ins
This chapter describes the TAN authentication plug-in. Currently, the TAN authentication plug-in consists of one AuthState, the TANState AuthState.
TANState
The new HTTP client shipped with nevisAuth 4.38.0.12 will likely require changes in this auth state configuration, specifically in the area of certificate configuration and handling.
Visit the migration guide for additional information.
The TAN (transaction number) plug-in provides means to use OTP-authentication over a side-channel. It can be used to send a random character string to the user via the configurable channel.
A typical use case for the TANState AuthState is to make it more difficult for an identity thief to log in with a stolen user account. Additionally to the user's password, the attacker will also need to have access to the mobile phone (or, less commonly, the email account, if the SMTP channel is used to send the TAN via EMAIL).
There are several available channels through which the TAN can be sent. Those are, for example:
- the SMTP channel, which can be used to send the message either directly via email, or more commonly via a Mail-to-SMS gateway
- the HTTP channel which connects to an HTTP web interface or
- the SwissPhone channel, which uses the SwissPhone SMS gateway
Be aware that the transfer of the TAN to the SMS gateway might be in plain text, depending on the channel configuration.
TAN state flow and transitions
The following diagram shows the TAN state flow in a simplified manner. It's intended to help understanding which conditions lead to which transition being triggered at which point in a TAN process:
Description
The following table and chapters describe the characteristics of the AuthState.
Topic | Description |
---|---|
Class | ch.nevis.esauth.auth.states.tan.TANState |
Logging | TAN |
Auditing | none |
Marker | TAN:challenge/response |
Methods | process (all events) |
Properties
channel
(string, {SMTP, http, Swissphone, null} or a classname, default: SMTP)Channel over which the TAN is sent. The "null" channel does not send the message but instead propagates all relevant data for further processing in other AuthStates.
cautionBe aware that for the channel "http", hostname verification is enabled by default. The relevant property is
httpclient.tls.hostnameVerification
(boolean, true). When establishing an HTTPS connection, the client will check the hostname in the HTTPS server certificate against the actual server hostname by default. To disable hostname verification, set the propertyhttpclient.tls.hostnameVerification
to "false".recipient
(string, -)The recipient of the TAN. When using SMTP as a channel, this is the recipient's e-mail address. This mandatory property is subject to variable substitution (e.g., an attribute in a LDAP directory).
sender
(string, -)Mandatory property which is subject to variable substitution that represents the sender of the TAN message.
response
(string, ${inargs:mtanresponse})The source of the TAN response provided by the user.
messageTemplate
(string, "MTAN authentication code: ${sess:mtan.challenge}")The text body of the e-mail. Must contain the challenge (session key: mtan.challenge).
Example<property name="messageTemplate" value="#{String.format(litdict.getString('some.litdict.key'), sess['mtan.challenge'])}"/>
messageTemplateFile
(string, -)File path to a template for the text body of a TAN e-mail message. Must contain the challenge if used.
This property is useful for more elaborate TAN messages such as styled HTML e-mail messages.
This property overrides the
messageTemplate
property: ifmessageTemplateFile
is set, the value ofmessageTemplate
is disregarded.tanTemplate
(string, 6{ABCDEFGHIJKLMNOPQRSTUVWXYZ})Syntax of the TAN to be generated. A TAN is a character string with one or several embedded randomized sequences. Each randomized sequence in turn is made up of one or several blocks of possible characters. A single block has the following syntax: d{C} – where d represents the number of characters and C is the list of characters which may be used. If two or more blocks are placed directly after each other (without separators), the resulting sequence will be a random permutation over those blocks. Special characters must be escaped with XML-entities.
Examples:
"3{ABCDE}2{1234}-2{UVWXY}-SEPARATOR+1{123456789}" can generate: "1CD4E-WV-SEPARATOR+6"
"4{ABCDE}2{1234}1{.-_:}-3{abcdef}" can generate: "C22.EBA-ada"generateNewTAN
(String, "false")An expression that is evaluated by the AuthState on each request and triggers the generation of a new TAN if it results to a non-empty string other than "false". Use this property in combination with a button for explicit regeneration of TAN challenges by the user.
maxRetry
(number, 1)Maximum number of tries per TAN. Unlike the name suggests, this is not counted in addition to the first attempt. Further, the counter gets reset on each regeneration. To allow only one attempt per generated TAN, the property should be set to 1.
infoSending the same incorrect input after each other only counts as one retry. The retries are not counted if a transition is configured on the result
inputFalse
. In this case, an external mechanism must be used to track the number of retries.|maxRegenerate
(number, 1)Maximum number of regenerations of a new TAN. This is counted in addition to the initial generation of the TAN challenge.
autoRegenerate
(boolean, true)Automatically regenerate a new TAN if the maximum number of retries is exhausted.
maxAge
(duration in seconds, 300)Maximum age of accepted TAN response.
ignoreCase
(boolean, false)If set to true, the differences of character case between challenge and response are ignored.
ignoreCharacterRegex
(regex, -)This regular expression may be used to remove inconsequential characters from both challenge and response, so that for example white spaces or dashes used to format the challenge do not have to appear in the response.
customerField
(string, -)This string can only be used with the SwissPhone channel and is optional. According to the IMASYS specififcation its maximum length is 254 chars with the "iso-8859-1" charset.
SMPT Channel
mail.*
(string, -)Properties starting with the prefix mail. are propagated to the SMTP Client.
In case the
mail.transport.protocol
is not provided nevisAuth usesmtps
as default.SOCKS ProxiesThe SMTP channel supports SOCKS proxies as described in chapter Configuring proxies.
smtpUser
(string, -)Username for simple SMTP authentication. If not set, no authentication will be attempted.
smtpPass
(string, -)Password for simple SMTP authentication.
smtpSubject
(string, MTAN authentication)The subject line of the e-mail.
messageContentType
(string, "text/plain;charset=UTF-8")The content type of the e-mail message. This property is useful for sending more elaborate TAN messages, such as styled HTML e-mail messages.
HTTP Channel
httpUrl
(url, -)The target URL for the request. This property is required. It overrides the HTTP target URLs that are configured for the AuthHttpClient.
httpMethod
(string, GET¦POST)The HTTP method to use. Supported: GET and POST.
httpHeader.<name>
(string, -)HTTPHeaders sent in the request.
httpParam.<name>
(string, -)Query or form parameters added to the request, depending on the httpMethod.
httpContent
,httpContentType
,httpContentCharset
(string, -)Send content in a POST request. This is not compatible with the
httpParam.<name>
property.httpSuccessStatus
(string, -)If the response status is in the range, sending the message was successful. Defaults to 200-299 for POST and 200-399 for GET requests.
Swissphone Channel
username
(string, -)The username that belongs to the Swissphone contract.
password
(string, -)The password that belongs to the username related to the Swissphone contract.
portalListServerAddress
(string, -)The server address that is the entry point of the Swissphone service. Its purpose is to provide meta-information about the specific services.
infoProvide only the address, without specific path or scheme. Example: imasys5.swissphone-gateway.com
portalListPort
(number, 443)The TCP port of the server that is the entry point of the Swissphone service.
HTTP client properties
The following properties configuring the HttpClient can be used to customize the HTTP
and the Swissphone
channels.
httpclient.*
(String)Configure the outgoing HTTP communication towards the Tan channel. For a list of valid HTTP properties, see HTTP Client.
Input
response
The response from the client (e.g., the MTAN challenge received through a side channel) as defined in the property response.
Transitions
ok
User passed TAN authentication successfully. That is, user input matched the sent challenge.
failed
User did not pass TAN authentication. That is, none of the user inputs matched the sent challenge(s) and the limit of retries/regenerations is reached.
sendFailed
Technical error (e.g., SMS gateway down)
For more complex configurations:
inputFalse
Use this transition to implement an individual handling for user inputs that do not match the challenge. If this transition is configured, the retries/regeneration handling of the TANState is disabled.
challengeSent
TAN challenge was successfully sent. Use this transition to trigger additional processing.
Output
none
Errors
lasterror=1
lasterrorinfo=lastTAN response verification failed
lasterror=1
lasterrorinfo=TAN response outdated
lasterror=1
lasterrorinfo=TAN response regenerations exhausted
Notes
tan.message
This note is set to
tan.sent
if a new TAN has been sent using the configured channel. This may be used to display information text to the user.
Examples
Simple Example
<AuthState name="Tan" class="ch.nevis.esauth.auth.states.tan.TANState" >
<ResultCond name="ok" next="AuthDone" authLevel="auth.strong"/>
<ResultCond name="failed" next="AuthError"/>
<ResultCond name="sendFailed" next="AuthError"/>
<Response value="AUTH_CONTINUE">
<Gui name="MTANDialog" label="Mobile Token">
<GuiElem name="lasterror" type="error"
label="${notes:lasterrorinfo}" value="${notes:lasterror}"/>
<GuiElem name="info" type="info"
label="${notes:tan.message}" value="${notes:tan.message}" />
<GuiElem name="tanresponse" type="text" label="Response"/>
<GuiElem name="submit" type="button" label="Submit" value="Login"/>
<GuiElem name="generate" type="button" label="tan.generate" value="true"/>
</Gui>
</Response>
<property name="response" value="${inargs:tanresponse}"/>
<property name="sender" value="noreply"/>
<property name="recipient" value="${sess:ch.nevis.idm.User.email} "/>
<property name="mail.smtp.host" value="smtp.company.com"/>
<property name="mail.smtp.port" value="25"/>
<property name="messageTemplate" value="${sess:mtan.challenge}"/>
<property name="generateNewTAN" value="${inargs:generate}"/>
<property name="maxRetry" value="1"/>
<property name="maxRegenerate" value="1"/>
<property name="tanTemplate" value="3{ABCDEFGHJKLMNPQRSTUVWXYZ}1{123456789}"/>
<property name="smtpSubject" value="tan.smtpSubject"/>
</AuthState>
Aspsms over HTTP Example
<AuthState class="ch.nevis.esauth.auth.states.tan.TANState" final="false" name="MTAN_ASP" resumeState="true">
<ResultCond name="ok" next="AuthDone"/>
<ResultCond name="failed" next="AuthError"/>
<ResultCond name="sendFailed" next="AuthError"/>
<ResultCond name="cancel" next="AuthDone"/>
<Response value="AUTH_CONTINUE">
<Gui name="MTANDialog" label="Mobile Token">
<GuiElem name="lasterror" type="error"
label="${notes:lasterrorinfo}" value="${notes:lasterror}"/>
<GuiElem name="info" type="info"
label="${notes:tan.message}" value="${notes:tan.message}" />
<GuiElem name="tanresponse" type="text" label="Response"/>
<GuiElem name="submit" type="button" label="Submit" value="Login"/>
<GuiElem name="generate" type="button" label="tan.generate" value="true"/>
</Gui>
</Response>
<property name="channel" value="http"/>
<property name="generateNewTAN" value="${inargs:generate}"/>
<property name="httpMethod" value="POST"/>
<property name="httpContent"
value="#{ELUtils.setQueryParam('','MessageText',notes.getProperty('tan.http.message','')).concat('&Password=@MTAN_ASP_PW@&UserKey=@MTAN_ASP_USER@&Originator=').concat(notes.getProperty('tan.http.sender','')).concat('&Recipient=').concat(notes.getProperty('tan.http.receivers','')).substring(1)}"/>
<property name="httpclient.proxy.host" value="proxy.mycompany.com"/>
<property name="httpclient.proxy.port" value="1234"/>
<property name="httpUrl" value="https://soap.aspsms.com/aspsmsx.asmx/SimpleTextSMS"/>
<property name="message-template" value="#{sess.get('mtan.challenge')}"/>
<property name="recipient" value="${sess:ch.nevis.idm.User.mobile}"/>
<property name="response" value="#{inargs.get('tanresponse').toString().replaceAll('\\s', '').replaceAll('.(?=.)', '$0 ')}"/>
<property name="sender" value="noreply"/>
</AuthState>