How to use Oak LDAP

Expand All

Service providers must register before being able to query the Oak LDAP service.  Please send a separate request for each service where you are interested in using Oak LDAP.

To register, please email to iam@it.ox.ac.uk with the following information:

  • Which Kerberos principal(s) should be granted access to Oak LDAP for this service?
    • IAM will no longer issue WebAuth principal(s), as we no longer operate Stanford WebAuth based services.
    • If your service does not have an Oak LDAP principal, we will create a new principal in the form oak-ldap/<HOSTNAME>@OX.AC.UK for this purpose
    • See the ITSS Wiki authentication page for information
  • Will the principal(s) need access to the personal LDAP entries of all people, or only of people affiliated to your unit(s)?
  • Confirmation that you have read the Oak LDAP terms of use

We can make various changes to Oak LDAP access for you. Please contact iam@it.ox.ac.uk to request any of the following:

  • Grant/revoke management rights over an oak-ldap/ service principal for a /itss principal
  • Revoke access and delete an oak-ldap/ service principal
  • Change the level/scope of access for an oak-ldap/ service principal

The service endpoints are ldap://ldap.oak.ox.ac.uk:389 (TLS) and ldaps://ldap.oak.ox.ac.uk:636 (SSL).

You will need to use an LDAP client that supports SASL / GSSAPI authentication.

Your client will need to trust the root certificate for both TLS and SSL which is the Entrust Root Certification Authority - G2 certificate as of 18th January 2022 (download).

Some pieces of client configuration are the same across all, or most, of the runtime environments dealt with in the remainder of this document. These common elements are described in this section. Examples are provided for Debian Linux with a typical setup, and will need to be translated for other operating systems and environments.

Ensure Oak LDAP's SSL certificates will be trusted

As discussed above, one CA root must be trusted. The exact details of configuration will vary according to OS, LDAP libraries and clients, but one common case is a single file containing the CA roots (it could include more; this is the minimum requirement). In Debian, for example, the ca-certificates package manages the file /etc/ssl/certs/ca-certificates.crt which may be used for this purpose. The directory /etc/ssl/certs may also be configured as a CA directory for some applications.

Any application using the OpenLDAP libldap libraries for making LDAP connections (examples of this include PHP ldap support, the OpenLDAP command line tools (ldapsearchldapcompare, etc), and mod_webauthldap) require the following to exist in a ldaprc; commonly, a system-wide file exists; for example on Debian this is /etc/ldap/ldap.conf. This file should contain the following:

TLS_CACERT <path to CA certificates file>

Install client packages and SASL GSSAPI support

You may need to install SASL GSSAPI support. In Debian this is provided by libsasl2-modules-gssapi-mit.

Fetch Kerberos keys into keytab files

When you registered for the service, you requested access for specific principal(s). You can fetch newly generated keys for these principals using the kadmin utility or equivalent (unfortunately, there is no way to fetch a key over the kadmin protocol without triggering generation of a new key, so be careful if this principal is already in use elsewhere). An example session:

$ kadmin -p USER/itss@OX.AC.UK
kadmin: ktadd -k /PATH/TO/KEYTAB host/example.ox.ac.uk@OX.AC.UK
Entry for principal oak-ldap/example.ox.ac.uk with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/PATH/TO/KEYTAB. Entry for principal oak-ldap/example.ox.ac.uk with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/PATH/TO/KEYTAB.

You can then check it has created something useful with:

$ klist -e -k /PATH/TO/KEYTAB

Make the Kerberos credentials cache available to the client

For the MIT or Heimdal Kerberos implementations, the KRB5CCNAME environment variable controls where the application looks for the credentials cache. If you're using Apache, you can use the SetEnv directive from mod_env. Alternatively, use the way of setting this environment variable provided by the runtime system or programming language you're using.

The credentials cache has a short lifetime (order of hours), so to keep it fresh you will need to periodically update it with new tickets fetched using the key in your keytab. The user updating the credentials cache based on the keytab will require read access to the keytab, and write access to the credentials cache. The credentials cache will then need to be readable by the user running the LDAP client, for example the web server.

One utility designed to assist with this is k5start, available in Debian in the package kstart. An example invocation is:

$ k5start -v -f /PATH/TO/KEYTAB -k /PATH/TO/CCACHE YOURPRINCNAME@OX.AC.UK

You should arrange for k5start to run as a continually-running process (daemon) on the system.

Another way to keep a fresh credentials cache derived from a keytab is by periodically running kinit.

