Qualtrics Social Connect uses the OAuth 2.0 protocol (draft 20) for authentication and authorization. We support a number of different OAuth flows that you can use within your website, mobile and desktop apps.

OAuth endpoints

The following URLs are the Qualtrics Social Connect specific OAuth endpoints.

User authorization
https://app.engagor.com/oauth/authorize/?client_id=[...]&response_type=code&scope=[...](&state=[...])(&scope=[...])
Access Token
https://app.engagor.com/oauth/access_token/?client_id=[...]&client_secret=[...]&grant_type=authorization_code&code=[...]
Refresh Access Token
https://app.engagor.com/oauth/access_token/?client_id=[...]&client_secret=[...]&grant_type=refresh_token&refresh_token=[...]

Server-side user authentication

OAuth 2.0 involves three different steps: user authentication, app authorization and app authentication. User authentication ensures that the user is who they say they are. App authorization ensures that the user knows exactly what data and capabilities they are providing to your app. App authentication ensures that the user is giving their information to your app and not someone else. Once these steps are complete, your app is issued an user access token that enables you to access the user's information and take actions on their behalf.

User authentication and app authorization are handled at the same time by redirecting the user to our user authorization endpoint. You pass in the client_id generated for your application, eg.;

https://app.engagor.com/oauth/authorize/?client_id=[...]&response_type=code

If the user isn't already logged in on Qualtrics Social Connect, we ask to enter their login credentials.

Once we have successfully authenticated the user (or the user was already logged in), the OAuth page will prompt the user to authorize the app.

By default, the user is asked to authorize the app to access basic information about the user (their ID and name). If your app needs more than this basic information to function, you must request specific permissions from the user. This is accomplished by adding a 'scope' parameter to the User Authorization endpoint followed by space separated list of the required permissions. The following example shows how to ask for read and write access to a user's different Qualtrics Social Connect accounts.

https://app.engagor.com/oauth/authorize/?client_id=[...]&response_type=code&scope=accounts_read%20accounts_write

A full list of available permissions/scopes can be found below.
Please note: don't ask for permissions you don't need, the user might be less likely to authorize your app.

If the user does not authorize your app, we will redirect (via HTTP 302) the user's browser to the redirect_uri configured for your application:

http://YOUR_URL?error_reason=user_denied&error=access_denied&error_description=The+user+denied+your+request.

If the user presses Authorize app, your app is authorized. We will redirect (via HTTP 302) the user's browser to the redirect_uri configured for your application with an authorization code appended:

http://YOUR_URL?code=A_CODE_GENERATED_BY_SERVER(&state=[...])

If you add a state parameter to the original user authorization endpoint this param will also be added to the return url (as shown above). You can use this parameter for maintaining state in your application specific code.

With this code in hand, you can proceed to the next step, app authentication, to gain the access token you need to make API calls.

In order to authenticate your app, you must pass the authorization code and your app secret to the access token endpoint. The client_secret is available on the applications page and should not be shared with anyone or embedded in any code that you will distribute.

https://app.engagor.com/oauth/access_token/?client_id=[...]&client_secret=[...]&grant_type=authorization_code&code=[...]

If your app is successfully authenticated and the authorization code from the user is valid, the authorization server will return the access_token and refresh_token:

{ "access_token": "[...]", "expires_in": 7890000, "token_type": "bearer", "scope": "email accounts_read accounts_write socialprofiles", "refresh_token": "[...]" }

If there is an issue authenticating your app, the authorization server will return the error in the body of the response, eg.:

{"error": "invalid_grant", "error_description": "Refresh token doesn't exist or is invalid for the client"}

Authenticating requests

The access_token returned by this last call returned should then be used to authenticate calls to protected resources (API endpoints), eg.:

https://api.engagor.com/me/?access_token=[...]

Token expiry:

In addition to the tokens, the access_token-response contains the number of seconds until the acces_token expires (the expires_in parameter). Once the access_token expires, you will need to refresh the access_token by using the refresh_token. Do a call to the refresh token OAuth endpoint with the refresh_token you've been passed and you'll get a new access_token and new refresh_token.

