Skip to content

Attribute Manipulations

Thijs Kinkhorst edited this page Sep 30, 2024 · 12 revisions

Introduction

Attribute Manipulations allows you to manipulate - per Service Provider - the attributes and their values that are sent to that SP. The following picture explains the typical setup and usage:

Diagram of attribute manipulations in the authentication flow

In the above example a user wants to log in to Google Apps and therefore clicks on Google Apps login; Google Apps makes a SAML2 Authentication Request and sends the user off with it to OpenConext Engine. Engine then does whatever it needs to do to get this user to his/her Identity Provider or IdP - probably showing a WAYF of some sorts - and finally sends the user off with a new SAML2 Authentication Request to in this example SURFguest.

The IdP receives the Authentication Request, and does whatever it needs to do to get the user logged in - probably showing a login screen - the user logs in and the IdP creates a SAML2 Response with an assertion. In this assertion are attributes about the user. For example:

  • Name: uid, Value 0: John
  • Name: schacHomeOrganization, Value 0: surfguest.nl
  • Name: groups, Value 0: students, Value 1: members

The IdP then sends the user off back to Engine with this response. Engine processes the response, including:

  • Checking if the response is valid;
  • Provisioning the user in the database, if needed;
  • Obtaining consent from the user to pass these attributes to the SP;
  • Setting the NameID.

And finally, when Engine is done with the response and sends it to the SP, it calls the Attribute Manipulations component for last minute modifications. After these modifications are done, Engine is finished and sends the user with the (changed) response to Google Apps.

Attribute Manipulations have been developed for several Service Providers; the most notable being Google Apps to manipulate the subjectId.

See the Create an Attribute Manipulation section below for more information on creating attribute manipulations.

General working of Attribute Manipulations

Engine can manipulate attributes in both IdP-OpenConext and OpenConext-SP flows. It is not common to perform Attribute Manipulations, but in rare cases (e.g.,Google Apps) it is required.

IdP-OpenConext

The Attribute Manipulation is performed by Engine just after a successful authentication and before the ACL and validation of the IDP's response. So in the following order:

  1. Removal of the OID attributes (rename to named attributes)
  2. AttributeManipulations
  3. ValidateRequiredAttributes

The order is important and gives the following restrictions and possibilities:

  • It is not possible to manipulate the attributes with the OID variant (the OID variants are converted to their named variant)
  • It is possible to manipulate to create / rename /modify the attributes provided by the IdP to successfully meet the OpenConext attribute requirements (UID + schacHomeOrganization)
  • All attributes can be manipulated

This allows for instance the possibility to add static attributes like schacHomeOrganization. It is also possible to adjust/remove attributes, like removal of extra email-addresses or Diacritics.

Although it is possible to manipulate the nameID, it is highly recommended NOT to manipulate it here (if needed perform this manipulation on the OpenConext-SP side)

OpenConext-SP

The Attribute Manipulation is performed just after applying the Attribute Release Policy (ARP) and before creating a new NameID (if needed) and/or add OID variants of the attributes. So in the following order:

  1. AttributeReleasePolicy;
  2. AttributeManipulations;
  3. SetNameId (if transient or persistent);
  4. Add OID variants of attribute names.

The order is important and gives the following restrictions and possibilities:

  • The ARP must be set to allow the attributes needed for the manipulation.

(At the end of the manipulation it is possible to remove attributes when the needed attributes may not be provided to the SP)

  • When manipulating the NameID ($subjectId) you need to set NameIDFormat to Unspecified (in the Metadata-tab).
  • It is not possible to manipulate the attributes with the OID variant (the OID variants are added after the manipulation).

Creating an Attribute Manipulation

Attribute Manipulations can be configured within Manage. Under an IdP or SP, see the manipulation tab.

Changing the released attributes

You can read incoming attributes from the $attributes array and change the contents of this array to influence the outgoing attributes.

An example that changes the names of some attributes:

$attr_gn       = 'urn:mace:dir:attribute-def:givenName';
$attr_sn       = 'urn:mace:dir:attribute-def:sn';
$attr_mail     = 'urn:mace:dir:attribute-def:mail';

# attributes to let through (ARP)
$requiredAttributes = [
  'FirstName',
  'LastName',
  'Email'
];

