kuleuven/authentication-bundle

Symfony3 Bundle for KU Leuven Shibboleth authentication, with LDAP and Person Data API integration

0.2.4 2016-09-14 12:15 UTC

README

This bundle adds a shibboleth authentication firewall to your Symfony3 project.

SensioLabsInsight Build Status Code Coverage Scrutinizer Code Quality

Latest Stable Version Dependency Status Latest Unstable Version Dependency Status

Installation

Download the Bundle

Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:

$ composer require kuleuven/authentication-bundle

This command requires you to have Composer installed globally, as explained in the installation chapter of the Composer documentation.

Enable the Bundle

Then, enable the bundle by adding it to the list of registered bundles in the app/AppKernel.php file of your project:

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...

            new Kuleuven\AuthenticationBundle\KuleuvenAuthenticationBundle(),
        );

        // ...
    }

    // ...
}

Shibboleth

Setup the Symfony firewall

# app/config/security.yml
security:
    ...
    providers:
        ...
        kuleuven_authentication.service.shibboleth_user_provider:
            id: kuleuven_authentication.service.shibboleth_user_provider
    ...
    firewalls:
        ...
        kuleuven_authentication:
            pattern: ^/secured # change this to your application's secured path
            stateless: true
            kuleuven_authentication: ~
            logout:
                path: /logout
                success_handler: kuleuven_authentication.security.http.logout.handler

By default, the bundle will use a default Shibboleth user provider. This is an in-memory user provider that will get your user on the fly, based on the server attributes.

You can setup the firewall to check specific attribute requirements before authentication. By default, this is set to the Shib-Identity-Provider needed to be 'urn:mace:kuleuven.be:kulassoc:kuleuven.be'.

# app/config/config.yml
...
kuleuven_authentication:
    authentication_attribute_requirements: { Shib-Identity-Provider: 'urn:mace:kuleuven.be:kulassoc:kuleuven.be' }

Setup Shibboleth in the .htaccess file in your public folder

# web/.htaccess
# Shibboleth
<IfModule mod_shib>
    AuthType shibboleth
    Require shibboleth
    ShibRequireSession On
</IfModule>

Change Shibboleth Service Provider settings (optional)

# app/config/config.yml
...
kuleuven_authentication:
    shibboleth_is_secured_handler: true
    shibboleth_handler_path: /Shibboleth.sso
    shibboleth_status_path: /Status
    shibboleth_session_login_path: /Login
    shibboleth_session_logout_path: /Logout
    shibboleth_session_logout_target: ~
    shibboleth_session_overview_path: /Session
    shibboleth_username_attribute: Shib-Person-uid
    shibboleth_authenticated_attribute: Shib-Identity-Provider
    shibboleth_logout_url_attribute: Shib-logoutURL
    shibboleth_default_charset: ISO-8859-1

Overwrite Shibboleth server attributes (optional)

The Shibboleth firewall will by default use the server environment. To be succesfully authenticated, at least two attributes should be present:

  • the 'Shib-Identity-Provider' attribute will tell you which provider provided your identity
  • the 'Shib-Person-uid' attribute contains your identity's uid

If you don't have Shibboleth running locally, you could add these attributes manually to your server environment, or add them to the $_SERVER array in for example your app_dev.php.

####Parameter injector

This bundle however lets you overwrite any attribute from within your parameters.yml, through the '\Kuleuven\AuthenticationBundle\Service\ParameterAttributesProvider' service that uses the 'authentication_attribute_overwrites' parameter to inject an array of server attributes.

By default this feature is disabled, so you have to explicitly enable it.

# app/config/config_dev.yml
kuleuven_authentication:
    ...
    authentication_attribute_overwrites_enabled: true

Now you can add your overwrites to your parameters.yml.

# app/config/parameters.yml
parameters:
    ...
    authentication_attribute_overwrites:
        Shib-Identity-Provider: 'urn:mace:kuleuven.be:kulassoc:kuleuven.be'
        Shib-Person-uid: '<(string)your-uid>'

The parameter injector will always overwrite any other server attributes, unless you would overwrite the priority of the service. By default the priority is set to -INF.

####Header injector

You could also overwrite specific attributes in your request, through the '\Kuleuven\AuthenticationBundle\Service\HeaderAttributesProvider' service that uses the symfony request headers to inject an array of server attributes.

By default this feature is disabled, so you have to explicitly enable it.

# app/config/config_dev.yml
kuleuven_authentication:
    ...
    authentication_attribute_headers_enabled: true

Now you can use something like Requestly to overwrite attributes in your application, by sending them as headers with your request.

The header injector will always overwrite any other server attributes, unless you would overwrite the priority of the service. By default the priority is set to -INF.

####LDAP attributes injector

