1. Overview & Set-up

Dataguard provides an integration to extend Auth0's universal login to include collection of consent as part of the login flow.

Please note DataGuard Consent & Preference Management was formally known as Consentric by MyLife Digital. We are in the process of updating all references to DataGuard in the platform, so you will see both names used inter-changeably until this work is complete.

1a - How It Works

The diagram above shows how authenticating with Auth0 can be extended to include a redirect to a page containing a DataGuard widget.

The authenticating user can then interact with the widget recording their permissions in a progressive manner.

On submission, the Auth0 authentication flow completes.

1b - User app_metadata

Once enabled for a tenant an entry will be created in the user's app_metadata on login.

In order to reflect a user's consents for the login flow, a token is generated and stored for a user on login.
This token is stored in the user's app_metadata under the namespace dataguard.
The integration will then pass this value to the associated web page by appending the value to the URL

https://yoursite.com/consent-capture?token=5cbf86968b08b7f45e454b39bff35e93

The integration will manage all aspects of this for you but adequate space will be needed in app_metadata to accommodate the token and expiry for the user.

2 - Installation

2a - Pre-Requisites

  • An active Auth0 account (you can sign up for free here)
  • A DataGuard Consent & Preference Management instance. To sign-up, go here and complete the submission form (we will recreate on the DataGuard website shortly).
  • A webpage where all users are redirected to at the point of login and where the Progressive Widget can be embedded into. You can use a DataGuard hosted page if you wish, this is created for you at sign-up (the URL is provided in your welcome email).
  • DataGuard API Client details (sent to you in your sign up email)

2b - Setup page with progressive widget

The example flow works by redirecting out of Auth0's login flow to a custom webpage containing a Progressive widget. The custom webpage needs to include the following Javascript snippet to support the Auth0 flow.

N.B. Ensure you populate the config object with relevant properties from your DataGuard CPM application and Auth0 tenant.

πŸ“˜

Config Value

The values of your Dataguard CPM application ID, client ID and client secret will be in your welcome emails. Please contact [email protected] if you have any issues.

<script>
  const urlParams = new URLSearchParams(
    window.location.search,
  );  

  const config = {
      elementId: <SELECTOR ID TO BIND THE CONSENTRIC WIDGET TO>,
      templateId: <CONSENTRIC TEMPLATE ID>,
      ruleId: <CONSENTRIC RULE ID>,
      auth0Domain: <ORGANISATION AUTH0 DOMAIN> 
  };

  // e.g.
  // const config = {
  //     elementId: 'mld-prog-widg',
  //     templateId: 'SVxfz4fUbnM',
  //     ruleId: 'jMDMcKcV8Th',
  //     auth0Domain: 'lightningenergy.eu.auth0.com' 
  // };

  const token = urlParams.get('token');
  const auth0State = urlParams.get('state');
  const returnUrl = 'https://' + config.auth0Domain + '/continue?state=' + auth0State;

  const onEmptyLoad = () => {
    console.log('EMPTYLOAD')
    window.location.href = returnUrl;
    //window.location.replace(returnUrl);
  };

  const onSuccess = () => {
    console.log('SUCCESS')
    //window.location.href = returnUrl;
    window.location.replace(returnUrl);
  };

  const events = {
    onSuccess,
    onEmptyLoad
  }

  window.addEventListener('load', function () {
    ProgressiveWidget.load({
      templateId: config.templateId,
      ruleId: config.ruleId,
      id: config.elementId,
      token,
      consentricLogo: true,
      display: {
        location: 'center',
        closeOnSubmit: false,
        displayCancelButtons: false
      },
      events
    });
  });
</script>
<script src="https://scripts.consentric.io/progressive-consent.min.js"></script>

3 - Add the Auth0 Action

  1. Select Add Integration (at the top of this page).
  2. Read the necessary access requirements and click Continue.
  3. Configure the integration using the following fields:
  • Auth Host: The URL to authenticate against for your DataGuard API token, like
    https://sandbox-consentric.eu.auth0.com
    
  • API Host: The Dataguard API host URL, like
    https://sandbox.consentric.io
    
  • Audience: The name of the Dataguard API being called, like
    https://sandbox.consentric.io
    
  • Client ID: The Dataguard ClientId issued to you
  • Application ID: The Dataguard ApplicationId issued to you
  • Redirect URL: The URL of the page containing the Progressive widget built above
  • Client Secret: The Dataguard ClientSecret issued to you

Finally, proceed with the following steps:

  1. Click Create to add the integration to your Library.
  2. Click the Add to flow link on the pop-up that appears.
  3. Drag the Action into the desired location in the flow.
  4. Click Apply Changes.

The example shows how authenticating with Auth0 can be extended to include a redirect to a page containing a Consentric widget.

The authenticating user can then interact with the widget recording their permissions in a progressive manner.

On submission, the Auth0 authentication flow completes.

API Access

In order to access the Consentric API the Integration will retrieve and store an API access token and store this for the entire Auth0 Tenant.

