Managing extensions
You can define your own extension scripts in order to modify the authentication context after the user authenticates themselves to autorize the client application. Complementary to the scripts, you can also create secrets in order to use them within scripts or to validate policies.
Extensions in a nutshell
ACP allows you to write JavaScript extension scripts in a convenient embedded environment so that you can modify the ACP authentication context. Once written, you can enable the scripts on individual IDPs so that they are executed after user authentication. For example, scripts can be useful for the following use-cases:
-
Pulling data (such as user permissions) from external systems
-
Overwriting static attributes in the authentication context
All extension code is executed independently in a secured environment following best security practices. You can test the code using the provided testing and debugging tools and execute it in a sandbox environment available out of the box.
In addition to scripts, you can create secrets and use them for the following purposes:
-
To safely store confidential information within ACP
-
To access protected resources from within your scripts
-
To validate policies in your authorization server
Secrets represent any information that you want to keep confidential. They are encrypted after creation, meaning that their value cannot be retrieved in any way outside of a scripted function or a policy validator.
Prerequisites
-
Access to an ACP tenant. For testing purposes, make sure that Sandbox IDP and Demo Application are set up. For more information, see Adding new workspace in ACP.
-
Working knowledge of JavaScript
-
Authentication context is defined. For testing purposes, add
authorized_clients
(list of strings) andstatic_attribute
(string) to your authentication context. -
Claims to be issued are mapped to authentication context attributes affected by your script. For testing purposes, make sure that
authorized_clients
andstatic_attribute
are issued as claims in the Demo Application.
Create an extension
The video below shows how to create scripted extensions in ACP based on the out-of-the-box templates.
Note
To remove or rename an extension, use the contextual hover-on menu available for each extension in the EXTENSIONS list.
-
Go to Extensions from the workspace main page.
-
Create an extension using one of the available menu options
-
+ - creates an empty script.
-
Sample api request - creates a script with code executing a request to a given URI.
-
Sample with secret - creates a script returning a secret.
-
Sample authn context modification - creates a script which modifies the authentication context after it’s prepared by ACP.
-
-
Enter the script name in the form and click Create. Your script is created and opened in the embedded editor.
-
Write or modify your script in the editor.
-
Save your script.
-
Run the script in test mode to check if it works as expected. In the video below, we are checking a simple script returning a secret value.
-
Check the data in the INPUT section. It is meant to mimic a real request processed by ACP. Modify the paremeters if necessary for the purpose of your test.
-
Select Run test.
Result
Your script runs against the input data. The result is printed in the OUTPUT section. Runtime information is printed in the CONSOLE section.
In a real world scenario, attribute values from OUTPUT override the original authentication context (provided they exist in the authentication context - new attributes are NOT created).
-
-
Optionally, proceed to testing the script with the Sandbox IDP based on the provided template, showing how to combine an API request with a modification of the authentication context.
Test the extension with the Sandbox IDP
Test the extension script using the Sandbox IDP in your workspace. For the purpose of this test, use
the code below as
a template to make a call to a target resource (under uri
)
and modify the authentication context based on data in the response. Note that
all code is within the function scope - it’s a requirement in ACP scripts.
In order to work end-to-end, the below script requires the following configuration in
ACP:
authorized_clients
andstatic_attribute
must be part of ACP authentication context.given_name
must be mapped to an incoming IDP parameter.authorized_clients
andstatic_attribute
must be mapped to claims.
module.exports = async function(context) {
const request = require('request-promise-native');
try {
const response = await request({
method: 'GET',
json: true,
uri: 'http://example.com/resource/path'
});
return {
authn_ctx: {
authorized_clients: response.find(x => x.userId == context.authn_ctx.given_name).authorizedClients.map(x => x.name),
static_attribute: 'static_value'
}
};
}
catch(e) {
console.error(e);
}
}
Attribute | Description |
---|---|
context | Represents the entire function input. Always contains the authn_ctx and secrets objects. |
authn_ctx | Your main object of interest. This object represents the authentication context and is always passed as the function input. Refer to it via context.authn_ctx.ATTRIBUTE_NAME . All attribute values written into authn_ctx by your script replace thvalues from the original authentication context. Attribute to be overwritten must be defined in the ACP authentication context - you cannot create new attributes using the script. Please check the authentication context definition in your ACP workspace if you’re not sure which attributes are defined. |
secrets | This object represents ACP secrets. Refer to it via context.secrets.SECRET_NAME . You can find secret names in the Secrets section. |
The above script compares the given_name
in the authentication context against the userId
in
the
target JSON record. When they match, the script writes the underlying authorizedClients.name
parameter into the authorized_clients
authentication context object. Additionally, the script
sets the static_attribute
in the authentication context to static_value
. ACP
can, therefore, issue claims mapped to the modified authorized_clients
and static_attribute
attributes.
-
Enable the script in the Sandbox IDP. Go to Identities -> Sandbox IDP -> Mappings and select the script from the Post authentication script list.
-
In Identities -> Sandbox IDP -> Mappings, map the
name
IDP attribute to thegiven_name
context attribute. -
Add
authorizedClients
(list of strings) andstatic_attribute
(string) to your authentication context. -
Add the
authorizedClients
andstatic_attribute
claims to your workspace. Map them to the corresponding attributes defined in the previous step. Assign theprofile
scope to both claims. For more information, see Configuring claims for ID tokens and access tokens. -
To simulate external data, add the following object to an online sharing tool (such as hastebin):
Note
Make sure that
userId
matches an existing user name in the Sandbox IDP user pool.[ { "userId":"SANDBOX_USER_NAME", "partnerDetails":{ "orgId":"001", "partnerId":"001", "partnerType":[ "third-party-access" ] }, "authorizedClients":[ { "name":"Client 1", "privileges":[ "tpa-access" ] }, { "name":"Client 2", "privileges":[ "tpa-access" ] }, { "name":"Client 2", "privileges":[ "tpa-access" ] }, { "name":"Client 4", "privileges":[ "tpa-access" ] } ] } ]
-
Add the path to the above resource to the
uri
parameter in your script. -
Log in to the demo application as the user you entered in the
userId
attribute above.Result
In case of the sample script used for this test , we can expect the
authorized_clients
andstatic_attribute
claims to be modified. Inspect the ID token presented after login to confirm this:{ "acr": "0", "aid": "default", "amr": [ "pwd", "mfa" ], "aud": "default-demo", "auth_time": 1633442410, "authorized_clients": [ "Client 1", "Client 2", "Client 3", "Client 4" ], "email": "mail@domain.com", "exp": 1633446013, "given_name": "SANDBOX_USER_NAME", "iat": 1633442413, "idp": "c5dh64n3qv46ahmfntq0", "iss": "https://tenant.authz.cloudentity.io/tenant/default", "jti": "88c8cb95-a826-41c1-8e55-c2508745d593", "name": "Joe", "nbf": 1633442413, "nonce": "c5e5klpli7m52gnpk300", "rat": 1633442413, "scp": [ "email", "openid", "profile" ], "static_attribute": "static_value", "st": "public", "sub": "12539980", "tid": "cloudentity-tenant" }
Recommendations for writing extensions
Please keep in mind that if your script fails, users won’t be able to autheticate. Adhere to the following best practices when writings scripts:
-
Write safe code using try/catch statements.
-
Add meaningful error messages.
-
Run your script in test mode at least once.
When running the script in test mode, check for errors in the console. You can see a sample error report in the video below, where we’re making a call to a non-existing document.
Create a secret
ACP allows you to define secrets which can be used in JavaScript function calls and policies. The video below shows how to add and manage secrets.
-
Go to Extensions in the left-hand menu. The Extensions page opens.
-
Select Create Secret. Provide the secret name and value in the pop-up window when prompted.
Note
You won’t be able to see the secret value after it’s saved. It can be only retrieved by an extension script or a policy validator.
-
Select Create. Your secret is added to the list.
You can manage your secrets from the workspace settings page. Go to Settings -> Secrets to edit secret values, delete secrets, or create new secrets.
Use secret in extension
To use your secret in an extension script, provide the secret name within a function via the
context.secrets.SCRIPT_NAME
reference:
module.exports = async function(context) {
return {
secret: context.secrets.SCRIPT_NAME
};
}
Such reference is ready out of the box if you create a script from the Sample with secret template.
Use secret in a policy
To use your secret in Cloudentity policy editor, refer to it in a policy validator by selecting Secrets as the source or target and providing the secret name. The secret value is then used for comparison in the validator. For more information, read Creating a policy in Cloudentity editor.
To use your secret in a Rego policy, see Rego secret check policy.