Introduction:
IBM Security Access Manager OIDC is certified for OP for 6 profiles: https://openid.net/certification/#OPs
Certified implementations can use the “OpenID Certified” certification mark.
OIDC OP conformance was achieved by tapping on several existing ISAM features like access policies, mapping rules, STS chains, etc.
In this blog we will see how the conformance for discovery endpoint, /.well-known/openid-configuration is achieved.
Conformance Criteria to be achieved:
OpenID Providers supporting Discovery MUST make a JSON document available at the path formed by concatenating the string /.well-known/openid-configuration to the Issuer.
IBM Security Access Manager provides an endpoint for discovery which is the metadata endpoint - /<mga>/sps/oauth/oauth20/metadata/<OIDCDefinition>. However, the specification strictly states that the discovery endpoint is /.well-known/openid-configuration appended to the issuer endpoint.
Achieving OIDC OP Conformance for the discovery endpoint:
OIDC OP conformance for the discovery (well-known) endpoint can be achieved using the HTTP transformation rule.
We can create an HTTP transformation rule, similar to htptransform.xsl below, and route the requests from 'test/.well-known/openid-configuration' to '/<mga>/sps/oauth/oauth20/metadata/<OIDCDefinition>'
In the following example, API definition's issuer is configured to be https://www.myidp.ibm.com/test.
The [http-transformations] stanza in the reverse proxy configuration file must be updated to:
[http-transformations]
updateuri = httptransform
[http-transformations:updateuri]
request-match = request:GET /test/.well-known/openid-configuration*
Adding optional Discovery parameters:
The json response for discovery is constructed using the metadata.json file that can be found under Secure Federation à Template Files or Secure Access Control à Template Files.
The optional discovery parameters, which are required for conformance, can be added, by modifying metadata.json.
The modification that must be made are as follows:
- Adding "claims_supported" with the following values:
["realmName","preferred_username","given_name","uid","upn","groupIds",
"employee_id","name","tenantId","mobile_number","department","job_title","family_name","email"]
- Adding "userinfo_signing_alg_values_supported" with this value: ["RS256"]
- Adding "request_parameter_supported" with the following value :
<%var supported = true;templateContext.response.body.write(supported);%>
httptransform.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*" />
<xsl:template match="/">
<HTTPRequestChange>
<xsl:apply-templates />
</HTTPRequestChange>
</xsl:template>
<!--
Replacing the URI 'test/.well-known/openid-configuration' with
'/mga/sps/oauth/oauth20/metadata/OIDCDefinition'
-->
<xsl:template match="//HTTPRequest/RequestLine/URI">
<xsl:variable name="output">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="node()" />
<xsl:with-param name="replace" select="'test/.well-known/openid-configuration'" />
<xsl:with-param name="by" select="'/mga/sps/oauth/oauth20/metadata/OIDCDefinition'" />
</xsl:call-template>
</xsl:variable>
<URI>
<xsl:value-of select="$output" />
</URI>
</xsl:template>
<xsl:template match="//HTTPRequest/Scheme">
</xsl:template>
<xsl:template name="string-replace-all">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>