Custom OIDC Discovery Endpoint for WSO2 Identity Server
WSO2 Identity Server supports OpenID Connect Discovery to discover an end user’s OpenID provider, and also to obtain information required to interact with the OpenID provider, including its OAuth 2.0 endpoint locations.
One limitation in the current Identity Server version (5.7.0) is that, the values in the Discovery response is not configurable and are not dynamically generated. For example, let’s say you plan to use an additional OAuth Client Authentication mechanism such as Private Key JWT or Mutual TLS with your Identity Server. These authenticators are not available out of the box but you can configure them through the connector store. Even though those can be configured to be used with IS, in the OIDC discovery endpoint this information will not be visible as the data is not dynamically generated. In this post, I’m going to show a work-around to make the OIDC discovery endpoint data configurable.
In order to make the .well-known endpoint data configurable we can introduce a new JSON file and populate the discovery data by reading this file. Then we can write a custom Java Servlet to render the JSON content whenever the .well-known URI is invoked. Servlet logic should simply be able to read the config file and render the JSON content when .well-known URI is invoked. It will be similar to following.
public class Discovery extends HttpServlet {
public void init() throws ServletException {
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Set response content type as 'application/json'
response.setContentType("application/json");
// read JSON file and populate data to 'outputContent' JSON object.
JSONObject outputContent = DiscoveryDataHolder.getInstance().getDiscoveryData();
// Get the PrintWriter object from response to write the required JSON object to the output stream.
PrintWriter out = response.getWriter();
out.print(outputContent);
out.flush();
}
}
In the JSON file, we can keep the original data by default and upon the requirement you can customize the content as per your wish. For the demonstration we will include ‘private_key_jwt’ under ‘token_endpoint_auth_methods_supported’ propery as shown below.
{
"scopes_supported": [
"address",
"phone",
"email",
"profile",
"openid"
],
"check_session_iframe": "https://localhost:9443/oidc/checksession",
"issuer": "https://localhost:9443/oauth2/token",
"authorization_endpoint": "https://localhost:9443/oauth2/authorize",
"claims_supported": [
"formatted",
"name",
"phone_number",
"given_name",
"picture",
"region",
"street_address",
"postal_code",
"zoneinfo",
"locale",
"profile",
"locality",
"sub",
"updated_at",
"email_verified",
"nickname",
"middle_name",
"email",
"family_name",
"website",
"birthdate",
"address",
"preferred_username",
"phone_number_verified",
"country",
"gender",
"iss",
"acr"
],
"token_endpoint": "https://localhost:9443/oauth2/token",
"response_types_supported": [
"id_token token",
"code",
"id_token",
"token"
],
"end_session_endpoint": "https://localhost:9443/oidc/logout",
"userinfo_endpoint": "https://localhost:9443/oauth2/userinfo",
"jwks_uri": "https://localhost:9443/oauth2/jwks",
"subject_types_supported": [
"pairwise"
],
token_endpoint_auth_methods_supported:[
"client_secret_basic",
"client_secret_post",
"private_key_jwt"
]
"id_token_signing_alg_values_supported": [
"RS256"
],
"registration_endpoint": "https://localhost:9443/identity/connect/register"
}
Above servlet implementation requires the JSON file to be located at <IS_HOME>/repository/conf/identity path.
Now follow the below steps to register the servlet in Identity Server.
- Compile the Java file as a JAR and copy it to <IS_HOME>/repository/components/lib folder.
- Copy the openid-configuration.json file to <IS_HOME>/repository/conf/identity folder. You can update/modify the values in this file as per your requirement.
- Register the servlet in the <IS_HOME>/repository/conf/tomcat/web.xml file by adding the following elements before the </webapp> element.
<servlet>
<servlet-name>Discovery</servlet-name>
<servlet-class>myPackage.Discovery</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Discovery</servlet-name>
<url-pattern>/oauth2/oidcdiscovery/.well-known/openid-configuration</url-pattern>
</servlet-mapping>
- Restart the server with updated JSON and execute the following command to obtain the updated discovery data.
curl -v -k -u admin:admin https://localhost:9443/oauth2/oidcdiscovery/.well-known/openid-configuration
Complete implementation of the custom OIDC discovery endpoint can be found in the following Github repository.