The API token will be stored in global.consentricApiToken which will be available to other rules running within the Auth0 context.

The expiry date of this token will also be stored in global.consentricApiToken.exp to indicate when the token expires.

User app_metadata

1674

Once enabled for a tenant an entry will be created in the users app_metadata on login

In order to reflect a user's consents for the log in flow a token is generated and stored for a user on log in.

This will be stored in the user's app_metadata under the namespace consentric .

The integration will then pass this value to the associated web page by appending the value to the URL.
i.e. https://yoursite.com/consent-capture?token=5cbf86968b08b7f45e454b39bff35e93

The integration will manage all aspects of this for you but adequate space will be needed in app_metadata to accommodate the token and expiry for the user.

Installation

Pre-requisites

  • An active Auth0 account (the application you are securing with Auth0)
  • A configured Consentric instance with Progressive Consent enabled
  • A self-hosted webpage into which the Progressive Widget can be embedded (
  • Consentric API Client Details (sent to you in your Consentric sign up email)

Setup page with Progressive Widget

The example flow works by redirecting out of Auth0's login flow to a custom webpage containing a Progressive widget.

The custom webpage needs to include the following Javascript snippet to support the Auth0 flow.

N.B. Ensure you populate the config object with relevant properties from your Consentric application and Auth0 tenant.

πŸ“˜

Config Values

The values of your Consentric application ID, client ID and client secret will be in your welcome emails. Please contact [email protected] if you have any issues.

<script>
  const urlParams = new URLSearchParams(
    window.location.search,
  );  

  const config = {
      elementId: <SELECTOR ID TO BIND THE CONSENTRIC WIDGET TO>,
      templateId: <CONSENTRIC TEMPLATE ID>,
      ruleId: <CONSENTRIC RULE ID>,
      auth0Domain: <ORGANISATION AUTH0 DOMAIN> 
  };

  // e.g.
  // const config = {
  //     elementId: 'mld-prog-widg',
  //     templateId: 'SVxfz4fUbnM',
  //     ruleId: 'jMDMcKcV8Th',
  //     auth0Domain: 'lightningenergy.eu.auth0.com' 
  // };

  const token = urlParams.get('token');
  const auth0State = urlParams.get('state');
  const returnUrl = 'https://' + config.auth0Domain + '/continue?state=' + auth0State;

  const onEmptyLoad = () => {
    console.log('EMPTYLOAD')
    window.location.href = returnUrl;
    //window.location.replace(returnUrl);
  };

  const onSuccess = () => {
    console.log('SUCCESS')
    //window.location.href = returnUrl;
    window.location.replace(returnUrl);
  };

  const events = {
    onSuccess,
    onEmptyLoad
  }

  window.addEventListener('load', function () {
    ProgressiveWidget.load({
      templateId: config.templateId,
      ruleId: config.ruleId,
      id: config.elementId,
      token,
      consentricLogo: true,
      display: {
        location: 'center',
        closeOnSubmit: false,
        displayCancelButtons: false
      },
      events
    });
  });
</script>
<script src="https://scripts.consentric.io/progressive-consent.min.js"></script>

Add Configuration Properties

  1. Navigate to your Auth0 Management Dashboard
  2. Click on the Rules Link from the left hand menu.
  3. Add the Required Properties to the Rule Configuration
    • CONSENTRIC_AUTH_HOST - The URL to authenticate against for your consentric API token. i.e. https://consentric.eu.auth0.com
    • CONSENTRIC_API_HOST - The Consentric API host URL i.e. https://api.consentric.io
    • CONSENTRIC_AUDIENCE - The name of the Consentric API being called i.e. https://api.consentric.io
    • CONSENTRIC_CLIENT_ID - The ClientId issued to you
    • CONSENTRIC_CLIENT_SECRET - The ClientSecret issued to you
    • CONSENTRIC_APPLICATION_ID - The ApplicationId issued to you
    • CONSENTRIC_REDIRECT_URL - The location of the page containing the widget to be included in the Auth0 authentication flow.

Create the Rule

  1. go to Rules > Create Rule and select the MyLife Digital Progressive Consent template
  2. Copy the contents of the rule below into the editor and Click Save
function consentricIntegration(user, context, callback) {
    const axios = require('[email protected]');
    const moment = require('[email protected]');
    const { Auth0RedirectRuleUtilities } = require("@auth0/[email protected]");

    const ruleUtils = new Auth0RedirectRuleUtilities(
        user,
        context,
        configuration
    );

    const asMilliSeconds = (seconds) => seconds * 1000;

    const {
        CONSENTRIC_AUTH_HOST,
        CONSENTRIC_API_HOST,
        CONSENTRIC_AUDIENCE,
        CONSENTRIC_CLIENT_ID,
        CONSENTRIC_CLIENT_SECRET,
        CONSENTRIC_APPLICATION_ID,
        CONSENTRIC_REDIRECT_URL
    } = configuration;

    const consentricAuth = axios.create({
        baseURL: CONSENTRIC_AUTH_HOST,
        timeout: 1000,
    });

    const consentricApi = axios.create({
        baseURL: CONSENTRIC_API_HOST,
        timeout: 1000,
    });

    // Returns Consentric API Access Token (JWT) from either the global cache or generates it anew from clientId and secret
    const getConsentricApiAccessToken = async () => {
        const consentricApiTokenNotValid = (!global.consentricApiToken) ||
            global.consentricApiToken.exp < new Date().getTime();

        if (consentricApiTokenNotValid) {
            try {
                // Exchange Credentials for Consentric Api Access token
                const { data: { expires_in, access_token } } = await consentricAuth                
                    .post('/oauth/token', {
                        grant_type: 'client_credentials',
                        client_id: CONSENTRIC_CLIENT_ID,
                        client_secret: CONSENTRIC_CLIENT_SECRET,
                        audience: CONSENTRIC_AUDIENCE,
                        applicationId: CONSENTRIC_APPLICATION_ID,
                    });
                
                

                const expiryInMs = new Date().getTime() + asMilliSeconds(expires_in);
                const auth = {
                    jwt: access_token,
                    exp: expiryInMs
                };

                // Persist API Access token in global properties
                global.consentricApiToken = auth;

            } catch (error) {
                console.error('Unable to retrieve API Access token for Consentric. Please check that your credentials (CONSENTRIC_CLIENT_ID and CONSENTRIC_CLIENT_SECRET) are correct.');
                throw error;
            }
        }

        return global.consentricApiToken;
    };

    // Creates Citizen Record in Consentric with Auth0 Id
    const createCitizen = ({ userRef, apiAccessToken }) => {
        console.log(`Upserting Consentric Citizen record for ${userRef}`);
        const data = {
            applicationId: CONSENTRIC_APPLICATION_ID,
            externalRef: userRef,
        };

        return consentricApi
            .post('/v1/citizens', data, {
                headers: {
                    Authorization: 'Bearer ' + apiAccessToken
                },
            })
            .catch(err => {
                if (err.response.status !== 409) { // 409 indicates Citizen with given reference already exists in Consentric
                    console.error(err);
                    throw err;
                }
            });
    };

    // Function to retrieve Consentric User Token from User Metadata
    const getConsentricUserTokenFromMetadata = user => user.app_metadata && user.app_metadata.consentric;

    // Generates On Demand Consentric User Token for the given User using the API Access Token
    const generateConsentricUserAccessToken = async ({ userRef, apiAccessToken }) => {
        try {
            console.log(`Attempting to generate access token API for ${userRef}`);

            const { data: { token, expiryDate: exp } } = await consentricApi
                .post('/v1/access-tokens/tokens',
                    {
                        applicationId: CONSENTRIC_APPLICATION_ID,
                        externalRef: userRef,
                        expiryDate: moment().add(3, 'months').toISOString()
                    },
                    {
                        headers: {
                            Authorization: 'Bearer ' + apiAccessToken
                        }
                    }
                );

            return {
                token,
                exp
            };

        } catch (err) {
            console.error(err);
            throw err;
        }
    };

    const loadConsentricUserAccessToken = async ({ user }) => {
        try {
            const metadataUserToken = getConsentricUserTokenFromMetadata(user);            
            if ((metadataUserToken) && moment(metadataUserToken.exp).subtract(1, "days").isAfter(moment())) return metadataUserToken;
        
            const { jwt: apiAccessToken } = await getConsentricApiAccessToken();            
            const apiCredentials = {
                userRef: user.user_id,
                apiAccessToken,
            };

            // Create Citizen with Auth0 UserId
            await createCitizen(apiCredentials);

            // Generate an On Demand Access Token for the created citizen
            const generatedToken = await generateConsentricUserAccessToken(apiCredentials);

            // Persist the app_metadata update            
            await auth0.users.updateAppMetadata(user.user_id, { consentric: generatedToken });

            return generatedToken;
        } catch (err) {
            console.error(`Issue Loading Consentric User Access Token for user ${user.user_id} - ${err}`);
            throw err;
        }
    };

    const initConsentricFlow = async () => {
        try {
            const { token } = await loadConsentricUserAccessToken({ user });
            const urlConnector = CONSENTRIC_REDIRECT_URL.includes('?') ? '&' : '?';
            const redirectUrl = CONSENTRIC_REDIRECT_URL + urlConnector + 'token=' + token;
    
            context.redirect = {
                url: redirectUrl
            };
            
        } catch (err) {
            console.error(`CONSENTRIC RULE ABORTED: ${err}`);
        }
        return callback(null, user, context);
    };

    if (ruleUtils.canRedirect) {
        return initConsentricFlow();
    } else {
        // Run after Redirect or Silent Auth
        return callback(null, user, context);
    }
}

🚧

Please Note

Once marked as active, all logins for your tenant will redirect users based on the configuration specified above. Please make sure all components have been configured correctly and verified before activating the integration.

Once you are happy with your configuration Mark the rule as Active