SungHoon_Kim

Using Persist Attributes

Blog Post created by SungHoon_Kim Employee on Jan 4, 2017

When you are federating, you receive assertion attributes and may want to store them for use later on.

 

For example, in case if you have 2 federation partnerships back to back, you might want to store the assertion attributes and forward those persisted attributes to the other federation partnership.

 

Partnership1: <IDP> ==> [You are SP] Persist Attributes

Partnership2: [You are IDP] Use Session Variables ==> <SP> 

 

Let's say in the Partnership1 you received <membership>VIP</membership> in the assertion attributes.

You then want to send this over to the next <SP> in Partnership2.

 

I have the following setup.

http://www.sso.lab is the IDP in the Partnership1.

http://partner.lab is the SP in Partnership1.

then

http://www.partner.lab is the IDP in Partnership2.

http://kimsu05-m4600.ca.com is the SP in Partnership2.

 

 

 

Configuration at the http://www.sso.lab, the IDP in Partnership1.

I am adding "TEST1" with "samaccountname" attribute value.

I am also adding "TESTEMPTY" with "assistant" attribute value, note that this attribute value is empty.

 

Configuration at the http://www.partner.lab, the SP in Partnershp1.

You must check "Persist Authentication Session Variables".

This includes all the assertion attributes so "TEST1" and "TESTEMPTY" both will be stored.

 

And at this point, if the user successfully federated, you can retrieve those persisted attributes from web agent HTTP response so your applications can consume them.

You can tie this response to OnAccessAccept and you will see "HTTP_TESTING" header with the value from TEST1 persisted attribute.

 

 

Now, moving on to the second partnership.

Configuration at the http://www.partner.lab, the IDP in Partnershp2.

You can specify a different Assertion Attribute Name or you can use the same name.

At the "Type" select "Session Attribute".

At the "Value", specify the Persisted Attribute Name.

 

Configuration at http://kimsu05-m4600.ca.com, SP at Partnership2.

 

Again, it is simply checking the "Persist Authentication Session Variables".

It is then up to you to fetch and set the HTTP response headers as needed.

 

Following is the Assertion generated from Partnership1.

Assertion from Partnership1
[01/04/2017][11:03:40][9132][152ce922-211cce88-0a9a6cf2-97c84e80-00fa9029-155][AssertionGenerator.java][invoke][][][][][][][][AssertionHandler process() succeeds, it returns:
<Response Destination="https://www.partner.lab/affwebservices/public/saml2assertionconsumer" ID="_e1f5270277496e84413d786f76e420d66c64" IssueInstant="2017-01-04T00:03:40Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:protocol">
<ns1:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:ns1="urn:oasis:names:tc:SAML:2.0:assertion">http://www.sso.lab</ns1:Issuer>
<Status>
<StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</Status>
<ns2:Assertion ID="_3089821f8163be67ea0a3a2a89233afd1961" IssueInstant="2017-01-04T00:03:40Z" Version="2.0" xmlns:ns2="urn:oasis:names:tc:SAML:2.0:assertion">
<ns2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.sso.lab</ns2:Issuer>
<ns2:Subject>
<ns2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user1@sso.lab</ns2:NameID>
<ns2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<ns2:SubjectConfirmationData NotOnOrAfter="2017-01-04T00:05:10Z" Recipient="https://www.partner.lab/affwebservices/public/saml2assertionconsumer"/>
</ns2:SubjectConfirmation>
</ns2:Subject>
<ns2:Conditions NotBefore="2017-01-04T00:03:10Z" NotOnOrAfter="2017-01-04T00:05:10Z">
<ns2:AudienceRestriction>
<ns2:Audience>http://www.partner.lab</ns2:Audience>
</ns2:AudienceRestriction>
</ns2:Conditions>
<ns2:AuthnStatement AuthnInstant="2017-01-04T00:03:40Z" SessionIndex="leaNPSlcI9vR8NWiKBq4sBmjD0c=mEGH+g==" SessionNotOnOrAfter="2017-01-04T00:05:10Z">
<ns2:AuthnContext>
<ns2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</ns2:AuthnContextClassRef>
</ns2:AuthnContext>
</ns2:AuthnStatement>
<ns2:AttributeStatement>
<ns2:Attribute Name="TEST1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<ns2:AttributeValue>user1</ns2:AttributeValue>
</ns2:Attribute>
<ns2:Attribute Name="TESTEMPTY" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<ns2:AttributeValue/>
</ns2:Attribute>
</ns2:AttributeStatement>
</ns2:Assertion>
</Response>
]

 

