Understanding SAML attributes - OIDC claims mapping, when using PhenixID Authentication Services as OP/SAML-SP bridge
This document describes how the mapping between SAML attributes and OIDC claims are made when PhenixID Authentication Services is used as an OpenID Connect Provider with a SAML SP as authorization method (this is the result when adding a provider through Scenarios->OIDC->SAML Identity Provider).
This document also describes how to map the flags indicating user authentication strength:
- SAML authnContextClassRefContext tag to OIDC amr claim
Incoming SAML attributes to session properties
The incoming SAML attributes will be added to the PhenixID Authentication Services session. The session property name will be the same as the saml attribute name. The session user_id will be set to the NameID value.
Example:
SAML Assertion extract:
<saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">john.dole</saml2:NameID>
.
.
.
<saml2:AttributeStatement>
<saml2:Attribute Name="firstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">John</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="LastName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">Dole</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">[email protected]</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="roles" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">sales_guy</saml2:AttributeValue>
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">market_man</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
After the SAML response consumption, the PhenixID Authentication Services session will contain these properties:
- user_id = john.dole
- firstName = John
- LastName = Dole
- mail = [email protected]
- roles = [sales_guy,market_man]
Incoming authnContextClassRef to session
The authnContextClassRef value from the SAML assertion will be stored in the session property authncontextclassref.
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:SoftwarePKI</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
Session properties to OIDC claims
id_token claims population
The id_token claims population is performed using the GenerateJWTTokenValve in the execution flow of the OpenID Connect Provider. Populate claims using session property expansion, based on the session properties in the previous step.
(Session property expansion only works on single values. For multi-values (for example roles in the above example), a supporting valve must be added to the flow prior to generating the JWT id_token. )
In this example the JWT is populated according to the session values populated above.
id_token amr claims population
Prepare amr value
The amr claim value is of the type array. This mapping table displays how the value mapping should be performed, based on the most common authentication methods.
(If the authnContextClassRef value you are looking for is not present in the table below, the proper amr values to map the value against can be found here.)
(Custom authnContextClassRef values, used in some custom federations, are not present in this list. Value-mapping in such federations is feasible but it is up to the administrator to decide on proper amr values.)
SAML authnContextClassRef value | OIDC amr value |
---|---|
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport |
["pwd"] |
urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorContract |
["otp","mfa"] |
urn:oasis:names:tc:SAML:2.0:ac:classes:XMLDSig |
[“swk","mfa"] |
urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient |
[“swk","mfa"] |
urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos |
[“wia” |
urn:oasis:names:tc:SAML:2.0:ac:classes:SmartcardPKI |
["sc","mfa"] |
- Login to configuration manager
- Find the OP config (Scenarios->OIDC)
- Click Execution flow
- Expand the Token Endpoint.
- Add a PropertyFromSessionToItem valve with source = authncontextclassref.
- Place it below ItemCreateValve
- Add a PropertyValueMapping valve with source = authncontextclassref and a mapping table string = urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient|swk,urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport|pwd,urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos|wia,urn:oasis:names:tc:SAML:2.0:ac:classes:SmartcardPKI|sc,
urn:oasis:names:tc:SAML:2.0:ac:classes:XMLDSig|swk,urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorContract|otp
(The mapping table string is based on the values in the table above. Please add mapping if the desired authncontextclassref-amr value is missing from the string)
- Place the valve below the newly added PropertyFromSessionToItem valve.
- Add a PropertyAddValve valve with name = authncontextclassref, value = mfa and a skip_if-expression = flow.getPropertyValue('authncontextclassref', '').equals('pwd') || flow.getPropertyValue('authncontextclassref', '').equals('wia')
- Place the valve below the newly added PropertyValueMapping valve.
- Add a PropertyJoinValve with source = authncontextclassref and separator = **
- Place the valve below the newly added PropertyAddValve valve
- Click Save
- Expand the PropertyJoinValve and click Advanced.
- Copy the id value.
- Click on the top Advanced tab
- Click on the pen to the right of Pipe valves
- Search for the id to locate the valve.
- Change to separator = \",\"
- Click Stage changes and Commit changes
Set amr value in id_token
- Go to Scenarios->OIDC->Your OP
- Click Execution Flow
- Click Token Endpoint
- Expand the GenerateJWTTokenVavle
- Click Advanced
- Copy the ID
- Click on the top Advanced tab
- Click on the pen to the right of Pipe valves
- Search for the id to locate the valve.
- In the tokenattributes part of the configuration, locate the amr object.
- Change value = [\"{{item.authncontextclassref}}\"] and add type=array
- Click Stage changes and commit changes
UserInfo claims population
When UserInfo (optional) has been added to the OpenID Connect Provider, the userinfo endpoint will point to a pipe that will add claims to the response using PropertyAddValve.
This pipe example populates and returns the same claims as above.
{
"id": "userinfo",
"valves": [
{
"name": "ItemCreateValve",
"config": {
"dest_id": "userinfo_props"
}
},
{
"name": "PropertyAddValve",
"config": {
"name": "authorization",
"value": "{{request.Authorization}}"
}
},
{
"name": "PropertyReplaceValve",
"config": {
"source": "authorization",
"dest": "access_token",
"token": "Bearer ",
"replacement": ""
}
},
{
"name": "SessionResolveValve",
"config": {
"alias": "{{item.access_token}}",
"require_session": "true",
"require_auth_session": "false"
}
},
{
"name": "PropertyAddValve",
"config": {
"name": "sub",
"value": "{{session.user_id}}"
}
},
{
"name": "PropertyAddValve",
"config": {
"name": "given_name",
"value": "{{session.firstName}}"
}
},
{
"name": "PropertyAddValve",
"config": {
"name": "family_name",
"value": "{{session.LastName}}"
}
},
{
"name": "PropertyAddValve",
"config": {
"name": "email",
"value": "{{session.mail}}"
}
},
{
"name": "PropertyFromSessionToItem",
"config": {
"source": "roles"
}
},
{
"name": "PropertyRenameValve",
"config": {
"source": "roles",
"dest": "role"
}
},
{
"name": "PropertyRemoveValve",
"config": {
"name":"access_token,authorization"
}
}
],
"created": "2017-11-13T09:53:46.595Z"
}
NB! The amr claim is not part of UserInfo.