|
User attributes may be returned either in ID Token http://openid.net/specs/openid-connect-core-1_0.html#IDToken or in UserInfo response http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse.
{ kid: "1e9gdk7", alg: "RS256" }. { iss: "http://server.example.com", sub: "248289761001", aud: "s6BhdRkqt3", nonce: "n-0S6_WzA2Mj", exp: 1311281970, iat: 1311280970, name: "Jane Doe", given_name: "Jane", family_name: "Doe", gender: "female", birthdate: "0000-10-31", email: "janedoe@example.com", picture: "http://example.com/janedoe/me.jpg" }. [signature] |
{ "sub": "248289761001", "name": "Jane Doe", "given_name": "Jane", "family_name": "Doe", "preferred_username": "j.doe", "email": "janedoe@example.com", "picture": "http://example.com/janedoe/me.jpg" } |
Whether the attribute ends up to the ID Token or UserInfo response depends on authentication request.
Third option is of course some agreement between RP and OP about non standard scope or some out of band agreement.
How clients request for claims is handled in more detail in section about attribute filtering |
Userinfo endpoint. Back-channel endpoint that can be accessed with Access Token returning UserInfo response.
Each of the endpoints perform attribute resolving! Back-channel endpoints do not have all session/context information available! Attributes that are based on session/context information must be instructed to be carried in tokens (i.e. encoded directly to authorization code and Access Token) unless implicit flow is used. Attribute resolvers that use session/context information must check the existence for the source information and fail gracefully if checking fails |
<AttributeDefinition id="password" xsi:type="ScriptedAttribute" dependencyOnly="true" language="nashorn"> <Script><![CDATA[ logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.script.password"); subjectCtx = profileContext.getSubcontext("net.shibboleth.idp.authn.context.SubjectContext"); subject = subjectCtx.getSubjects()[0]; if (!subject.getPrivateCredentials().isEmpty()){ password.addValue(subject.getPrivateCredentials().toArray()[0].getName()); } ]]></Script> </AttributeDefinition> |
<AttributeEncoder xsi:type="oidcext:OIDCString" name="affiliation" /> Input: IdPAttribute["member", "staff"] Output: "affiliation": "member staff" |
asArray
<AttributeEncoder xsi:type="oidcext:OIDCString" asArray="true" name="affiliation" /> Input: IdPAttribute["member", "staff"] Output: "affiliation":["member","staff"] |
<AttributeEncoder xsi:type="oidcext:OIDCString" asInt="true" name="updated_at" /> Input: IdPAttribute["1536143427"] Output: "updated_at": 1536143427 |
<AttributeEncoder xsi:type="oidcext:OIDCString" asBoolean="true" name="email_verified" /> Input: IdPAttribute["true"] Output: "email_verified": true |
<AttributeDefinition id="address" xsi:type="ScriptedAttribute"> <Dependency ref="staticAttributes" /> <Script><![CDATA[address.addValue("{\"street_address\":\""+street_address.getValues().get(0) + "\"," +"\"locality\":\""+locality.getValues().get(0) + "\"," +"\"region\":\""+region.getValues().get(0) + "\"," +"\"postal_code\":\""+postal_code.getValues().get(0) + "\"," +"\"country\":\""+country.getValues().get(0) + "\"}");]]></Script> <AttributeEncoder xsi:type="oidcext:OIDCString" asObject="true" name="address" /> </AttributeDefinition> Output: "address":{"street_address":"234 Hollywood Blvd.","country":"US","locality":"Los Angeles","region":"CA","postal_code":"90210"} |
<!-- This demonstrates a claim that is placed always to id token --> <AttributeDefinition id="email_idtoken" xsi:type="Simple" sourceAttributeID="email"> <Dependency ref="email" /> <AttributeEncoder xsi:type="oidcext:OIDCString" placeToIDToken="true" denyUserinfo="true" name="email" /> </AttributeDefinition> |
Attribute not resolvable in token and UserInfo endpoints must be carried in tokens if necessary.
<AttributeDefinition id="password" xsi:type="ScriptedAttribute" dependencyOnly="true" language="nashorn"> <Script><![CDATA[ logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.script.password"); subjectCtx = profileContext.getSubcontext("net.shibboleth.idp.authn.context.SubjectContext"); <!-- Subject does not have credentials populated in Token and UserInfo endpoints, have to give up in such case --> if (subjectCtx!=null){ subject = subjectCtx.getSubjects()[0]; password.addValue(subject.getPrivateCredentials().toArray()[0].getName()); } ]]></Script> <AttributeEncoder xsi:type="oidcext:OIDCString" setToToken="true" name="password"/> </AttributeDefinition> |
Locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client. It MUST NOT exceed 255 ASCII characters in length. The value is a case sensitive string.
Two types of Subject Identifiers, public and pairwise, http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
Different RPs may belong to same pairwise group by sharing the sector_identifier_uri - value
Placed always in ID Token and UserInfo response, whether requested or not.
Extension provides default resolver and a configuration for it.
# The source attribute used in generating the subject idp.oidc.subject.sourceAttribute = uid # The digest algorithm used in generating the subject #idp.oidc.subject.algorithm = SHA # The encoding used in generating the subject #idp.oidc.subject.encoding = BASE32 # The salt used in generating the subject # Do *NOT* share the salt with other people, it's like divulging your private key. idp.oidc.subject.salt = this_too_should_be_ch4ng3dExercises |
<!-- Subject Identifier is a attribute that must always be resolved. There has to be exactly one resolved and filtered attribute that would be encoded as 'sub'. This example attribute (the data connector actually ) will generate public or pairwise 'sub' depending on client registration data. --> <AttributeDefinition id="subject" xsi:type="Simple" activationConditionRef="SubjectRequired"> <InputDataConnector ref="computedSubjectId" attributeNames="subjectId"/> <AttributeEncoder xsi:type="oidcext:OIDCString" name="sub" /> </AttributeDefinition> <!-- Subject Identifier is a attribute that must always be resolved. There has to be exactly one resolved and filtered attribute that would be encoded as 'sub'. Use activation conditions and filters to ensure the requirement is met if you have need for several different kind of formats for 'sub'. <AttributeDefinition id="subject-public" xsi:type="Simple" sourceAttributeID="uid" activationConditionRef="PublicRequired"> <Dependency ref="uid" /> <AttributeEncoder xsi:type="oidcext:OIDCString" name="sub" /> </AttributeDefinition> <AttributeDefinition id="subject-pairwise" xsi:type="Simple" activationConditionRef="PairwiseRequired"> <InputDataConnector ref="computedSubjectId" attributeNames="subjectId"/> <AttributeEncoder xsi:type="oidcext:OIDCString" name="sub" /> </AttributeDefinition> --> <!-- Data Connector for generating 'sub' claim. The connector may be used to generate both public and pairwise subject values --> <DataConnector id="computedSubjectId" xsi:type="ComputedId" generatedAttributeID="subjectId" sourceAttributeID="%{idp.oidc.subject.sourceAttribute}" salt="%{idp.oidc.subject.salt}" algorithm="%{idp.oidc.subject.algorithm:SHA}" encoding="%{idp.oidc.subject.encoding:BASE32}"> <Dependency ref="%{idp.oidc.subject.sourceAttribute}"/> </DataConnector> |
<AttributeFilterPolicy id="OPENID_SCOPE"> <PolicyRequirementRule xsi:type="oidcext:OIDCScope" value="openid" /> <AttributeRule attributeID="subject"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> </AttributeFilterPolicy> |
|
There are two main mechanisms for RP to ask for attributes,
{ "userinfo": { "given_name": {"essential": true}, "nickname": null, "picture": null, "http://example.info/claims/groups": null }, "id_token": { "email": {"essential": true}, "email_verified": {"essential": true}, "sub": {"value": "248289761001"} "auth_time": {"essential": true}, "acr": {"essential": true, "values": ["urn:mace:incommon:iap:silver", "urn:mace:incommon:iap:bronze"]} } } |
It is your job to resolve and filter attributes to match the requests. OIDC extension has reserved the right to control some claims you should not try to resolve or filter.
PolicyRule which returns true if any of the scope values in the authentication request matches a supplied string.
<!-- This demonstrates a rule that releases email claims in response to all oidc authentication requests having scope email. The requester needs to have scope email as a registered scope. --> <AttributeFilterPolicy id="OPENID_SCOPE_EMAIL"> <PolicyRequirementRule xsi:type="oidcext:OIDCScope" value="email" /> <AttributeRule attributeID="email"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="email_verified"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> </AttributeFilterPolicy> |
Matcher which returns attribute values after comparing them to requested claims parameter of oidc authentication request.
<!-- This demonstrates a rule that releases email in id token if specifically asked to be released as essential for id token --> <AttributeFilterPolicy id="REQUESTED_CLAIMS"> <PolicyRequirementRule xsi:type="ANY" /> <AttributeRule attributeID="email_idtoken"> <PermitValueRule xsi:type="oidcext:AttributeInOIDCRequestedClaims" matchOnlyIDToken="true" onlyIfEssential="true" /> </AttributeRule> </AttributeFilterPolicy> |
Define a new scope "campus". Target is to have scope "campus" that includes a claim "campus_id" to ID Token.
|
Define attribute release rules to release "campusId" attribute to be released if asked to be released for ID Token as essential claim. 1. Make sure "campusId" is not requested anymore by scope.
2. Modify RP to ask "campusId" as essential ID Token claim.
3. Remove or comment the campus scope filter rule that you added in exercise 4.1.1. Add a new filtering rule that will release "campusId" as a claim only if requested to be released as essential ID Token claim
4. Authenticate the user and verify from the logs the attribute is released. At this point you should be able to do it without hints and tips. |
Available contexts in Endpoints
|
Formatting attribute
|
Configuring Subject claim
|