Following is the Assertion generated from Partnership2.

Assertion from Partnership2
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][SAMLSPEntitlementGenerator.java][SAMLSPEntitlementGenerator()][][][][][][][][Generated Entitlement List
]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][SAMLSPEntitlementGenerator.java][generateValue][][][][][][][][
param1 : SM_SESSIONCTXVAR:TEST1
sessionID: null]
[01/04/2017][11:05:08][9132][][SmAuthUser.cpp:2213][GetPropIndex][][][][][][][][Processing Attribute [Property = SM_SESSIONCTXVAR:TEST1] [Trim Property = SM_SESSIONCTXVAR:TEST1] [Separator = ^]]
[01/04/2017][11:05:08][9132][][SmSSProvider.cpp:961][CSmSSProvider::GetVariable][][][][][WXgQaVaclA3UFalgTEGwEodrVk8=][][][Leave function CSmSSProvider::GetVariable]
[01/04/2017][11:05:08][9132][][SmSSProvider.cpp:1104][CSmSSProvider::Free][][][][][][][][Enter function CSmSSProvider::Free]
[01/04/2017][11:05:08][9132][][SmSSProvider.cpp:1133][CSmSSProvider::Free][][][][][][][][Leave function CSmSSProvider::Free]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][SAMLSPEntitlementGenerator.java][generateValue][][][][][][][][Entitlement: NameAttrFormat = unspecified, Encrypt = false, Mode = User, TEST2 = NOT PRINTABLE]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][SAMLSPEntitlementGenerator.java][generateValue][][][][][][][][
param1 : SM_SESSIONCTXVAR:TESTEMPTY
sessionID: null]
[01/04/2017][11:05:08][9132][][SmAuthUser.cpp:2213][GetPropIndex][][][][][][][][Processing Attribute [Property = SM_SESSIONCTXVAR:TESTEMPTY] [Trim Property = SM_SESSIONCTXVAR:TESTEMPTY] [Separator = ^]]
[01/04/2017][11:05:08][9132][][SmSSProvider.cpp:961][CSmSSProvider::GetVariable][][][][][WXgQaVaclA3UFalgTEGwEodrVk8=][][][Leave function CSmSSProvider::GetVariable]
[01/04/2017][11:05:08][9132][][SmSSProvider.cpp:1104][CSmSSProvider::Free][][][][][][][][Enter function CSmSSProvider::Free]
[01/04/2017][11:05:08][9132][][SmSSProvider.cpp:1133][CSmSSProvider::Free][][][][][][][][Leave function CSmSSProvider::Free]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][SAMLSPEntitlementGenerator.java][generateValue][][][][][][][][Entitlement: NameAttrFormat = unspecified, Encrypt = false, Mode = User, TESTEMPTY = NOT PRINTABLE]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][AuthnRequestProtocol.java][generateAttributeStatement][][][][][][][][Generating SAML Assertion AttributeStatement...]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][AuthnRequestProtocol.java][processAttributes][][][][][][][][Raw Value: user1]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][AuthnRequestProtocol.java][generateAttributeStatement][][][][][][][][Require to Encrypt Attribute: false]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][AuthnRequestProtocol.java][processAttributes][][][][][][][][Raw Value: NULL]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][AuthnRequestProtocol.java][generateAttributeStatement][][][][][][][][Require to Encrypt Attribute: false]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][AuthnRequestProtocol.java][processRequest][][][][][][][][The authentication request is processed successfully.]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][AuthnRequestProtocol.java][processRequest][][][][][][][][Policy server generates the saml2 assertion [CHECKPOINT = SSOSAML2_PSGENERATEASSERTION_RSP]]
[01/04/2017][11:05:08][9132][be1edeee-41504703-4478120d-7650731f-8a7b9726-d3f][AssertionGenerator.java][invoke][][][][][][][][AssertionHandler process() succeeds, it returns:
<Response Destination="http://kimsu05-m4600.ca.com/affwebservices/public/saml2assertionconsumer" ID="_d11c55bef5750b1a86f7963ae538e1fe107c" IssueInstant="2017-01-04T00:05:08Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:protocol">
<ns1:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:ns1="urn:oasis:names:tc:SAML:2.0:assertion">http://www.partner.lab</ns1:Issuer>
<Status>
<StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</Status>
<ns2:Assertion ID="_810f8903b8c757a278fc0f2bd4ab22aaee58" IssueInstant="2017-01-04T00:05:08Z" Version="2.0" xmlns:ns2="urn:oasis:names:tc:SAML:2.0:assertion">
<ns2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.partner.lab</ns2:Issuer>
<ns2:Subject>
<ns2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">User1</ns2:NameID>
<ns2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<ns2:SubjectConfirmationData NotOnOrAfter="2017-01-04T00:06:38Z" Recipient="http://kimsu05-m4600.ca.com/affwebservices/public/saml2assertionconsumer"/>
</ns2:SubjectConfirmation>
</ns2:Subject>
<ns2:Conditions NotBefore="2017-01-04T00:04:38Z" NotOnOrAfter="2017-01-04T00:06:38Z">
<ns2:AudienceRestriction>
<ns2:Audience>http://kimsu05-m4600.ca.com</ns2:Audience>
</ns2:AudienceRestriction>
</ns2:Conditions>
<ns2:AuthnStatement AuthnInstant="2017-01-04T00:03:40Z" SessionIndex="WXgQaVaclA3UFalgTEGwEodrVk8=xKoP3w==" SessionNotOnOrAfter="2017-01-04T00:06:38Z">
<ns2:AuthnContext>
<ns2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</ns2:AuthnContextClassRef>
</ns2:AuthnContext>
</ns2:AuthnStatement>
<ns2:AttributeStatement>
<ns2:Attribute Name="TEST2" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<ns2:AttributeValue>user1</ns2:AttributeValue>
</ns2:Attribute>
<ns2:Attribute Name="TESTEMPTY" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<ns2:AttributeValue>NULL</ns2:AttributeValue>
</ns2:Attribute>
</ns2:AttributeStatement>
</ns2:Assertion>
</Response>
]

 

The reason why I added 2 attributes, one with value and one without, is because there seems to be a design limitation.

When the attributes are persisted in the session store, the schema dictates that it should not be null.

Following is a section from the sm_mssql_ss.sql script.

sm_mssql_ss.sql
CREATE TABLE [ss_sessionvar5] (
                [sessionid] [varchar] (64) NOT NULL ,
                [varname] [varchar] (64) NOT NULL ,
                [varvalue] [varchar] (4000) NOT NULL ,
                [chunkgroupid] [varchar] (256) ,
                [datasize] [int] ,
                PRIMARY KEY CLUSTERED
                (
                                [sessionid],
                                [varname]
                ) ON [PRIMARY] ,
                FOREIGN KEY
                (
                                [sessionid]
                ) REFERENCES [ss_sessionspec5] (
                                [sessionid]
                )
) ON [PRIMARY]
go

 

Even after removing this "NOT NULL" restriction, the <null> value was getting stored as "NULL" string value.

So, it seems it is coded that way and would be a limitation if you wanted to pass on a <null> value via Session Variable(Persist Attributes).

 

You can confirm this from the session store as well.

 

Other than that, I did not see any issue.

Hope this helps.

Outcomes