Moodle SSO Integration Guide

Some of our application partners use the Moodle platform to deliver their content and manage courses. It may be helpful to build out Clever SSO integration to allow users to more easily access this content. While this integration can be set up with minimal development work, there are aspects of it that may still require engineering based on your needs.

πŸ“˜

SSO Integrations Only

Please note that this guide is meant for Clever SSO integrations with Moodle only and does not include any guidance for rostering.

OAuth with Moodle

🚧

Moodle Version

This guide is written with version 4.0 in mind. If you are working with a different version of Moodle, some aspects may not apply.

To get SSO working, we will need to set up an OAuth connection. You will need administrator access. On the Site administration page, navigate to Server

Next, select "OAuth 2 services"

Configuration - Clever

In newer versions of Moodle, you should see an option to create a new "Clever" service. Selecting this option, will pre-populate some fields in the configuration page. At this stage, all you need to do is provide a Client ID and Client secret. These can be found in your Clever application developer dashboard Settings.

Once you've provided your client credentials, you are done! You have effectively set up SSO between your Moodle instance and Clever. Navigating to your login page, you should now see a Clever login button.

Configuration - Custom

If you do not see the option to create a Clever service in your Moodle instance, select "Custom". You will have additional configuration steps involving authentication endpoints and field mappings. Please see the screenshots below:

Under "Edit", the second icon from the left represents endpoint configuration and the third represents field mappings.

Under "Edit", the second icon from the left represents endpoint configuration and the third represents field mappings.

authorization_endpoint: https://clever.com/oauth/authorize

token_endpoint: https://clever.com/oauth/tokens

userinfo_endpoint: https://api.clever.com/v3.0/me

userdata_endpoint: https://api.clever.com/v3.0/users

data-id: idnumber

data-name-first: firstname

data-name-last: lastname

data-email: email

Once you've set up the field mappings and

Clever-initiated Logins and the State Param

Many Clever users will launch SSO from the Clever Portal, which is Clever's SSO launchpad page. See the screenshot below as an example:

By default, your Moodle-Clever SSO integration is unable to handle authentication requests that are kicked off from the Clever Portal. This is because Moodle requires a state parameter for authentication requests in order to prevent CSRF attacks.

If your integration is not set up to handle this, you will see the following error message when authentication is initiated from the Clever Portal into your Moodle instance.

To handle authentication requests initiated from the Clever Portal, we'll need to re-initiate the authentication request from our Moodle application with the state parameter appended. Clever will pass the state parameter through so all you need to do is adjust the authentication service to handle this use case.

In your Moodle source code files, navigate to /admin/oauth2callback.php.

Here, you will want to process Clever-initiated SSO requests that are missing state parameters by creating a new request and formulating it to include a state parameter. See an example workflow below:

$state = optional_param('state', '', PARAM_RAW);
if ($state == '') {
    /*print_error('missing state');*/

    $stateparams['wantsurl'] = new moodle_url('/');
    $stateparams['sesskey'] = sesskey();
    $stateparams['id'] = $issuer->get('id');
//Include all relevant params for the new authentication request
    $params = array_merge(
        [
            'client_id' => $issuer->get('clientid'),
            'redirect_uri' => new moodle_url('/admin/oauth2callback.php'),
            'response_type' => 'code',
            'scope' => optional_param('scope', null, PARAM_RAW),
            'code' => optional_param('code', null, PARAM_RAW),
            'state' => new moodle_url('/auth/oauth2/login.php', $stateparams),
        ]
    );
 //Formulate a new SSO request URL with the necessary params
    $backtocleverurl = new moodle_url($clever_url, $params);
 
    error_log("*****************admincallback backtocleverurl redirect back to clever");
    error_log(print_r($backtocleverurl, true));
    redirect($backtocleverurl);
} else {
// The authorization code generated by the authorization server.
    $code = required_param('code', PARAM_RAW);
// The state parameter we've given (used in moodle as a redirect url).
    $state = required_param('state', PARAM_LOCALURL);
    error_log("admincallback state");
    error_log(print_r($state, true));

    $redirecturl = new moodle_url($state);
    $params = $redirecturl->params();

    if (isset($params['sesskey']) and confirm_sesskey($params['sesskey'])) {
        $redirecturl->param('oauth2code', $code);
        redirect($redirecturl);
    } else {
        print_error('invalidsesskey');
    }
}