You can use LDAP to request some of the server attributes from a specific person, through the '\Kuleuven\AuthenticationBundle\Service\LdapAttributesProvider' service that uses the 'authentication_attribute_ldap_filter' parameter to inject an LDAP result array of server attributes.

By default this feature is disabled, so you have to explicitly enable it.

# app/config/config_dev.yml
kuleuven_authentication:
    ...
    authentication_attribute_ldap_enabled: true

Once enabled, you can add your LDAP filter. Make sure the filter is unique enough to only provide one user.

# app/config/parameters.yml
parameters:
    ...
    authentication_attribute_ldap_filter: {uid: '<(string)your-uid>'}

It might be possible that you also need to enable LDAP - if so, jump to the LDAP chapter further down.

####Custom injector

If you want to add other services to populate your server attributes, they should implement '\Kuleuven\AuthenticationBundle\Service\AttributesInjectionProviderInterface', and should be tagged with 'kuleuven_authentication.shibboleth_attributes_injector'.

# app/config/services.yml
    ...
    my_attributes_provider:
        class: "%my_attributes_provider.class%"
        tags:
            - { name: kuleuven_authentication.shibboleth_attributes_injector }

Change the default firewall settings (optional)

For more control, there are two more firewall settings that can be overwritten:

  • the 'provider' value defines the user provider - defaults to "kuleuven_authentication.service.shibboleth_user_provider"
  • the 'default_roles' value defines some default roles - defaults to an empty array
# app/config/security.yml
security:
    ...
    firewalls:
        ...
        kuleuven_authentication:
            ...
            kuleuven_authentication:
                provider: 'kuleuven_authentication.service.shibboleth_user_provider'
                default_roles: ~

Overwrite the attribute definitions

By default, the bundle exposes several Shibboleth attributes through the user token KuleuvenUserToken or the user KuleuvenUser. Attributes can be accessed through getAttribute, getSingleAttribute, getArrayAttribute or hasAttributeValue, with their id or aliases as the argument.

The built-in SP variables are:

Variable Meaning
Shib-Application-ID The applicationId property derived for the request.
Shib-Authentication-Instant The ISO timestamp provided by the IdP indicating the time of authentication.
Shib-Authentication-Method The AuthenticationMethod or value supplied by the IdP, if any.
Shib-AuthnContext-Class The AuthenticationMethod or value supplied by the IdP, if any.
Shib-AuthnContext-Decl The value supplied by the IdP, if any.
Shib-Handler The self-referential base location of the SP's "handlers" for use by applications in requesting login, logout, etc.
Shib-Identity-Provider The entityID of the IdP that authenticated the user associated with the request.
Shib-Session-ID The internal session key assigned to the session associated with the request.

The KU Leuven provides a long list of usable attributes. A non-exhaustive list:

id aliases multivalue
Shib-Application-ID false
Shib-Session-ID false
Shib-Identity-Provider false
Shib-Authentication-Instant false
Shib-Authentication-Method false
Shib-AuthnContext-Class false
Shib-AuthnContext-Decl false
Shib-Handler false
eppn user false
affiliation Shib-EP-ScopedAffiliation, eduPersonScopedAffiliation true
unscoped-affiliation Shib-EP-UnscopedAffiliation, eduPersonAffiliation true
entitlement Shib-EP-Entitlement, eduPersonEntitlement false
targeted-id Shib-TargetedID, eduPersonTargetedID false
persistent-id false
primary-affiliation Shib-EP-PrimaryAffiliation, eduPersonPrimaryAffiliation false
nickname Shib-EP-Nickname, eduPersonNickName false
primary-orgunit-dn Shib-EP-PrimaryOrgUnitDN, eduPersonPrimaryOrgUnitDN false
orgunit-dn Shib-EP-OrgUnitDN, eduPersonOrgUnitDN true
org-dn Shib-EP-OrgDN, eduPersonOrgDN false
cn Shib-Person-commonName false
sn Shib-Person-surname false
givenName Shib-Person-givenName false
mail Shib-Person-mail false
uid Shib-Person-uid false
telephoneNumber Shib-Person-telephoneNumber true
title false
initials ?
description false
carLicense ?
departmentNumber ?
displayName ?
employeeNumber ?
employeeType ?
preferredLanguage ?
manager ?
seeAlso ?
facsimileTelephoneNumber Shib-Person-facsimileTelephoneNumber true
postalAddress Shib-Person-postalAddress true
street ?
postOfficeBox ?
postalCode ?
st ?
l ?
o ?
ou Shib-Person-ou true
businessCategory ?
physicalDeliveryOfficeName ?
roomNumber Shib-Person-roomNumber true
KULluditServer Shib-KUL-luditServer false
KULprimouNumber Shib-KUL-PrimouNumber true
KULouNumber Shib-KUL-ouNumber true
KULtap Shib-KUL-tap false
KULemployeeType Shib-KUL-employeeType true
KULdipl Shib-KUL-dipl true
KULopl Shib-KUL-opl true
KULstamnr Shib-KUL-stamnr false
KULid Shib-KUL-id false
KULlibisnr Shib-KUL-libisnr false
KULstudentType Shib-KUL-studentType true
KULcampus Shib-KUL-campus false
userAppUserID false
syncoreLogonCode false
KULMoreUnifiedUID false
KULCardApplicationId true
KULCardSN true
KULPreferredMail false
KULMainLocation true
KULAssocUCCtag true
KULOfficialGivenName false
logoutURL Shib-logoutURL false
uidToledo Shib-uidToledo false
aid Shib-assoc-aid false
HomeOrganization ?
HomeOrganizationType ?
KULAssocSAPID ?
KULAssocLibisPID ?
KULAssocLibisNbr ?
KULAssocMigrateID ?

