Contents


Implementing OAuth on IBM WebSphere DataPower Appliances, Part 9

Customization scenario for scope and identity support

Comments

Content series:

This content is part # of # in the series: Implementing OAuth on IBM WebSphere DataPower Appliances, Part 9

Stay tuned for additional content in this series.

This content is part of the series:Implementing OAuth on IBM WebSphere DataPower Appliances, Part 9

Stay tuned for additional content in this series.

Figure 1 shows native WebSphere® DataPower® support for OAuth with DataPower playing both the authorization and resource enforcement endpoint roles. You may recall from previous articles in this series that DataPower may act in either role or in conjunction with other services such as IBM's Tivoli® Federated Identity Management.

Figure 1. An OAuth exchange using an authorization code grant type
An OAuth exchange                     using an authorization code grant type
An OAuth exchange using an authorization code grant type

For DataPower to act as an authorization server, it has to provide at a minimum the following functions:

  • Issue and verify an authorization code.
  • Issue and verify an access token.
  • Issue and verify a refresh token (new in 6.0.0 release).

Within DataPower processing, both the authorization code and access token are self-contained and cryptographically protected. These tokens are transmitted as a part of transactional data such as HTTP headers, query parameters, or within post-data.

DataPower allows you to customize the processing of these tokens through extension points. These extension points allow customizations such as:

  • Check and validate the scope.
  • Set the default scope if none is provided (6.0 feature).
  • Determine validate the resource owner.
  • Customize the authorization/consent form
  • Additional OAuth processing (covered in Part 10)

During the customization steps for the following, DataPower will provide information to the custom stylesheet. It will also indicate which steps of the OAuth protocol DataPower is invoking for the stylesheet. The following list will also be expanded as new features are added:

  • authorization_request: This custom process is triggered during an authorization code grant type when the authorization code is requested by the client.
  • access_request: This custom process is triggered when the OAuth client/application is requesting for an access_token, which can be during the supported grant type.
  • resource_request: This custom process is triggered when the OAuth client/application is accessing a resource with its validated access_token.
  • refresh_request: This custom process is triggered when DataPower received a refresh grant_type from the OAuth client/application.
  • validate_request: This custom process is triggered when DataPower received a validation grant_type for an access_token.
  • client_revoke_request: This custom process is triggered when DataPower received a revoke request by the OAuth client/application to revoke the permission it received.
  • owner_revoke_request: This custom process is triggered when DataPower received a request by the resource owner to revoke an OAuth client/application to the owner's resource.

Checking the scope

The scope is checked in the following scenarios:

  • When requesting an authorization code (for the authorization code grant type)
  • When requesting an access token
  • When requesting a resource using a previously provided access token

In these cases, the OAuth client indicates the requested scope. By default, DataPower uses the regular expression specified in the Scope field of the OAuth Client Profile (as seen in Figure 2) to verify what is requested. You can enable customization of this behavior by checking the Customized Scope Check checkbox.

Figure 2. Enable the Custom Scope Check
Enable the Custom                     Scope Check
Enable the Custom Scope Check

Selecting the custom scope option enables a stylesheet selection field named Scope Customization Process. DataPower delegates scope-authorization decisions to this stylesheet for the OAuth client. For example, in Figure 3, dp-custom-scope.xsl is used to determine what scope is supported by this OAuth client.

Figure 3. Custom scope stylesheet field
Custom scope                     stylesheet field
Custom scope stylesheet field

The input to the scope is an XML node set as shown in Listing 1. Note that this XML node set may be extended in the future to include additional information.

Listing 1. Sample of custom scope processing input node
<input>
  <scope>requestedscope another-requested-scope</scope>
  <oauth-id type="authorization_request | access_request |
                     resource_request | …">
    …. from AAA Extract Identity (EI) ….
  </oauth-id>
  <OAuthSupportedClient>
    …. the registered OAuth client profile ….
  </OauthSupportedClient>
</input>

The "type" attribute of the oauth-id element describes the state or "type" of processing that DataPower is currently performing (see above for the list).

The output of the stylesheet must conform to either a success or failure format. The success format is shown in Listing 2.

Listing 2. Sample custom scope processing input node
<result>
   <scope>allowedscope1 allowedscope2</scope>
<result>

The failure format is shown in Listing 3.

