Symbiote

Engineer the web, together.

Azure Active Directory and SilverStripe

If you're developing webapps for business customers, chances are at some point you'll come across a requirement to provide authentication against Active Directory, Microsoft's domain management system. This used to be a case of figuring out LDAP settings and figuring out all sorts of gnarly LDAP tree queries - now, it's a much simpler OAuth model that doesn't require deepdiving into LDAP. 

Side note - for development, Azure has quite a few always-free services, Active Directory included. Check out https://azure.microsoft.com/en-au/free/free-account-faq/.  

Once you've got an AD account, you'll need to set up a few pieces

Register a new App in your Azure AD; this should be of type Web app / API

From this, you'll need the Application ID, which is the Client ID from oauth's perspective. 

After clicking "Settings", you can create a new Password from the "Keys" section that comes up - this is the oauth "secret" parameter. The name isn't important, just make sure you copy the key down before navigating away

Next, you'll need to set the "Reply URLs". This is how AD knows that the auth request is sending the user back to a known source. 

Lastly, you'll need the Directory ID from the Azure AD properties (this becomes the tenant ID)

SilverStripe configuration

First, add a couple of modules to your project; in composer.json, add to your requirements list

    "bigfork/silverstripe-oauth-login": "dev-master#5cb417589d4b066207d57aa41e63530b1b7a1d2c",
    "thenetworg/oauth2-azure": "~1.3.0"

and run composer update bigfork/silverstripe-oauth-login

Next up, the configuration;

---
Name: azure_auth
---
SilverStripe\Core\Injector\Injector:
  Bigfork\SilverStripeOAuth\Client\Factory\ProviderFactory:
    properties:
      providers:
        'Sharepoint': '%$AzureProvider'
  AzureProvider:
    class: 'TheNetworg\OAuth2\Client\Provider\Azure'
    constructor:
      Options:
        # Taken from the "Application ID" ; Azure AD => App Registrations => {App}
        clientId: 'the-application-id'
        # Create from Azure AD => App registrations => {App} => Settings => Keys 
        clientSecret: 'from the keys section'
        # From Azure AD => Properties => Directory ID
        tenant: 'the azure AD directory id'
        # Add in Azure AD => App registrations => {App} => Reply URLs
        redirectUri: https://myhostname.com.au/oauth/callback/
Bigfork\SilverStripeOAuth\Client\Authenticator\Authenticator:
  providers:
    'Sharepoint': 
      name: 'Sharepoint'
      scopes: ['email profile']

Note: The redirectUri here must match that created in the Reply URLs section above. And while the OAuth module states that it automatically detects this, if you are running on HTTPS it will not correct identify it as such because the URL detection happens before the request object is created by the framework, thus it's unable to correctly determine whether we're on https.

And, to ensure values are properly mapped to the user objects that get created,

---
Name: oauth_properties
---

Bigfork\SilverStripeOAuth\Client\Mapper\GenericMemberMapper:
  mapping:
    'Sharepoint':
      'Email': 'email' 
      'FirstName': 'given_name'
      'Surname': 'family_name'