The instructions in this section assume that you have configured your system according to Common Client Configuration above.

ldapsearch and ldapcompare, part of the OpenLDAP client tools, may be used to perform initial testing of access to the LDAP service. In Debian, they are contained in the ldap-utils package.

Assuming you have the keytab of the principal allowed access to the LDAP service accessible, you can do:

$ export KRB5CCNAME=<PATH_TO_CREDENTIALS_CACHE>
$ kinit -k -t <PATH_TO_KEYTAB> <PRINCIPAL_NAME>
$ ldapsearch -H ldaps://ldap.oak.ox.ac.uk -b ou=people,dc=oak,dc=ox,dc=ac,dc=uk '(sn=<your surname>)'

This should return results including (assuming the principal in question is permitted access to view your record) information about you and other people with your surname.

$ ldapcompare -H ldaps://ldap.oak.ox.ac.uk \
oakPrimaryPersonID=<yourpersonid (from above)>,ou=people,dc=oak,dc=ox,dc=ac,dc=uk \
eduPersonOrgUnitDN:oakUnitCode=itserv,ou=units,dc=oak,dc=ox,dc=ac,dc=uk

This will return the string "TRUE" or "FALSE" depending on whether you have an affiliation with the unit (in this case itserv).

We recommend that you ensure that you can perform the above steps successfully on your server using the keytab/principal registered for access before going any further.

The instructions in this section assume that you have configured your system according to Common Client Configuration above.

If you are using a Debian-based distribution, install these packages:

  • libnet-ldap-perl 0.36-1 or later
  • libauthen-sasl-perl
  • libgssapi-perl

For other distributions, use the appropriate method to install these CPAN modules:

(An alternative to the native Perl GSSAPI module is Authen::SASL::Cyrus which is based on the SASL libraries described above, but in our tests there appeared to be some problems with its handling of the round-robin DNS hostname of the Oak LDAP service.)

You will also need be running with access to suitable Kerberos credentials (eg by running kinit as described in the introductory documentation above).

Sample Perl code to bind to the Oak LDAP service and retrieve information about a user:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    # Need Net::LDAP 0.37 or above
    use Net::LDAP;
    # Replace Perl with Cyrus below to use Authen::SASL::Cyrus
    use Authen::SASL qw( Perl );
    use Readonly;
    use Net::hostent;
    
    Readonly my $base => 'ou=people,dc=oak,dc=ox,dc=ac,dc=uk';
    Readonly my $cafile =>
      '/etc/ssl/certs/ca-certificates.crt';
    
    my $sasl = Authen::SASL->new( mechanism => 'GSSAPI' );

    my $ldap = Net::LDAP->new(
        'ldap.oak.ox.ac.uk',
        onerror               => 'die',
        multihomed            => 1
    );

    $ldap->start_tls( verify => 'require', cafile => $cafile );
    # Newer Kerberos/GSSAPI libraries must be told to perform
    # reverse DNS lookups to get the correct service name
    # when using round-robin DNS.
    #
    # Older clients can replace the next line with:
    #
    #  $ldap->bind( sasl => $sasl );
    #
    $ldap->bind( sasl => $sasl, sasl_host => 0 );
    
    my $search = $ldap->search( base => $base, filter => '(sn=hargreaves)' );
    
    foreach my $entry ( $search->entries ) {
        $entry->dump;
    }