Listing 3. Sample of failure scope processing
<result>
   <error>Scope is not allowed</error>
</result>

Listing 4 shows an example of a custom scope processing stylesheet. In this simple example, the <result> element is created and the /input/scope content is checked for supportedScope. If the test succeeds, a <scope> element is added. Otherwise, an <error> element is added. In this demonstration, the input scope of supportedScope is replaced with realScope. This is similar to the mapping capabilities of the AAA process, where credentials or resources may be "mapped" to other values.

Listing 4. Sample of custom scope processing
<xsl:template match="/">
  <result>
    <xsl:choose>
      <xsl:when test="contains(/input/scope, 'supportedScope')">
        <scope><xsl:value-of select="'realScope'"/></scope>
      </xsl:when>
      <xsl:otherwise>
        <error>requested scope is not allowed</error>
     </xsl:otherwise>
    </xsl:choose>
  </result>
</xsl:template>

Instead of using custom scope processing, you can also use AAA > Mapped Resource to archive this. The following is an example of the stylesheet on how to match a wild card "approved scope" to a list of URI requested by the client:

approved scope contains '/photo/spoon/*
requested resource by the client/application is '/photo/spoon/mutt.jpg

In order to map /photo/spoon/mutt.jpg to /photo/spoon/*, you can use a similar script as shown in Listing 5.

Listing 5. Sample of mapped resources processing (include the right namespace)
<xsl:stylesheet xmlns: ...
      xmlns:str="http://exslt.org/strings"
      xmlns:regexp=http://exslt.org/regular-expressions exclude-result-prefixes="... str regexp">
<xsl:template match="/">
  <xsl:variable name="req-res" select="/resource/item[@type != 
   'metadata']/text()"/>  <!—this gives .../mutt.jpg
        <entry type="custom">
           <xsl:variable name="splited-resource-from-at">
               <xsl:copy-of select="str:tokenize(/resource/item[@type=
                'metadata']/scope, ' ')"/>
           </xsl:variable>
           <xsl:variable name="resource">
               <xsl:for-each select="$splited-resource-from-at/token">
                  <xsl:if test="regexp:test($req-resource, text())">
                      <xsl:value-of select="text()"/>
                      <xsl:text> </xsl:text>
                  </xsl:if>
               </xsl:for-each>
           </xsl:variable>
           <xsl:if test="$resource != ''">
              <xsl:attribute name="oauth-verified">true</xsl:attribute>
              <xsl:value-of select="$req-resource"/>
           </xsl:if>
       </entry>
</xsl:template>
</xsl:stylesheet>

Specifying the default scope

In the 6.0.0 firmware release, DataPower allows for the specification of a default value of the scope when none is provided in the request. The format of the scope string is a space delimited string within the URL parameters. An example of specifying multiple scopes is using the "curl" command as follows:

curl -k -v https://<datapower.xxx.com>:8000/authz?client_id=<client-id>&redirect_uri=
 <redirect-uri>&response_type=code&scope=scope1%20scope2

Beginning with the 6.0.0 firmware release, the request can omit the scope and DataPower will use the field, as shown in Figure 4, to populate the scope attribute from the request. This field is found on the Advanced tab of the OAuth client profile object.

Figure 4. Default scope field
Default scope field
Default scope field

You can send the request by using the following format:

curl -k -v https://<datapower.xxx.com>:8000/authz?client_id=<client-id>&redirect_uri=
 <redirect-uri>&response_type=code

The above request with the default scope field shown in Figure 4 is equivalent to the following request with no default scope. Note that for the URL-encoding, %20 is a space and %2f is a forward slash.

curl -k -v https://<datapower.xxx.com>:8000/authz?client_id=<client-id>&redirect_uri=
 <redirect-uri>&response_type=code&scope=%2FgetCustomer%20%2FgetCreditCard%20%2FgetAbc

Determining the resource owner

By default, DataPower determines the user name from multiple steps during the OAuth process. First, by what already exists in the token, followed by the authenticated identity, and then the actual identity. This may not be what is required to track the resource owner's identity. You can customize this behavior through a stylesheet. Figure 5 shows a section of the Advanced tab of the OAuth client profile object. Check the box labeled Custom Resource Owner Handling and select the stylesheet as shown in Figure 5.

Figure 5. Customize the identity of the resource owner
Customize the identity of the resource owner
Customize the identity of the resource owner

The input for the resource owner process is an XML node set in the format shown in Listing 6. Note that this may be extended in the future to include additional information.

Listing 6. Input for the resource owner process
<input>
   <identity>....from AAA Extract Identity (EI) ….</identity>
   <credentials>.... from AAA Authenticate (AU) ….</credentials>
</input>

The output of the stylesheet must conform to the format shown in Listing 7. Since this retrieves the resource owner's identity, it should not return a failure.

Listing 7. Output for the resource owner process
<result>
  <resource-owner-name>internal resource owner name</resource-owner-name>
<result>

Listing 8 shows a snippet from the stylesheet. This snippet encrypts the resource owner information such that when the information is presented in an authorization/consent form, the user will not know his or her internal enterprise identity.

Listing 8. Sample of the custom resource owner processing
<xsl:template match="/">
<result>
        <!-- encrypt the credential, so it will not be shown on the html page
        -->
        <xsl:variable name="oauth-identity" select="/input/identity/entry[@type='oauth']"/>

        <!-- determine the actual resource owner identity -->
        <xsl:variable name="name">
          <xsl:choose>
            <xsl:when test="string(/input//mapped-credentials//username) != ''">
              <xsl:value-of select="/input//mapped-credentials//username"/>
            </xsl:when>
            <xsl:when test="string(/input//mapped-credentials//dn) != ''">
              <xsl:value-of select="/input//mapped-credentials//dn"/>
            </xsl:when>
            <xsl:when test="string(/input//mapped-credentials/entry[@type='xmlfile']
             /*[local-name()='OutputCredential']/text()) != ''">
              <xsl:value-of select="/input//mapped-credentials/entry[@type='xmlfile']
                /*[local-name()='OutputCredential']/text()"/>
            </xsl:when>
            <xsl:when test="string(/input/credentials//usernname) != ''">
              <xsl:value-of select="/input/credentials//usernname"/>
            </xsl:when>
            <xsl:when test="string(/input/identity//entry[@type='oauth']
             //resource_owner) != ''">
              <xsl:value-of select="/input/identity//entry[@type='oauth']
                //resource_owner"/>
            </xsl:when>
            <xsl:when test="string(/input/identity//entry[@type='oauth']
             //username) != ''">
              <xsl:value-of select="/input/identity//entry[@type='oauth']
               //username"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="/input/identity//usernname"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:message dp:priority="debug">*<xsl:value-of select=
          "$name"/>*</xsl:message>
        <!-- for resource access, potential to decrypt the resource owner field by
              <xsl:variable name="decrypted" select="dp:decrypt-data
               ('http://www.w3.org/2001/04/xmlenc#aes256-cbc',
                'hex:8374613847475628394384524354234243543254371643821764398714348900',
                $encrypted-owner )"/>
        -->
        <xsl:choose>
          <xsl:when test="$oauth-identity//oauth-id/@type = 'authorization_request'">
             <!-- this only occurs during initial request with either authorization code 
              or implicit grant type -->
             <resource-owner-name><xsl:value-of select="dp:encrypt-string
              ('http://www.w3.org/2001/04/xmlenc#aes256-cbc',
               'hex:8374613847475628394384524354234243543254371643821764398714348900', 
               $name)"/></resource-owner-name>
          </xsl:when>
          <xsl:otherwise>
            <resource-owner-name><xsl:value-of select="$name"/></resource-owner-name>
          </xsl:otherwise>
        </xsl:choose>
</result>
</xsl:template>

Customizing the authorization/consent form

DataPower generates the authorization/consent form using a script, which provides maximum flexibility for you. For example, you can add your company logo to the form, add additional information about the application, or add a link to a description about what the application will do. For more details, see the provided file, store:///OAuth-Generate-HTML.xsl, in the Download section to create your own local:///coolapp-az-form.xsl.

Conclusion

Part 9 of this multi-series described how you can customize WebSphere DataPower's native OAuth scope and identity support. By using the attached stylesheets in the Download section, you can use the extension points individually or combine them in different combinations to meet your business requirements.

Acknowledgments

The author would like to thank Paul Glezen for reviewing this article.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Middleware
ArticleID=1005005
ArticleTitle=Implementing OAuth on IBM WebSphere DataPower Appliances, Part 9: Customization scenario for scope and identity support
publish-date=05062015