Authors: Jim Taylor, DECE; Peter Davis, Neustar
This article explains the basics of Security Tokens (SAML assertions) and presents recommended best practices to manage linking (a.k.a. binding).
Access to the Coordinator by a Node on behalf of a user is granted by the user authenticating or linking to their UltraViolet account, after which the Node obtains a Delegation Security Token (DST).
Note: Technically, access is not the same as link. Access is represented by a Delegation Security Token. A link is represented by the UserLinkConsent policy. Historically this was an important difference, but as part of the UltraViolet simplification process, linking was made automatic when a user granted access (the "Link my UltraViolet Library" checkbox was removed from the authenticaion UI), so for most purposes authenticate, link (aka bind), and access mean the same thing.
A Retailer connects with an UltraViolet user in one of four ways:
At the successful end of any of the steps above, the Retailer receives a delegation security token (DST) at the ACS endpoint defined in the Retailer's SAML metadata. The Retailer presents the DST to the Coordinator to perform actions on behalf of the user. The DST typically lasts one year and can be renewed by the Retailer without user intervention. DECE recommends that Retailers implement a background process that renews DSTs with an expiration date less than a month away. If the DST expires, or if the user unlinks at UltraViolet Web Portal or elsewhere, the user will have to relink using option 2, 3, or 4 above before the Retailer can perform an action on behalf of the user. Retailers should check for an “unauthorized” response after every API call and prompt the user to relink if needed.
Linking a User to an UltraViolet implementer's service is simply a shortcut so the User doesn’t have to sign in to UltraViolet every time they use the implementer's service. A linked User is explicitly represented by the UserLinkConsent policy being set for that User. A linked User is not represented by the Security Token or the longevity of the Security Token.
A node can rely on the Coordinator to set the UserLinkConsent policy and issue corresponding long-term Security Token by directing the User to the FormAuth page (i.e., making an AuthnRequest to the Coordinator s-host; see DSecMech 5.3).
Note: Formerly the user was able to choose whether or not to establish a long-term link, using the "Link my UltraViolet Library" checkbox, but this is now automatic and the checkbox no longer appears.
The link connects a single User within an UltraViolet Account to a Node at the Organization level. In other words, all Nodes associated with the Org are linked to the User and don't need to be separately linked.
The Security Token contains its validity period. Before the Security Token expires, the Node should use the Security Token Exchange Service (STS) to renew it, which is allowed as long as UserLinkConsent is still set. This token renewal process should be invisible to users. A Node can choose to renew a Security Token at any time. The duration assigned by the Coordinator is typically one year but may vary, so implementations must be designed without assumptions about duration. An implementation could periodically check all Security Tokens and renew any that have less than a month left, or an implementation could maintain a table of renewal triggers for each Security Token by storing the expiration date of each Security Token when it's first received.
In general, every time a Node makes an API call it must be prepared in error handling routines to deal with an invalid Security Token, since it could have expired. (See "How to Manage" details below.)
When a Node shares a Security Token with other Nodes (within in its own Org, including when a Retailer shares a Security Token with a DSP partner) it must first ensure that the right SAML audience is set (i.e., it includes all the appropriate NodeID's within the AudienceRestriction) when requested. This can either be done in the original SAML assertion request message or by using STS to exchange the Security Token for one with a different audience (see [DSecMech] 5.5 and 8). If a Node ever needs to change the audience (such as when a Retailer switches to a different DSP) then it must update Security Tokens through STS. This can be done all at once in a batch or on-the-fly per user as needed.
Each time a Node calls a Coordinator API that requires a Security Token, the call can potentially fail because the Security Token is invalid. This can happen for various reasons:
An expired Security Token for a User with UserLinkConsent indicates that the Node didn't swap out the token before it expired. (And the Node should therefore fix its Security Token refresh mechanism.) A Security Token contains the validity period, so a Node can also determine beforehand that it has expired. A well-behaved Node will always check a Security Token to see if it has expired before attempting to use it.
Nodes should be prepared to handle Security Token errors after every API call. In particular, Nodes should check for 403 ("urn:dece:errorid:org:dece:securitycontext:unauthorized" and "urn:dece:errorid:org:dece:securitycontext:forbidden") errors. Expired or revoked Security Tokens are not renewable, so the Node must ask the User to log in to UltraViolet (or the Node must use email linking) before it can proceed. A node can mitigate error handling by responding to SAML Logout messages and internally discarding or flagging revoked Security Tokens, however there’s no guarantee that SAML Logouts will always be received, so error handling for Security Token rejection by the Coordinator should always be in place. Of course the user can choose not to log in when asked, in which case there is nothing further the Node can do other than to inform the user that they must log in to continue.
A Node can remove its own link by deleting the UserLinkConsent policies for the User. The Coordinator will revoke the Security Token related to the link. (If there are multiple UserLinkConsent policies, the Security Token will not be revoked until the last policy for the Org and related Nodes is deleted.)
Important note: For FormAuth-based linking, the Coordinator formerly created a multi-entity UserLinkConsent policy for each Node listed in the SAML audience, and before that it created multiple UserLinkConsent policies, one for each Node in the SAML audience. Therefore, when unlinking a user the Node must a) check for and delete any UserLinkConsent policies for Nodes in the same Org, and b) check for and delete any UserLinkConsent policy for its Org. An implementer can derive its Organization ID from its Node ID by removing the role at the end and adding “o:” before the licensee name. I.e., for Node ID urn:dece:org:org:dece:licenseename:retailer the Organization ID is urn:dece:org:org:dece:o:licenseename. And of course a Node must not attempt to delete UserLinkConsent policies belonging to other Nodes.
A Node with Account Management consent can unbind other Nodes, but only on User request as part of an Account Management interface that lists all linked services. This requires the presence of the ManageAccountConsent policy for the Node wishing to modify the consents.
Keep in mind the following when forming a request for email-response linking via UserValidationTokenCreate (urn:dece:type:token:DelegationTokenRequest) or InstaLink immediate linking (urn:dece:type:token:DelegationTokenRequest:VerifiedEmail):
application/x-www-form-urlencoded
For more on the Coordinator authentication interface (aka UVConnect, aka FormAuth) see Authentication UI.
For more on Security Tokens see the Security Mechanisms specification.
For more on account linking (binding), see the System specification and the Coordinator API specification.
Example request for v1.1.1: POST /rest/1/11/VerificationToken/urn:dece:type:token:DelegationTokenRequest:VerifiedEmail?subject=kbtestuvtc1@gsa.gov&responseType=urn:dece:type:tokenprofile:saml2 HTTP/1.1 Content-Type: application/x-www-form-urlencoded SAMLRequest=PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0a W9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJodHRwczovL3N0ZGVjcWF2dXRsMS52YS5uZXVzdGFyLmNvbToyNDg1L3NpbXBsZXNhbWwvbW9kdWxlLnBocC9zYW1sL3NwL3NhbWwyLWFjcy5waHAvQzBDRUY4RTA4Q0UxQzd ENkUwNDAxRjBBMDU5OTEyMEIiIERlc3RpbmF0aW9uPSJodHRwczovL3FhLnMudXZ2dS5jb206NzAwMS9zZWN1cml0eS9kZWxlZ2F0aW9uL3NhbWwvbG9naW5zZXJ2aWNlL2xvZ2luIiBGb3JjZUF1dGhuPSJ0cnVlIiBJRD0i NThlNTVkMGQtYTM4NC00Yzc1LWI0MmUtNmYzMDM4OGI0MmQwIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDUtMTVUMTI6Mjc6NTUuMDNaIiBQcm90b2NvbEJpbmRpbmc9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpia W5kaW5nczpIVFRQLVBPU1QiIFZlcnNpb249IjIuMCI%2BPHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI%2BdXJuOmRlY2U6b3JnOm9yZzpkZWNlOklTQ19 SRVQ8L3NhbWwyOklzc3Vlcj48c2FtbDJwOk5hbWVJRFBvbGljeSBBbGxvd0NyZWF0ZT0idHJ1ZSIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDp0cmFuc2llbnQiLz48c2FtbDJw
Example response for 1.1.1: HTTP/1.1 201 Created Date: Thu, 15 May 2014 16:27:58 GMT Server: Apache Set-Cookie: JSESSIONID=1ieegogwhsvp2rkr2s6uuas7q.api1;Path=/rest/1/11;Secure Expires: Thu, 01 Jan 1970 00:00:00 GMT Location: https://iot2.q.uvvu.com:/rest/1/11/SecurityToken/Assertion/_4297e771-2b74-4a68-b6b7-c28f3e3d6e9f x-Transaction-Info: t=1400171280 U3TrDgofmQsAAE9tKkoAAAAH urn:dece:org:org:dece:ISC_RET 10.33.201.21 Content-Length: 0 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: application/xml;charset=UTF-8
Example AuthnRequest (login): <samlp:authnrequest assertionconsumerserviceindex="0" destination="https://s.uvvu.com/security/delegation/saml/loginservice/login" id="c8206ddb-8877-44ef-9f51-4e5a5d7d8ca4" issueinstant="2012-10-22T19:04:10" version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">urn:dece:org:org:dece:{retailerid}:retailer</issuer> <samlp:nameidpolicy format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"> <samlp:requestedauthncontext> <samlp:authncontextclassref xmlns:samlp="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:Password</samlp:authncontextclassref> </samlp:requestedauthncontext> </samlp:nameidpolicy> </samlp:authnrequest>