You can always extend these definitions by adding definitions into the parameter 'authentication_attribute_definitions'.

LDAP

Change LDAP settings (optional)

If you have your own LDAP credentials, you may use those by setting the LDAP parameters. The default settings however should work as long as you are connected to the KU Leuven network.

# app/config/parameters.yml
parameters:
    ldap_rdn: ''
    ldap_password: ''
    ldap_base: 'ou=people,dc=kuleuven,dc=be'
    ldap_domain: 'ldap.kuleuven.be'
    ldap_port: '389'

Impersonate users (optional)

Through LDAP, we have the possibility to impersonate any KU Leuven member.

Allthough the Shibboleth authentication is stateless itself, for this to work it needs to save a token to the session. You don't need to change the stateless key though, as the Shibboleth authentication will still check the Shibboleth session of the source user to make sure the session stays alive.

To enable this, you need to add an LDAP user provider. However, we also still need our Shibboleth user provider. So let's add a chain_provider, and overwrite the firewall provider. Also add the switch_user attribute, and detect some default_role to check if a user may impersonate.

# app/config/security.yml
security:
    ...
    providers:
       chain_provider:
            chain:
                providers: [kuleuven_authentication.service.shibboleth_user_provider, kuleuven_authentication.service.shibboleth_via_ldap_user_provider]
        kuleuven_authentication.service.shibboleth_user_provider:
            id: kuleuven_authentication.service.shibboleth_user_provider 
        kuleuven_authentication.service.shibboleth_via_ldap_user_provider:
            id: kuleuven_authentication.service.shibboleth_via_ldap_user_provider
    ...
    firewalls:
        ...
        kuleuven_authentication:
            ...
            kuleuven_authentication:
                provider: chain_provider
                default_roles: [ROLE_SHIBBOLETH_AUTHENTICATED]
            switch_user: { role: ROLE_SHIBBOLETH_AUTHENTICATED, parameter: _switch_user }

Typical development setup

Both using the overwrites and LDAP, there is a very easy setup to enable local development without installing Shibboleth.

Enable the overwrites and provide the overwrite for the Shib-Identity-Provider attribute in config_dev.yml. Also enable LDAP in config_dev.yml.

# app/config/config_dev.yml
...
kuleuven_authentication:
    authentication_attribute_overwrites_enabled: true
    authentication_attribute_overwrites: {Shib-Identity-Provider: 'urn:mace:kuleuven.be:kulassoc:kuleuven.be'}
    authentication_attribute_ldap_enabled: true

Add your uid by adding this to your parameters.yml(.dist). It will be ignored in production.

# app/config/parameters.yml.dist
...
parameters:
    authentication_attribute_ldap_filter: {uid: '<(string)your-uid>'}

Extra

There is a default route "/authentication".

Check if you are behind a certain firewall with the FirewallHelper service.

Upcoming

Security

  • Make it possible to add your own attribute-map.xml file (including external url) - downloading in compiler pass?
  • Find a way to detect which fields are multivalue, instead of hard-coding it into the AttributeDefinitionsProvider
  • Add providerKey in token support checks

Logging

  • Use one central proxy logger for the authentication bundle
  • Implement LoggerAware in some extra classes

Data Collector

  • Add authentication (including use_headers), LDAP, PersonDataAPI and impersonation to DataCollector

Switch User

  • Instead of overwriting the switchuser_listener, add a new Security Factory
  • Add KuleuvenSwitchUserToken
  • ShibbolethSwitchUserPersistenceSubscriber should authenticate token in onKernelRequest with ShibbolethAuthenticationProvider

Docker

Extra

  • Send notice if LDAP filter returns more than 1 user
  • Provide examples: how to add an automatic user save on visit

References

Reference Status