If both your access_token and refresh_token have been expired, please redo the full OAuth flow and start by redirecting your users to the user authorization OAuth endpoint.

https://app.engagor.com/oauth/access_token/?client_id=[...]&client_secret=[...]&grant_type=refresh_token&refresh_token=[...]

Token Lifetime
access_token 7890000 seconds
refresh_token 63072000 seconds

Server-side user authentication example

The following PHP example demonstrates the server-side flow with CSRF protection in one self-contained example:

                    <?php

// configuration (see {{getCurrentDevelopersDomain()}}/applications)
// set up your application so the redirect_uri runs this script
$clientId = 'YOUR_CLIENT_ID';
$clientSecret = 'YOUR_CLIENT_SECRET';
$scope = 'accounts_read accounts_write';

session_start();
$code = $_REQUEST['code'] ?? null;

if (!empty($_GET['error']) && $_GET['error'] === 'access_denied') {
    echo 'The user did not authorize your application to use your Qualtrics Social Connect account.';
    exit();
}

// Step 1 is generating a session state against CSRF and redirecting the user
// to the authentication url so that they can consent to us using their token.
if (empty($code)) {
    // Put a random state in the session so that we can protect ourselves against CSRF attacks
    $_SESSION['state'] = bin2hex(random_bytes(32));

    $params = [
        'client_id' => $clientId,
        'state' => $_SESSION['state'],
        'response_type' => 'code',
    ];

    if (!empty($scope)) {
        $params['scope'] = $scope;
    }

    $authorizeUrl = 'https://app.engagor.com/oauth/authorize/';
    $authorizeUrl .= '?' . http_build_query($params);

    header("Location: {$authorizeUrl}");
    exit;
}

// Step 2 is converting the code that we got through step 1 to an access token
// We'll need the state that we set in the session as well, to see if we were
// subject to a CSRF attack.
if (empty($code) || $_REQUEST['state'] !== $_SESSION['state']) {
    echo 'The state does not match. You may be a victim of CSRF.';
    exit();
}

$params = [
    'client_id' => $clientId,
    'client_secret' => $clientSecret,
    'grant_type' => 'authorization_code',
    'code' => $code,
];

$tokenUrl = 'https://app.engagor.com/oauth/access_token/';
$tokenUrl .= '?' . http_build_query($params);

// Ideally replace with PSR-18 Http client
$apiResponse = file_get_contents($tokenUrl);
// Do error checking with json_last_error()
$apiResponse = json_decode($apiResponse, true);

if (!$apiResponse['access_token']) {
    echo 'We could not validate your access token.';
    exit();
}

$token = $apiResponse['access_token'];

// You will want to save the access_token and refresh_token (+ details)
// in the database (instead of the session) for re-use later


// When everything was successful, we can start issueing authorized requests
$params = [
    'access_token' => $token,
];

$protectedResource = 'https://api.engagor.com/me/';
$protectedResource .= '?' . http_build_query($params);

$apiResponse = file_get_contents($protectedResource);
// Don't forget error checking with json_last_error()
$content = json_decode($apiResponse, true);

if (!is_array($content) || !isset($content['response'])) {
    throw new RuntimeException('Something went wrong');
}

$user = $content['response'];

echo 'Hello ' . $user['name'];

                

Available scopes

If your application needs more than the basic identification rights, you can request more permissions by adding a scope parameter to the user authorization endpoint. The value of 'scope' is a space separated list of keys from the following table.

Key Description
identify Identification
… know who you are and can access your Qualtrics Social Connect id and name.
accounts_read Read Access
… read data from your Qualtrics Social Connect accounts, projects and topics.
accounts_write Write Access
… update and delete data from your Qualtrics Social Connect accounts, projects and topics.
socialprofiles Social Profiles
… publish to your personal social profiles (Facebook, Twitter, a.o.).
email Email
… know what your email address is.
accounts_handover Handover
… initiate a handover for contacts in your Qualtrics Social Connect accounts, projects and topics.

Notes

  • A user's access tokens are revoked whenever they change their password. This is to prevent abuse. If this happens, you'll get a standard error, and can guide the user through the OAuth flow again to get a new valid access token.