Skip to content

Setting Up External Authentication

Jason Bau edited this page May 15, 2014 · 9 revisions

Currently the edx-platform supports Shibboleth, CAS, and SSL certificates as external authentication sources, but the documentation for setting them is quite light (i.e. read the code), here is how to use CAS and SSL certificates.

Central Authentication Service (CAS) integration

CAS is one of the simplest and easiest ways to enable external authentication on the platform. All that is required is one feature flag and one configuration item. The feature flag to enable in your EDXAPP_FEATURES yaml hash for ansible (or in any of the settings files) is AUTH_USE_CAS set to true. That flag turns on the django-cas (https://bitbucket.org/cpcc/django-cas/overview) middleware and installed_app. From there only one additional setting is required. and that is CAS_SERVER_URL which needs to be pointed at your CAS server (and is available as $EDXAPP_CAS_SERVER_URL in the edxapp ansible role variables. There is also an optional CAS_EXTRA_LOGIN_PARAMS that can be used to pass additional get attributes to your CAS server to identify where the login is coming from, setting a allowed key, or specifying which authentication provider to use as examples. That setting can be overridden with $EDXAPP_CAS_EXTRA_LOGIN_PARAMS. Additional documentation can be found at the django-cas project page.

We recently added the ability to specify a custom attribute handler so that the attributes returned by your CAS server can be parsed and mapped to the local user model inside the platform. To set that up you need to specify some options in the lms.env.json file and provide a python package and function to do the parsing. Here is an example of the CAS config for the ansible role:

EDXAPP_CAS_ATTRIBUTE_PACKAGE: "git+https://github.com/mitocw/mitx_cas_mapper"
EDXAPP_CAS_ATTRIBUTE_CALLBACK:
  module: "mitx_cas_mapper"
  function: "populate_user"

This will cause the edxapp role to install the specified package and properly populate the json configuration file. The example repo is a real working package that can be easily forked and modified to map your own CAS attributes.

SSL Client Certificates

This is another fairly simple mechanism (configuration wise) that enables using SSL certificates to authenticate and register users from an external source. This just requires adding the feature flag AUTH_USE_CERTIFICATES. Once enabled all that is required to do is have your front end Web server (most likely nginx here) setup to validate client certificates and set the SSL_CLIENT_S_DN header with the clients DN. This can be setup by adding the folling lines to your nginx server config:

ssl_client_certificate /path/to/my/client/cacert
ssl_verify_client on;

The verify client can also be optional if you want to allow ssl auth, but also support another authentication method (like CAS for example), and then adding the header to the proxy location section of your nginx config that looks like:

proxy_set_header SSL_CLIENT_S_DN $ssl_client_s_dn;

That should cause authentication to automatically occur in studio and lms whenever a protected page is accessed. An additional feature flag, AUTH_USE_CERTIFICATES_IMMEDIATE_SIGNUP if set to true will also enable automatic registration to occur for user's so they won't even have to fill out profile information.

Shibboleth

The Shibboleth setup is somewhat more complex than the other methods on this page, mainly because Shibboleth runs as an Apache module. At Stanford, our OpenEdX hosting stack actually includes BOTH nginx and Apache--with Apache running solely to provide Shibboleth support (through mod_shib for authentication and mod_wsgi to run a bit of edx-platform python code, to login and register the user). Here's a general step-by-step guide to how we set up shib access. Some of the steps might be kind of broad and require some debugging on your own.

A lot of this setup is a part of the edx/configuration repo already. If you look at Stanford's production app server playbook, you'll see the roles for apache and shibboleth are part of our standard app server install, and all we do is configure the vars at https://github.com/edx/configuration/blob/master/playbooks/roles/shibboleth/defaults/main.yml.

  • You need to install Apache and mod_shib (as an SP) and configure it to receive attributes from your identity provider IdP. Again, the apache and shib roles at https://github.com/edx/configuration/blob/master/playbooks/roles will do much of this for you, and you can see if configuring the vars in https://github.com/edx/configuration/blob/master/playbooks/roles/shibboleth/defaults/main.yml work out of the box for you. You will at least need to generate a private/public X.509 pair for the IdP. Stanford's instructions for doing that are here.

  • You will need to configure the shibboleth attribute to Apache environment variable mapping. This is done (in Ubuntu) in /etc/shibboleth/attribute-map.xml and /etc/shibboleth/shibboleth2.xml. Basically, you'll want to map the human readable persistent identifier returned by the IdP to Apache's REMOTE_USER environment variable. For Stanford, this is identifier is eppn (of the form <username>@stanford.edu). The mapping is done by the lines

in attribute-map.xml:

    <Attribute name="urn:mace:dir:attribute-def:eduPersonPrincipalName" id="eppn">
        <AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
    </Attribute>

in shibboleth2.xml

    <ApplicationDefaults entityID="https://class.stanford.edu/shibboleth" REMOTE_USER="eppn">
  • You need to set up nginx to proxy the correct urls to apache. Our lms nginx config file has the following for doing that:
upstream apache-lms-backend {
    # For a TCP configuration:
    server 127.0.0.1:{{apache_port}} fail_timeout=0;  # We set {{ apache_port }} to 8080 -- see https://github.com/edx/configuration/blob/master/playbooks/roles/apache/defaults/main.yml 
}
server {
  # LMS configuration file for nginx, templated by ansible

  listen 80;
.
.
.
  location @proxy_to_apache_lms {
    proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
    proxy_set_header X-Forwarded-Port $http_x_forwarded_port;
    proxy_set_header X-Forwarded-For $http_x_forwarded_for;
    proxy_set_header Host $http_host;

    proxy_redirect off;
    proxy_pass http://apache-lms-backend;
  }

  # pass /Shibboleth.sso on to apache
  location /Shibboleth.sso {
    try_files $uri @proxy_to_apache_lms;
  }
  
  # pass shib-login on to apache
  location ~ ^/shib-login/?$ {
    try_files $uri @proxy_to_apache_lms;
  }
}

The apache config files in this very repo already have the corresponding urls correctly routed (/Shibboleth.sso goes to mod_shib, /shib-login goes to mod_wsgi, running the edx-platform application code)

  • You need to enable shib for edx-platform. The shib related feature flags Stanford sets are:
'FEATURES':
    'AUTH_USE_SHIB': true                     # Enables Shibboleth support
    'SHIB_DISABLE_TOS': true                  # Disables the TOS agreement checkbox during registration page
    'RESTRICT_ENROLL_BY_REG_METHOD': true     # Allows course enrollment to be tied to a "linked" shib account from a particular IdP.

Regarding the use of 'RESTRICT_ENROLL_BY_REG_METHOD', mod_shib sets an Apache environment variable 'Shib-Identity-Provider' that the external_auth edx-platform app captures during user registration. This environment variable should identify the IdP server that provided the authentication credentials. (This is 'https://idp.stanford.edu/' for Stanford.) When FEATURES['RESTRICT_ENROLL_BY_REG_METHOD'] is true, you can go into a course's advanced settings in studio (or edit the appropriate course XML) and set the enrollment_domain key (at Stanford we set it to "shib:https://idp.stanford.edu/"), and then course enrollment will be restricted to users who have authenticated using Shib credentials provided by that server.

How does a user log in or register using Shib in LMS? At Stanford we've only had need for specific courses to trigger Shib authentication. So when a course's enrollment_domain Advanced Setting is set to shib:<your_idp>, the "Login", "Register Now", and big "Register for ..." buttons on that course's "About" page in LMS get pointed at a url (/shib-login) that will trigger mod_shib (after proxying from nginx to apache) to handle the auth, which if successful will then land back in apache/mod_wsgi to run the edx-platform code responsible for registering/logging in the user and enrolling them in the correct course.