Conditional authentication - API reference¶
Asgardeo provides a set of defined functions and objects to write your conditional authentication script. They are grouped as follows:
-
Core functions: These are the basic functions used in the script. These are used to identify the user who initiated the login flow, execute a step in the login flow, handle login failures, etc. Listed below are the core functions that can be used in conditional authentication scripts.
-
Utility functions: These utility functions are used for specific scenarios. For example, checking whether the login user belongs to a specific user group. Listed below are the utility functions that can be used in conditional authentication scripts.
isMemberOfAnyOfGroups()
setCookie()
getCookieValue()
prompt()
getUserSessions()
terminateUserSession()
sendEmail()
callChoreo
getValueFromDecodedAssertion()
getUniqueUserWithClaimValues()
getAssociatedLocalUser()
getMaskedValue()
httpGet()
httpPost()
resolveMultiAttributeLoginIdentifier()
updateUserPassword()
-
Object references: You can use objects to capture user behaviors and set attributes. For example, you can use the user and request objects and write the login conditions accordingly. Listed below are the object references that can be used in conditional authentication scripts.
Core functions¶
These are the basic functions that are required for defining the application login flow using an authentication script.
Initial login request¶
onLoginRequest()
This function is called when Asgardeo receives the initial login request. It includes the parameters given below.
-
Parameters
context
The authentication context, which contains the context information about the request. -
Example
onLoginRequest = function(context)
Execute a step¶
executeStep()
This function is called to execute an authentication step in the login flow. You need to define your application's login flow before using this function.
This method accepts an object as a parameter and should include the details listed below.
<stepId> |
(Mandatory) The step number in the login flow. |
<options> |
(Optional) A map that can configure step execution. Authentication option filtering is supported. For more information, see the example on filtering connections in a step given below. |
<eventCallbacks> |
(optional) The object that contains the callback functions, which are to be called based on the result of the step execution. Supported results are onSuccess and onFail which can
have their own optional callbacks as anonymous functions. For these callbacks, the [context](#context) and [data](#data) parameters are passed.
|
The following sample template shows how the above categorization can be used in a script.
executeStep(<stepId>,
{
<options>:[
//The objects of the option
]
},
{
<eventCallback>: function()> {
//eventCallback can be `onSuccess` or `onFail`
//Define what should be done
}
});
Parameters¶
This section describes the options you can use to configure the executeStep()
function, and the values you can use as local authenticators and federated IdPs in the function.
-
Options
You can use these options when executing an authentication step through the script. See the examples given below for details.
authenticationOptions
List the authentication methods that will be prompted for this step. authenticationOptions.authenticator
The name of the local authenticator used. authenticationOptions.idp
The name of the federated identity provider used. authenticatorParams
Pass the configuration for the step authenticators or identity providers. authenticatorParams.common
Specify the common configurations for both local authenticators and federated identity providers. authenticatorParams.local.{authenticator-name}
The name of the local authenticator used in the application. The configurations passed here will be available for that specific authenticator. authenticatorParams.local.{federated-identity-provider}
The name of the federated identity provider used in the application. The configurations passed here will be available for that federated identity provider. -
Connections: Local authenticators and federated IdPs
When you want to access your configured connections in an authentication step, you can use the following values through the options explained above.
See the example on filtering connections in a step given below for details.
The local authenticators are represented by the
authenticator
parameter. The table shows the connection names (as displayed on the Asgardeo Console) and the corresponding authenticator name you can use in the scripts.Connection Name Authenticator Email OTP email-otp-authenticator Identifier First IdentifierExecutor Magic Link MagicLinkAuthenticator Security Key/Biometrics FIDOAuthenticator SMS OTP sms-otp-authenticator TOTP totp Username & Password BasicAuthenticator The external identity providers are represented by the
idp
parameter. The federated connection names are generated based on the name you assign to the connection at registration.Example
If you add a federated google connection with the name bifrost google, the value you can use in your authentication scripts is
bifrost_google
.
Examples¶
Shown below are ways to define a login flow using the core functions.
-
Example 1: Use
stepId
This example uses only the
stepId
.executeStep(1)
-
Example 2: Use
stepId
andeventCallbacks
This example uses only the
stepId
andeventCallbacks
.executeStep(1, { onSuccess: function(context) { //Do something on success } });
-
Example 3: Use all parameters
This example uses the
stepId
,options
, and an emptyeventCallbacks
object. Different properties can be defined by theoptions
object, such asauthenticationOptions
andauthenticatorParams
. However, you cannot write a script with only thestepId
andoptions
. See the following two examples:executeStep(1, { authenticationOptions:[{ authenticator: 'totp' }]}, {} );
executeStep(1, { authenticatorParams: { local: { email-otp-authenticator: { enableRetryFromAuthenticator: 'true' } } }, {} );
-
Example 4: Filter connections in a step
The
authenticationOptions
array filters out connections (local authenticators and federated identity providers) of a step based on a condition.This can be achieved by specifying an array named
authenticationOptions
to theoptions
map. You can haveidp
as an array item for federated connections andauthenticator
as an array item for local connections, as shown below.executeStep(1,{ authenticationOptions:[{authenticator:'BasicAuthenticator'},{idp:'google'}] },{ onSuccess: function (context) { // Do something on success };
Fail the login flow¶
fail()
This function redirects the user to the redirect URI provided in the authorization request when the login flow fails.
This function takes a map as an optional parameter. When a map is provided as the parameter, the redirect URL will be appended with the following properties (which should be contained in the map). Otherwise, the default parameters are passed. All the properties passed in the map are also optional.
-
Parameters
errorCode
The error code to be appended in the redirect URL. errorMessage
The error message to be appended in the redirect URL. errorURI
The URI of a web page that includes additional information about the error. -
Example
var parameterMap = {'errorCode': 'access_denied', 'errorMessage': 'login could not be completed', "errorURI":'http://www.example.com/error'}; if (!isAuthenticated) { fail(parameterMap); }
Redirect to error code¶
sendError()
This function redirects the user to an error page.
-
Parameters
url
The URL of the error page that the user is redirected to. If the value is null, the user is redirected by default to the retry.do error page.
Note that any relative URL is assumed to be relative to the host's root.parameters
Key value map passed as parameters. These are converted to query parameters in the URL. -
Example
It is recommended to use an i18n key to describe the error messages so that they can be internationalized easily on the error page.
var user = context.steps[1].subject; var isAdmin = hasRole(user, 'admin'); if (!isAdmin) { sendError('http://www.example.com/error',{'status':'000403','statusMsg':'You are not allowed to login to this app.', 'i18nkey':'not.allowed.error'}); }
Utility functions¶
The implementation of utility functions can be found in the WSO2 extensions code repository.
Check group membership¶
isMemberOfAnyOfGroups()
This function returns true
if the specified user belongs to at least one of the given groups, and returns false
if the user does not.
-
Parameters
user
A user object representing the user details. groups
A list of strings that contain the groups. Each string is a group name.
-
Example
var groups = ['admin', 'manager']; var user = context.steps[1].subject; var isMember = isMemberOfAnyOfGroups(user, groups); if (isMember) { executeStep(2); }
Set cookie¶
setCookie(response, name, value, properties)
This function sets a new cookie.
-
Parameters
response
The HTTP response. name
Name of the cookie. value
Value of the cookie. properties
A map that may contain optional attributes of the cookie with the two custom attributes given below.
sign
: The default value isfalse
. If it is set to true, the value will be signed.encrypt
: The default value isfalse
. If it is set to true, the value will be encrypted.
-
Example
The size of the value has to be less than the RSA key pair length if '
encrypt
' is enabled (set to true).setCookie(context.response, "name", "test", {"max-age" : 4000, "path" : "/", "domain" : "localhost", "httpOnly" : true, "secure" : true, 'sameSite': 'LAX', "version" : 1, "comment" : "some comments", "encrypt" : true, "sign" : true})
Get cookie value¶
getCookieValue(request, name, properties)
This function gets the plain-text cookie value for the cookie name if it is present.
-
Parameters
request
HTTP authentication request. name
Name of the cookie. properties
A map that may contain optional attributes of the cookie:
decrypt
: The default value isfalse
. If it is set totrue
, the value will be decrypted.validateSignature
: The default value isfalse
. If it is set totrue
, the signature will be validated before returning a response.
-
Example
getCookieValue(context.request,"name", {"decrypt" : true,"validateSignature" : true })
Prompt¶
prompt(templateId, data, eventHandlers)
This function prompts the user for different interactions.
-
Parameters
templateId
Identifier of the template that needs to be prompted. data
The data associated with the template to be sent in the prompt. eventHandlers
The callback event handlers. The following table contains the supported templates and the associated data.
Template Id Description Data genericForm Prompt for generic user input. username
: Username that will be used in a greetinginputs
: A list of input field objects in the form. For example:{id: “”, label: “”}
externalRedirect Redirect users to an external static page. redirectURL
: The external URL to redirect the user.
internalWait Keep a user waiting for a predefined fixed time or until a status is completed. waitingType
: Waiting method. Can be one ofFIXED_DELAY
orPOLLING
. Default waitingType isFIXED_DELAY
.waitingConfigs
: Waiting page configurations.greeting
: An optional greeting. Default text isJust a moment...
message
: An optional message. Default text isWe are setting things up for you.
.timeout
: Optional timeout period in seconds. Default timeout is 10 seconds and max timeout is 20 seconds.
If your pollingEndpoint
: REST endpoint to poll a status.pollingInterval
: Time internal in seconds to poll the polling endpoint. Default value is2
seconds.requestMethod
: Polling request method. Can be one ofGET
orPOST
. Default value isGET
.contentType
: Content type of the polling request. Default value isapplication/x-www-form-urlencoded
.requestData
: Data to be sent to the polling endpoint. Can specify a string or an object. If the HTTP method isGET
, the data will be appended to the URL.
waitingType
isPOLLING
, the following configs also apply:
-
Examples
var onLoginRequest = function(context) {
executeStep(1, {
onSuccess: function (context) {
var username = context.steps[1].subject.username;
prompt("genericForm", {"username":username, "inputs":[{"id":"fname","label":"First Name"},{"id":"lname","label":"Last Name"}]}, {
onSuccess : function(context) {
var fname = context.request.params.fname[0];
var lname = context.request.params.lname[0];
Log.info(fname);
Log.info(lname);
}
});
}
});
}
var onLoginRequest = function(context) {
executeStep(1, {
onSuccess: function (context) {
prompt("externalRedirect", {
"redirectURL": "{EXTERNAL_URL}"}, {
onSuccess : function(context) {
Log.info("Successfully redirected back from the external page");
},
onFail: function(context, data) {
Log.info("Error occurred during the prompt.");
}
});
}
});
}
var onLoginRequest = function(context) {
executeStep(1, {
onSuccess: function (context) {
prompt("internalWait", {
"waitingType": "POLLING",
"waitingConfigs": {
"pollingEndpoint": "<POLLING_ENDPOINT>",
"requestData": "contextId=1234",
"pollingInterval": "2",
"timeout": "10"
}
}, {
onSuccess: function (context) {
Log.info("Successfully redirected back from waiting page.");
},
onFail: function (context, data) {
Log.info("Error occurred during the prompt.");
}
});
}
});
}
Get user sessions¶
getUserSessions()
This function returns a session object (i.e., all the active user sessions of the specified user or an empty array if there are no sessions).
-
Parameters
user
This is a user object that represents the user details. -
Example
var user = context.currentKnownSubject; var sessions = getUserSessions(user); for (var key in sessions) { Log.info("Session ID: " + sessions[key].id); }
Terminate user session¶
terminateUserSession()
This function returns a session object (i.e., all the active user sessions of the specified user or an empty array if there are no sessions).
-
Parameters
user
This is a user object that represents the user details. sessionId
This is the sessionId
string of the session that needs to be terminated. -
Example
var user = context.currentKnownSubject; var sessions = getUserSessions(user); if (sessions.length > 0) { var result = terminateUserSession(user, sessions[0]); Log.info("Terminate Operation Successful?: " + result); }
Send email¶
sendEmail()
This function sends an email to the specified user.
-
Parameters
user
An object representing the user details. templateId
Identifier of the email template. The email template specifies the body of the email that is sent out. placeholderParameters
Used to replace any placeholders in the template. -
Example
var user = context.steps[1].subject; var firstName = user.localClaims['http://wso2.org/claims/givenname']; sendEmail(user, 'myTemplate', {'firstName':firstName});
Call a Choreo API¶
This function invokes an API hosted in Choreo.
Important
Note that to use the callChoreo
function, the API should,
- contain an endpoint that accepts
POST
requests. - return a status code of
2xx
.
-
Parameters
connectionMetadata
An object containing the necessary metadata to invoke the API. . See ConnectionMetadata for more information. payloadData
An object representing the payload that needs to be sent in the API request body. eventHandlers
An object that contains the callback functions, which are to be called based on the result of API invocation.
Supported results areonSuccess
,onFail
, andonTimeout
. -
Example
var connectionMetadata = { "url": "<Choreo API URL>", "consumerKey": "<Consumer key of the Choreo Application>", "consumerSecret": "<Consumer secret of the Choreo Application>" }; var requestPayload = {"example-key": "example-value"}; callChoreo(connectionMetadata, requestPayload, { onSuccess: function(context, data) { Log.info("Successfully invoked the Choreo API."); }, onFail: function(context, data) { Log.info("Error occurred while invoking the Choreo API."); }, onTimeout: function(context, data) { Log.info("Invoking Choreo API timed out."); } });
Using Asgardeo as the key manager
If you are using Asgardeo as the key manager in your Choreo organization, append the
asgardeoTokenEndpoint
parameter to theconnectionMetadata
variable as follows:var connectionMetadata = { "asgardeoTokenEndpoint": "{{ product_url_format }}/oauth2/token" };
Get parameter value from JWT¶
getValueFromDecodedAssertion(jwt, parameterName, isParameterInPayload)
This function returns a string containing the parameter's value in a decoded Json Web Token (JWT). It includes the following parameters:
-
Parameters
jwt
The JWT to be decoded. parameterName
The name of the parameter in the JWT for which the value should be retrieved. isParameterInPayload
Indicates whether the parameter to be retrieved is in the JWT header or body.
Value should betrue
if the parameter to be retrieved is in the body. -
Example
var state = getValueFromDecodedAssertion(context.request.params.request[0],"state",true);
Get unique user¶
getUniqueUserWithClaimValues(claimMap, context)
The utility function will search the underlying user stores and return a unique user with the claim values. The claim map consists of the claim and value.
-
Parameters
claimMap
A map that contains the claim URI and claim value. context
The authentication context, which contains the context information about the request. -
Example
var claimMap = {}; claimMap[MAPPED_FEDERATED_USER_NAME_CLAIM] = federatedUserName; claimMap[MAPPED_FEDERATED_IDP_NAME_CLAIM] = idpName; var mappedUsername = getUniqueUserWithClaimValues(claimMap, context);
Get associated user¶
getAssociatedLocalUser(federatedUser)
This function returns the local user associated with the federate username given as input.
-
Parameters
federatedUser
The federated user object.
Get masked value¶
getMaskedValue(value)
This utility function returns a masked value for the given input value. It can be used to mask sensitive content in logs.
-
Parameters
value
Value needs to be masked. -
Example
If there is a requirement to add logs containing sensitive information (such as PII), those can be masked using this function as follows.
var email = context.currentKnownSubject.username;
Log.info("Email of the logged user : " + getMaskedValue(email));
HTTP GET¶
httpGet(url, headers, authConfig, eventHandlers)
The HTTP GET function enables sending HTTP GET requests to specified endpoints as part of the adaptive authentication scripts in Asgardeo. It's commonly used to interact with external systems or APIs to retrieve necessary data for authentication decisions.
-
Parameters
url
The URL of the endpoint to which the HTTP GET request should be sent. headers
HTTP request headers to be included in the GET request (optional). authConfig
An object containing the necessary authentication metadata to invoke the API. See AuthConfig for information. eventHandlers
The object that contains the callback functions, which are to be called based on the result of the GET request.
Supported results areonSuccess
andonFail
, which can have their own optional callbacks as anonymous functions. -
Example
var authConfig = { type: "basic", properties: { username: "admin", password: "adminPassword" } }; var onLoginRequest = function(context) { httpGet('https://example.com/resource', { "Accept": "application/json" }, authConfig, { onSuccess: function(context, data) { Log.info("Successfully invoked the external API."); context.selectedAcr = data.status; executeStep(1); }, onFail: function(context, data) { Log.info("Error occurred while invoking the external API."); context.selectedAcr = 'FAILED'; executeStep(2); }, onTimeout: function(context, data) { Log.info("Invoking external API timed out."); executeStep(2); } }); }
HTTP POST¶
httpPost(url, body, headers, authConfig, eventHandlers)
The HTTP POST function enables sending HTTP POST requests to specified endpoints as part of the adaptive authentication scripts in Asgardeo. It's commonly used to interact with external systems or APIs to retrieve necessary data for authentication decisions.
-
Parameters
url
The URL of the endpoint to which the HTTP POST request should be sent. body
HTTP request body to be included in the POST request. headers
HTTP request headers to be included in the POST request (optional). authConfig
An object containing the necessary authentication metadata to invoke the API. See AuthConfig for more information. eventHandlers
The object that contains the callback functions, which are to be called based on the result of the GET request.
Supported results areonSuccess
,onFail
andonTimeout
which can have their own optional callbacks as anonymous functions. For these callbacks, the context and data parameters are passed. -
Example
var authConfig = { type: "clientcredential", properties: { consumerKey: "clientId", consumerSecret: "clientSecret", tokenEndpoint: "https://token-endpoint.com/token" } }; var onLoginRequest = function(context) { httpPost('https://example.com/resource', { "email": "[email protected]" }, { "Authorization": "Bearer token", "Accept": "application/json" }, authConfig, { onSuccess: function(context, data) { Log.info("Successfully invoked the external API."); context.selectedAcr = data.status; executeStep(1); }, onFail: function(context, data) { Log.info("Error occurred while invoking the external API."); context.selectedAcr = 'FAILED'; executeStep(2); }, onTimeout: function(context, data) { Log.info("Invoking external API timed out."); executeStep(2); } }); }
Resolve multi attribute login identifier¶
resolveMultiAttributeLoginIdentifier(loginIdentifier, tenantDomain)
If alternative login identifiers are enabled, this function resolves the username from the provided login identifier.
-
Parameters
loginIdentifier
User provided login identifier. organization
Organization name. -
Example
var loginIdentifier = context.request.params.username[0]; var tenantDomain = context.tenantDomain; var username = resolveMultiAttributeLoginIdentifier(loginIdentifier, tenantDomain);
Update user password¶
updateUserPassword(user, newPassword, eventHandlers)
This function updates the user password.
-
Parameters
user
The user object. newPassword
New user password. eventHandlers
Optional callback event handlers. -
Example
updateUserPassword(user, "newPassword"); updateUserPassword(user, "newPassword", { onSuccess: function(context) { Log.info("Password updated successfully."); }, onFail: function(context) { Log.info("Password update failed."); } });
Object reference¶
Context¶
Contains the authentication context information. The information can be accessed as follows:
context.steps[n] |
Access the authentication step information, where 'n' is the step number (1-based). See step for more information. |
The step number is the one configured at the step configuration, not the actual order in which they get executed.
context.request |
Access the HTTP authentication request information. See request for more information. |
context.response |
Access the HTTP response, which will be sent back to the client. See response for more information. |
context.serviceProviderName |
Get the application name. |
Step¶
Contains the authentication step information. It may be a null or invalid step number.
step.subject |
Contains the authenticated user's information from this step. It may be null if the step is not yet executed. See user for more information. |
step.idp |
Gives the name of the federated connection that is used to authenticate the user. |
step.authenticator |
Give the name of the authenticator that is used for authenticating te user. You can find the authenticator names from the connection names table. |
User¶
user.uniqueId |
The unique identifier of the user. |
user.username |
The user's username. |
user.userStoreDomain |
(Read/Write) The user store domain of the local user. |
user.localClaims["local_claim_url"] |
(Read/Write) User's attribute (claim) value for the given "local_claim_url". If the user is a federated user, this will be the value of the mapped remote claim from the identity provider. |
user.claims["local_claim_url"] |
(Read/Write) Sets a temporary claim value for the session. |
user.localClaims["local_claim_url"] |
Updates the claim value in the user store as well. The user.claims["local_claim_url"] parameter is an alternative to setting a temporary claim. |
user.remoteClaims["remote_claim_url"] |
(Read/Write) User's attribute (claim) as returned by the identity provider for the given remote_claim_url . Applicable only for federated users. |
Request¶
request.headers["header_name"] |
The request's header value for the given header name. |
request.params.param_name[0] |
The request's parameter value for the given parameter name by the param_name index (param_name is an array). |
request.cookies["cookie_name"] |
The request's cookie value for the given cookie name. |
request.ip |
The client IP address of the user who initiated the request. If there are any load balancers (eg. Nginx) with connection termination, the IP is retrieved from the headers set by the load balancer. |
Response¶
response.headers["header_name"] |
(Write) The response header value for the given header name. |
Session¶
session.userAgent |
The user agent object of the user session. See userAgent for more information. |
session.ip |
The session's IP address. |
session.loginTime |
The session's last login time. |
session.lastAccessTime |
The session's last accessed time. |
session.id |
The session's id. |
session.applications |
The list of application objects in the session. See application for more information. |
Application¶
application.subject |
This is the subject of the application. |
application.appName |
This is the name of the application. |
application.appId |
This is the ID of the application. |
User agent¶
userAgent.rawString |
This is the raw userAgent string. |
userAgent.browser |
This is the web browser property that is extracted from the raw userAgent string. |
userAgent.platform |
This is the operating system property that is extracted from the raw userAgent string. |
userAgent.device |
This is the device property that is extracted from the raw userAgent string. |
ConnectionMetadata¶
It contains the necessary metadata for invoking the API when calling the callChoreo function.
connectionMetadata.url |
URL of the Choreo hosted API. |
connectionMetadata.consumerKey |
The consumer key of the Choreo application. |
connectionMetadata.consumerSecret |
The consumer secret of the Choreo application. |
You can securely store consumer keys and secrets as secrets in conditional authentication scripts and refer to
them in your conditional authentication scripts using the secrets.{secret name}
syntax. For example, to retrieve a secret value, you may use:
var consumerSecret = secrets.clientSecret;
Change in behavior from 30th September 2024
Starting from 30th September 2024, you are no longer required to set the aliases for consumer keys and consumer secrets when calling the callChoreo command. Instead, you may directly reference them using the secrets.secretName
notation.
However, if you prefer, you may continue using the previous method as follows.
connectionMetadata.consumerKeyAlias |
The name of the secret that stores the consumer key. |
connectionMetadata.consumerSecretAlias |
The name of the secret that stores the consumer secret. |
AuthConfig¶
When using httpGet or httpPost functions in Asgardeo adaptive authentication scripts, the table summarizes each authentication type and its required properties:
Authentication Type | Properties | Description |
---|---|---|
basic | username, password | Uses user credentials. |
apikey | apiKey, headerName | Uses an API key sent as a header. |
clientcredential | consumerKey, consumerSecret, tokenEndpoint, scope (optional, a space separated list of scopes) | Uses client credentials to obtain an access token. |
bearer | token | Uses a bearer token for authentication. |
You can securely store sensitive values of properties like username, password, consumerKey, consumerSecret as secrets in conditional authentication scripts and refer to them in your conditional authentication scripts using the secrets.{secret name}
syntax. For example, to retrieve a secret value, you can use:
var consumerSecret = secrets.clientSecret;
For more information on adding secrets, refer to the Add a secret to the script section in the documentation.
Data¶
data |
The response data is a JSON object that contains the response data from the API call. |