if (isset($attributes) and ($attributes !== FALSE)) {
    if (!empty($attributes[$attr_gn])) {
        $attributes['FirstName'] = $attributes[$attr_gn];
    }
    if (!empty($attributes[$attr_sn])) {
        $attributes['LastName'] = $attributes[$attr_sn];
    }
    if (!empty($attributes[$attr_mail])) {
        $attributes['Email'] = $attributes[$attr_mail];
    }
}

# Remove all unrequired attributes (the ones with the original names)
foreach ($attributes as $k => $v) {
  if (!in_array($k, $requiredAttributes, true)) {
    unset($attributes[$k]);
  }
}

Influencing the NameID

It is possible to change the released SAML Subject (NameID) of the user. You can read $subjectId to get the incoming nameId and set $subjectId to determine the outgoing NameID. If you want to be able to set the outgoing NameId in this way, the NameIdFormat of the SP must be set to unspecified.

Example that reads attributes and sets the NameID to a combination of attributes, when present:

if (!empty($attributes['urn:mace:dir:attribute-def:uid'][0]) and 
    !empty($attributes['urn:mace:terena.org:attribute-def:schacHomeOrganization'][0])) {
        $subjectId = $attributes['urn:mace:dir:attribute-def:uid'][0] . "_" .
            $attributes['urn:mace:terena.org:attribute-def:schacHomeOrganization'][0];
}

If you want to do more than set a new value and keep the format at 'unspecified', you can also override the entire NameId:

if (!empty($attributes['urn:mace:dir:attribute-def:mail'][0])) {
    $response['__']['CustomNameId'] = [
        'Format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
        'Value' => $attributes['urn:mace:dir:attribute-def:mail'][0],
    ];
}

Custom error message

You can generate a custom EB error screen from within the attribute manipulation. An example that throws a custom error text to the user:

    $allowed = false;
    if (array_key_exists('urn:mace:dir:attribute-def:eduPersonAffiliation', $attributes)) {
        $values = ['student', 'employee', 'affiliate'];
        foreach ($attributes['urn:mace:dir:attribute-def:eduPersonAffiliation'] as $v) {
            if (in_array($v, $values, true)) {
                $allowed = true;
                break;
            }
         }
    }

    if (!$allowed) {
            $amFout = new EngineBlock_Attributes_Manipulator_CustomException("AM_ERROR Authorization Incorrect _ Affilliation Incorrect", EngineBlock_Attributes_Manipulator_CustomException::CODE_NOTICE);
            $amFout->setFeedbackTitle(["nl" => "Autorisatie Incorrect", "en" => "Authorization Incorrect"]);
            $amFout->setFeedbackDescription([
                "en" => 'This user does not have access to services of OpenConext. ' .
                    'Contact the Example University Netherlands if you think you should have access. ',
                "nl" => 'Deze gebruikersnaam heeft geen toegang tot de diensten van OpenConext. ' .
                    'Bent u van mening dat u wel toegang zou moeten hebben, geef dit dan door aan de Voorbeeld Universiteit Nederland. ',
                    ]);
            throw $amFout;
    }

Using request and response information and entity metadata fields

The entire original SAML AuthnRequest and the already built SAML Response are available. You can read information from $requestObj and $responseObj (read-only objects) for input into your manipulation. Also the $entityId of the current entity is available. The read-only arrays $idpMetadata and $spMetadata contain the metadata fields that EB knows about from the current involved entities.

Manipulating the response

For advanced, but possibly more fragile use cases that are not covered by changing the NameId or released attributes, it's also possible to manipulate elements of the entire prepared SAML Response. The variable $response contains the response as a nested array structure. If you need to change e.g. the AuthnContextClassRef:

$response['saml:Assertion']['saml:AuthnStatement']['saml:AuthnContext']['saml:AuthnContextClassRef']['__v'] = 'urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified';

Manipulation notes

In Manage there's also a "Manipulation notes" tab. The notes for an Attribute Manipulation are included in the MetaData and displayed in the Dashboard application. These notes are intended to give a human-readable description what happens to the IdP administrators that use the Dashboard. Please explain in non-technical terminology what is being achieved in the manipulation.