Note that, for Perl, we recommend the use of TLS rather than SSL, (ldap:// rather than ldaps://) since IO::Socket::SSL does not support round-robin addresses correctly.

The instructions in this section assume that you have configured your system according to Common Client Configuration above.

Install PHP support for SASL and LDAP. On Debian, these are provided by the packages php5-sasl and php5-ldap.

You will also need to be running with access to the kerberos credentials (eg by running kinit as described in the introductory documentation above).

If running with a web server, you could use k5start to maintain a credentials cache separately, and set the KRB5CCNAME environment variable in the PHP code.

Sample code:

    #!/usr/bin/php
    <?php
    $base = 'ou=people,dc=oak,dc=ox,dc=ac,dc=uk';
    $ldap = false;
    $ldap = ldap_connect('ldaps://ldap.oak.ox.ac.uk');
    if ( $ldap === false ) {
        print "Could not contact LDAP server\n";
        die;
    }
    ldap_set_option($ldap,LDAP_OPT_PROTOCOL_VERSION,3);
    putenv("KRB5CCNAME=/PATH/TO/YOUR/service_ccache");
    $ldap_bind_result = ldap_sasl_bind($ldap, NULL, NULL, 'GSSAPI');
    if ( $ldap_bind_result === false ) {
        print "Could not bind to LDAP server\n";
        die;
    }
    $search = ldap_search($ldap, $base, '(sn=hargreaves)');
    if ($search) {
        $entries = ldap_get_entries($ldap,$search);
        for($i=0; $i < $entries["count"];$i++) {
            print "dn is: " . $entries[$i]["dn"] . "\n";
            print "first cn entry is: " . $entries[$i]["cn"][0] . "\n";
            print "first email is: " . $entries[$i]["mail"][0] . "\n";
        }
    }
    ?>

Note that PHP's ldap_get_entries function returns an associative array where the LDAP attributes are given in lower case. For example, the LDAP attribute givenName is obtained using

    $entries[$i]["givenname"][0]

rather than

    $entries[$i]["givenName"][0]

The instructions in this section assume that you have configured your system according to Common Client Configuration above.

You will need python-ldap (on Debian-based systems, aptitude install python-ldap should be sufficient).

You will also need to be running with access to Kerberos credentials (eg by running kinit as described in the introductory documentation above, or by setting the KRB5CCNAME environment variable to point to a suitable credentials cache).

Sample code:

   #!/usr/bin/python
   
   import ldap, ldap.sasl, sys, pprint
   
   try:
     auth = ldap.sasl.gssapi("")
     oakldap = ldap.initialize("ldap://ldap.oak.ox.ac.uk:389")
     oakldap.start_tls_s()
     oakldap.sasl_interactive_bind_s("",auth)
     results = oakldap.search_s( "ou=people,dc=oak,dc=ox,dc=ac,dc=uk",
                                 ldap.SCOPE_SUBTREE,
                                 "(sn=Howes)" )
   except ldap.LDAPError, error:
     print "LDAP error: %s" % error
     sys.exit()
   
   pp = pprint.PrettyPrinter()
   pp.pprint(results)

Example JAAS configuration:

OakGSSAPI {
    com.sun.security.auth.module.Krb5LoginModule required 
        keyTab="conf/keytab"
        useKeyTab=true
        doNotPrompt=true
        principal="oak-ldap/HOSTNAME@OX.AC.UK"
        debug=TRUE;
};

Example Java VM Invocation Arguments:

java -Djava.security.auth.login.config=conf/jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf

Example code for querying Oak LDAP:

import java.security.PrivilegedAction;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;


public class LdapGssapi {

    /**
     * @param args
     */
    public static void main(String[] args) {

        try {

            LoginContext lc = new LoginContext("OakGSSAPI");
            lc.login();

            Subject.doAs(lc.getSubject(), new PrivilegedAction() {

                public Object run() {

                    // Set up environment for creating initial context
                    Hashtable env = new Hashtable(3);

                    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");

                    // Must use fully qualified hostname
                    env.put(Context.PROVIDER_URL, "ldaps://ldap.oak.ox.ac.uk");

                    // Request the use of the "GSSAPI" SASL mechanism
                    // Authenticate by using already established Kerberos credentials
                    env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");

                    try {
                        /* Create initial context */
                        DirContext ctx = new InitialDirContext(env);

                        NamingEnumeration units = ctx.list("ou=units,dc=oak,dc=ox,dc=ac,dc=uk");

                        while(units.hasMore()) {
                            System.out.println(units.next());
                        }

                        // Close the context when we're done
                        ctx.close();
                    } catch (NamingException e) {
                        System.err.println("LDAP exception: " + e.getMessage());
                    }


                    return null;

                }

            });

        } catch (LoginException e) {
            System.err.println("Login exception: " + e.getMessage());
        }

    }

}

The following references may be useful

When using GSSAPI or LDAP over SSL pooling has to be done manually.

Please note that JLDAP does not have support for GSSAPI and is therefore not suitable for use with Oak LDAP.

Warning: mod_webauthldap is deprecated

mod_webauthldap is no longer supported by its creator, Stanford University, or by the University of Oxford. We recommend that you move to SAML-based authorisation.

 

Lookup a person by Oxford SSO / username

Perform an LDAP search with a base of ou=people,dc=oak,dc=ox,dc=ac,dc=uk and a filter of krbPrincipalName=<USERNAME>@OX.AC.UK,cn=OX.AC.UK,cn=KerberosRealms,dc=oak,dc=ox,dc=ac,dc=uk.

Lookup a person by oakPersonID

You should do an LDAP search with a base of ou=people,dc=oak,dc=ox,dc=ac,dc=uk and a filter of oakPersonID=<ID>.

You should not do an LDAP search with a base of oakPrimaryPersonID=<ID>,ou=people,dc=oak,dc=ox,dc=ac,dc=uk. This is because in some cases a person may have multiple oakPersonIDs. Only one of these will be present in the distinguished name of the person's entry as the oakPrimaryPersonID.

Lookup a person by University Card barcode

If the card reader you're using reads the whole barcode including the check digit, then perform an LDAP search with a base of ou=people,dc=oak,dc=ox,dc=ac,dc=uk and a filter of oakUniversityBarcodeFull=BARCODE. Otherwise, use the oakUniversityBarcode attribute instead.

Authorise based on membership of the University

To query whether someone is a member of the University, perform an LDAP compare query to compare the eduPersonAffiliation attribute of the person's entry to the string member.

Authorise based on membership of a particular unit: via person

Perform an LDAP compare query to compare the eduPersonOrgUnitDN attribute on the person's entry with the known distinguished name of the unit's entry. For example, to see whether person 38463 is a member of IT Services, one would perform an LDAP compare to ask whether the eduPersonOrgUnitDN attribute of oakPrimaryPersonID=38463,ou=people,dc=oak,dc=ox,dc=ac,dc=uk has a value of oakUnitCode=itserv,ou=units,dc=oak,dc=ox,dc=ac,dc=uk.

Authorise based on membership of a particular unit: via unit

Equally valid is to perform an LDAP compare query to compare the member attribute on the unit's entry with the known distinguished name of the person's entry. Using the same example as above, one would perform an LDAP compare to ask whether the member attribute of oakUnitCode=itserv,ou=units,dc=oak,dc=ox,dc=ac,dc=uk has a value of oakPrimaryPersonID=38463,ou=people,dc=oak,dc=ox,dc=ac,dc=uk

Authorise based on ITSS status

Perform an LDAP compare query to compare the member attribute on the oakGN=ITSS,ou=oucscentral,dc=oak,dc=ox,dc=ac,dc=uk entry with the known distinguished name of the person's entry

Authorise based on ITSS status at a particular unit

Check the oakGN=ITSS,oakUnitCode=<CODE>,ou=units,dc=oak,dc=ox,dc=ac,dc=uk group for the unit of interest.

Find all units for which a person is ITSS

Query the person's oakITSSFor attribute.

Display someone's name

Some applications need to display a person's name, for example in a welcome message. The correct attribute to use for this is displayName.

Keep persistent references to a person in your application

You should use oakPrimaryPersonID or oakPersonID for this. None of the other unique attributes are guaranteed to be present on every person entry.

You should not treat oakPrimaryPrincipal as a persistent reference to a person; principal names may be used to store persistent references to particular principals, but this is different from treating oakPrimaryPrincipal as a persistent reference to a person.

If your query returns more than a few hundred entries, throughput will be improved by using paged results, which is a feature of the LDAP protocol.

Example: use the ldapsearch option -E pr=1000/noprompt for paged results with 1000 entries per page.

Oak LDAP is normally accessible via four IP addresses spread across two or more data centres (DNS records for ldap.oak.ox.ac.uk contain current details).

In order to take advantage of the resilience offered, clients need to implement these related behaviours:

  • If a node refuses the connection, or if the initial connection fails due to a timeout or any other reason, try connecting to a different node from the pool. Don't give up until all nodes in the pool have been tried
  • If the node you're connected to closes the connection, or the connection breaks or expires for other reasons, open a new connection to a node currently in the pool (taking care to expire any cached DNS responses according to their TTLs), and reissue any incomplete queries

The exact way to achieve this differs from client to client. Clients not implementing the above behaviours will still work properly a lot of the time, but will not exhibit continuous operation when individual nodes become unavailable, for example due to maintenance operations or component failures.

Get support


Local IT support provides your first line of on-the-spot help

FIND MY LOCAL IT TEAM

 

Common requests and fault reports can be logged using self-service

   USE IT SELF SERVICE      

   LOG A SUPPORT CALL     

VIEW MY SUPPORT CALLS  

 

The Central IT Service Desk is available 24x7 on +44 1865 6 12345

If you do not have access to your Single Sign-On, you can use this form to contact the Service Desk