Categories:
Aura authentication flow
Description of the authentication flow for Aura users
The authentication validation process
Before starting a conversation with aura-bot, the channel needs to set a valid auraId and a fresh DirectLine token, if accessing via Direct Line, that should be sent as authorization header of bearer type in the request to the bot.
Find further information about Direct Line request in MS DirectLine API description.
Authentication validation in aura-bot consists of two phases:
-
Validate that the Direct Line token is a valid one, generated by the bot instance running behind aura-bot.
-
Validate the Aura credentials of the user, currently only based on Kernel authentication. If request authentication fails, the message is no longer processed, and an unauthenticated error response is returned to the channel.
An Aura channel should send its auraId in the from.id field of the request to the bot. Once the Direct Line token has been validated, aura-bot reads the from.id field to validate it:
-
Firstly, aura-bot checks if the
auraIdexists in theAuraUsersdatabase and, if exists, then goes on with the authentication in Kernel.-
If the channel allows anonymous users: In the happening that the received
auraIddoes not exist in theAuraUsersdatabase, then the user is marked as anonymous and the Kernel authentication validation is not launched. -
If the channel does not allow anonymous users, then an
UNAUTHENTICATEDerror is sent to the channel, informing that the Kernel authentication process must be relaunched before going on.
-
-
Kernel authentication validation:
-
A new fresh Kernel accessToken is requested for the
userIdandauthorizationIdrelated to theauraId. -
If the
authorizationIdis invalid or no longer exists in Kernel, then anUNAUTHENTICATEDerror is sent to the channel, informing that the Kernel authentication process must be relaunched before going on. -
Then a fresh Kernel introspect token is requested, so deeper information about the user identities and permissions for aura-bot is obtained.
-
Finally, the Kernel UserProfile info is obtained and processed to obtain further information about the user’s contract, for instance, its subscription type.
-
After that, all this information is stored in a cache during the time when Kernel accessToken is valid. During this period, the authentication validation process is avoided.
-
Besides, all this information is set in the
AuraUsermodel and stored in the conversation context of the bot to be available during the rest of the conversation messages processing.
-
The authentication process is managed by the fourth-platform-authorization-middleware.
Users data storage
Authenticated users
Users database
When a user authenticates with the basic authentication mechanism of a channel, the user’s information is created/updated in MongoDB and aura-bot accesses it through the aura-authentication-api API Aura Services API published in Kernel.
For instance, in WhatsApp, when the user authenticates with SMS-OTP, her information is stored in AuraUsers database.
Local cache
It is the node cache that each pod has with information from the users.
The information is saved on each request and expires in 5 minutes, configurable via AURA_USER_LOCAL_CACHE_TTL environment variable.
Remote cache
Mongo cache with aura-bot users’ information. It is shared by all pods.
The information is saved on each request and expires in 1 hour, configurable via AURA_MONGODB_BOT_COLLECTION_CACHES_INDEX_TTL environment variable.
Anonymous users
Local cache
Node cache to store anonymous users’ information, who are accessing each pod.
The information expires in 5 minutes, configurable via AURA_USER_LOCAL_CACHE_TTL environment variable.
Both types of users
BotFramework conversational cache
This is the conversational cache of BotFramework, which is called internally in aura-bot persistentData.
It is a MongoDB cache with three parts: ConversationData, UserData and AuthData. Therefore, as this section is related to users’ information, it is stored in the last two sections.
Find more information about cache module.
How does the authenticated user’s cache expire?
The expiration of the cache depends on different factors:
- The TTL of each cache element.
- Kernel accessToken is no longer valid.
- If the
accountRemovalTimestampof the conversational cache is greater than the timestamp of the cache
Authentication process flowchart
The following flowchart shows the authentication process:

Authentication steps
getUserData()
This function gets the user’s data from AuraUsers database, accessing through the Aura Services API published in Kernel.
If the endpoint returns a 404 error, null is returned by the function because in this case the user is anonymous, but it depends on the channel configuration to mark it as an error, if the channel does not support anonymous users ( for example, novum-mytelco channel), or as a valid anonymous users, for channels that allowed them (such as WhatsApp or Aura Webclient).
If other error is returned, the function throws an error and the authentication flow ends.
In the normal flow, the endpoint returns a user and the function returns a AuraUserModel object:
{
"userAuraId":"c2aa81f0-abd9-444f-b7cb-47c179f10556",
"userAuraIdGlobal":"d065dba31c79090a9e3c5afa94558d0c39ffa90c8e136931a5a12069418efad5",
"userChannel":{
"id":"45494a5b-835a-4fff-a813-b3d2be529dbe",
"dialogs":[
],
"outputMessageFormat":null,
"allowAnonymous":null,
"name":null,
"shortName":null,
"fpaAuthIntegrated":null
},
"authorizationId":"",
"userPhoneNumber":"+34600000003",
"userClientId":"up24456789",
"timestamp":1575366984,
"userPhoneType":null,
"userSubscriptionType":null,
"userAccessToken":null,
"introspectScopes":null,
"userProfile":null,
"userType":null,
"userAccountNumber":null
}
getChannelConfiguration()
This method returns an ChannelConfiguration object. This function tries to obtain the channel configuration by the
channelId or channelName passed as parameters.
{
"dialogLibraries": [
{
"name": "common",
"dialogs": [
{
"id": "greetings",
"allowAnonymous": true,
"triggerConditions": [
{
"intent": "intent.common.greetings"
}
]
}
]
}
],
"id": "45494a5b-835a-4fff-a813-b3d2be529dbe",
"name": "novum-mytelco",
"nlp": {
"enabled": true,
"enabled": true
}
},
"prefix": "nov",
"requestOptions": {
"requestOptionsVersion": {
"1": {
"channel": "directline"
}
}
},
"responseOptions": {
"dialogContext": {
"cardActions": {
"generate": "always",
"generateList": true
},
"defaultListType": "ordinalCardinal",
"disabled": false,
"normalizeTerms": true,
"processFromClient": true,
"promptChoice": {
"generate": "always",
"generateList": true
},
"returnToClient": false
}
},
"security": {
"authPurposes": "customer-self-service identify-customer aura-technical-problems-purpose",
"channelId": "novum-mytelco"
}
}
getInitialUserType()
This method returns an initial approach of the userType, because at this point some user types cannot be inferred.
Depending on the channel configuration and the user returned by getUserData(), there are four possible scenarios:
getUserData()returns a valid user- The user has
userTypeUser.userTypeis returned
- The user does not have
userTypeUndefinedis returned
- The user has
getUserData()returnsnull- The channel allows anonymous
Anonymousis returned
- The channel does not allow anonymous
Unauthenticatedis returned
- The channel allows anonymous
At this point, we can have three different flows:
- If the user is
anonymous, it is returned with the minimal data available. - If the user is
unauthenticatedand the channel have integrated auth,getIntegratedAuthIntent()is called but if the channel does not have integrated auth, an error is returned and the authentication ends. - If the user is
undefinedor other type, it starts the flow to obtain the data from Kernel.
getIntegratedAuthIntent() (Only unauthenticated users)
This method returns the intent to redirect to the integrated authentication.
This intent is returned in user.redirectIntent provided by the authentication function.
getUserAccessToken()
This method constructs the options object with scopes, purposes, authorizationId, deviceId, security.channelId and userId. Afterwards, it makes the request and obtain the token.
If an error occurs, the function will throw an error and the authentication ends with error.
security.channelId is added when requesting the jwt-bearer.
getUserProfile()
This method returns the user profile from Kernel. If there is any error, it will be thrown and the authentication will end with error.
{
"id": "up24456789",
"name": "ESP - Usuario de Prueba 2 - prepago",
"id_document": {
"country": "ESP",
"type": "NIF",
"value": "712724440A"
},
"identities": [
{
"type": "phone_number",
"id": "+34600000003",
"services": ["mobile_prepaid"],
"roles": ["owner", "admin"]
}
]
}
getAnonymousUserProfile()
This method returns the user profile from Kernel, for anonymous users. If there is any error, it will be thrown and the authentication will end with error.
[
{
"identities": [
{
"roles": [
"owner"
],
"id": "12SIME16",
"services": [
"authentication"
],
"type": "uid"
},
{
"roles": [
"owner",
"basic",
"admin"
],
"id": "+34680395460",
"services": [
"mobile_postpaid"
],
"type": "phone_number"
},
{
"roles": [
"owner",
"basic",
"admin"
],
"id": "+34911725467",
"services": [
"landline",
"internet"
],
"type": "phone_number"
},
{
"id": "CD53D6C5285CB60DD8E50052C1DBFADDDA033613",
"type": "uid",
"roles": [
"owner"
],
"services": [
"authentication"
]
}
],
"id": "CD53D6C5285CB60DD8E50052C1DBFADDDA033613"
}
]
encodeAnonymousData()
This method sets the userId and auraIdGlobal for anonymous users. These values are needed to be stored in KPIs.
{
"userId": "76661cf96c2bda27c4fb016627f2d74af1c3cee496b76cf5d7bc2b2ad8a38cb2",
"auraIdGlobal": "8eeb101175bfe9c247e9d10669c0d1696e8034f8e1a12b25b54780e00de0e1c1!616e6f6e796d6f7573"
}
getAuraUserType()
This method returns the final userType and the userIdentity.
- First of all, identities are filtered and only the type
phone_numberwith services prepaid, postpaid, control, hybrid or internet are returned. - After that, we need to select the phone number of the user among the numbers filtered.
- If we have more than 1 number and
userDatado not haveuserPhoneNumber(the user has not been logged with phone number), theuserTypereturned ismultimsisdnanduserIdentityisundefined. - If there is only 1 phone number,
userTypeismonomsisdn. - If there are many phones but we also have
userPhoneNumberinuserData, this phone is searched in phones array and if found, the user is consideredmonomsisdnalthough it ismultimsisdn.
- If we have more than 1 number and
Monomsisdn users return userType (prepaid, postpaid or control) and userIdentity filled:
{
"type":"phone_number",
"id":"+34600000003",
"services":[
"mobile_prepaid"
],
"roles":[
"owner",
"admin"
],
"phone_type":"mobile",
"subscription_type":"prepaid",
"identifier":"+34600000003"
}
getIntrospect()
This method returns the scopes, purposes and boundScopes for this user from Kernel.
{
"scopes":[
"event-low-data-read",
"insights-data-usage-result-read",
"mobile-balance-transfer-write",
"auraid-read",
"webviews-phone-number-read",
...
],
"purposes":[
"sim-upgrade-suggestion",
"identify-customer",
"customer-self-service",
"aura-read-insight-events",
"device-recommendations",
"detect-abnormal-usage"
],
"identifierBoundScopes":[
]
}