[JIRA] (JOIDC-6) Release policy for OAuth2 scope values based on IdPAttributes

Henri Mikkonen (Jira) jira at shibboleth.atlassian.net
Fri Jun 17 11:06:32 UTC 2022


Henri Mikkonen ( https://shibboleth.atlassian.net/secure/ViewProfile.jspa?accountId=557058%3A1614c4a5-c89e-4edc-9421-990bd6ea85fd ) *commented* on JOIDC-6 ( https://shibboleth.atlassian.net/browse/JOIDC-6?atlOrigin=eyJpIjoiMGQzOGZlZjJjMTE2NDU4NThmMDJhZmU0ZDk0MjU5ZDkiLCJwIjoiaiJ9 )

Re: Release policy for OAuth2 scope values based on IdPAttributes ( https://shibboleth.atlassian.net/browse/JOIDC-6?atlOrigin=eyJpIjoiMGQzOGZlZjJjMTE2NDU4NThmMDJhZmU0ZDk0MjU5ZDkiLCJwIjoiaiJ9 )

The following example describes how the allowed scope set can be modified according to the authenticated users' attributes.

In conf/global.xml, specify the function *shibboleth.oidc.AllowedScopeStrategy* (in this case together with a HelperPair to be able to exploit the default function and attribute resolver service):

   <bean id="shibboleth.oidc.AllowedScopeStrategy.HelperPair"
         class="net.shibboleth.utilities.java.support.collection.Pair"
         p:first-ref="shibboleth.AttributeResolverService"
         p:second-ref="shibboleth.oidc.DefaultAllowedScopeStrategy" />

   <bean id="shibboleth.oidc.AllowedScopeStrategy"
         parent="shibboleth.Functions.Scripted"
         p:customObject-ref="shibboleth.oidc.AllowedScopeStrategy.HelperPair"
         factory-method="inlineScript">
       <constructor-arg name="scriptSource">
           <value>
               <![CDATA[
               var logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.plugin.oidc.op.profile.AllowedScopeStrategy");
               authCtx = input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
               usernameLookupStrategyClass = Java.type("net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy");
               usernameLookupStrategy = new usernameLookupStrategyClass();
               username = usernameLookupStrategy.apply(input);
               result = custom.getSecond().apply(input);
               if (username != null) {
                   resCtx = input.getSubcontext("net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext", true);
                   resCtx.setPrincipal(username);
                   resCtx.resolveAttributes(custom.getFirst());
                   attribute = resCtx.getResolvedIdPAttributes().get("allowedScope");
                   if (attribute != null && attribute.getValues().size() > 0) {
                       logger.debug("Setting new scope value from allowedScope attribute");
                       result = Java.type("net.shibboleth.idp.plugin.oidc.op.profile.ScopeUtil").buildScope(attribute);
                   } else {
                       logger.debug("Keeping the existing scope value");
                   }
                   input.removeSubcontext(resCtx); // cleanup
               }
               logger.debug("Scope to be returned: " + result);
               result;
               ]]>
           </value>
       </constructor-arg>
   </bean>

The function checks if username can be resolved and if yes, resolves user’s attribute via resolver service. If an attribute allowedScope is resolved, its value will be used as the allowed scope for this user. If the username cannot be resolved (for instance with the backend flows) or the attribute allowedScope is not resolved, the value returned by the default function ( shibboleth.oidc.DefaultAllowedScopeStrategy ) is returned. It corresponds to the scope specified in the RP metadata.

The attribute-resolver snippet below shows one example for specifying the allowedScope attribute:

   <AttributeDefinition id="allowedScope" xsi:type="ScriptedAttribute">
       <InputDataConnector ref="oAuth2ScopeConnector" attributeNames="defaultAllowedScope"/>
       <InputDataConnector ref="staticAttributes" attributeNames="phone_number_verified"/>
       <Script><![CDATA[
           logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.attribute.allowedSope");
           ScopeUtil = Java.type("net.shibboleth.idp.plugin.oidc.op.profile.ScopeUtil");
           var phoneVerified = "";
           if (typeof phone_number_verified != "undefined" && phone_number_verified.getValues().size() > 0) {
              phoneVerified = phone_number_verified.getValues().get(0);
           }
           if (phoneVerified.equals("true")) {
              logger.debug("Keeping scope as it was");
              ScopeUtil.populateScriptedAttribute(allowedScope, defaultAllowedScope);
           } else {
              logger.debug("Removing 'phone' from the scopes");
              newScope = ScopeUtil.buildScope(defaultAllowedScope);
              ScopeUtil.removeValue(newScope, "phone");
              newAttribute = ScopeUtil.populateScriptedAttribute(allowedScope, newScope);
           }
       ]]></Script>
   </AttributeDefinition>

   <DataConnector id="oAuth2ScopeConnector" xsi:type="ScriptedDataConnector" customObjectRef="shibboleth.oidc.DefaultAllowedScopeStrategy">
       <Script><![CDATA[
           defaultAllowedScope = custom.apply(profileContext);
           scopeAsAttribute = Java.type("net.shibboleth.idp.plugin.oidc.op.profile.ScopeUtil").buildAttribute("defaultAllowedScope", defaultAllowedScope);
           connectorResults.add(scopeAsAttribute);
       ]]></Script>
   </DataConnector>

In this example, the allowedScope is defined so that *phone* value is removed from the default scope, if the attribute phone_number_verified is not set to *true*.

Obviously this specific example could have been implemented solely inside single *shibboleth.oidc.AllowedScopeStrategy* function, but the attribute-resolver snippet was included to demonstrate how its features may be exploited too in this context.

( https://shibboleth.atlassian.net/browse/JOIDC-6#add-comment?atlOrigin=eyJpIjoiMGQzOGZlZjJjMTE2NDU4NThmMDJhZmU0ZDk0MjU5ZDkiLCJwIjoiaiJ9 ) Add Comment ( https://shibboleth.atlassian.net/browse/JOIDC-6#add-comment?atlOrigin=eyJpIjoiMGQzOGZlZjJjMTE2NDU4NThmMDJhZmU0ZDk0MjU5ZDkiLCJwIjoiaiJ9 )

Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.core&referrer=utm_source%3DNotificationLink%26utm_medium%3DEmail ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailNotificationLink&mt=8 ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100201- sha1:07cea57 )
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://shibboleth.net/pipermail/commits/attachments/20220617/81d4731d/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jira-generated-image-static-comment-icon-bab07e25-e064-4fe8-ba26-69315c5cd304
Type: image/png
Size: 1084 bytes
Desc: not available
URL: <http://shibboleth.net/pipermail/commits/attachments/20220617/81d4731d/attachment-0003.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jira-generated-image-avatar-fb06b281-de0d-4c60-b124-ea01e2d50ca8
Type: image/png
Size: 457 bytes
Desc: not available
URL: <http://shibboleth.net/pipermail/commits/attachments/20220617/81d4731d/attachment-0004.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jira-generated-image-static-footer-desktop-logo-e9af1f58-98e3-48bf-bada-f96ad035538f
Type: image/png
Size: 10805 bytes
Desc: not available
URL: <http://shibboleth.net/pipermail/commits/attachments/20220617/81d4731d/attachment-0005.png>


More information about the commits mailing list