This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.
Writing A New OAuth Client Authenticator
Client authentication is used to identify the application or the client that is making the request. In most scenarios, in order to authenticate the application or client, you retrieve the access token using the client ID and secret that are sent in the token request. Only the application knows the client ID and secret and it sends them out to authenticate the calling party.
There are multiple ways to authenticate an OAuth client. For more information, see the client authentication specification. The most widely used authentication method is the client secret authentication. This method can further be divided into the Client secret basic authentication, Client secret post authentication, Client secret JWT authentication, and Private key JWT authentication sections.
Previously, with WSO2 Identity Server (WSO2 IS) the client ID and client secret were hard coded to the OAuth service provider that was created. With this new implementation, the OAuth client authentication process is decoupled and is handled via different authenticators.
Using WSO2 Identity Server 5.5.0 you are able to extend the client authentication implementation. Therefore, you don’t need to stick to the same client id and secret. You can write your own client authentication mechanism following a specification or any other standard. WSO2 Identity Server 5.5.0 supports client secret basic authentication out of the box.
This document covers the following sections:
The default authenticator
The default authenticator that is supported out of the box is named BasicAuthClientAuthenticator. It is written to handle the basic client authenticator as follows:
To have an HTTP header known as the
Authorizationin the following format:(base64encoded(client_id:client_secret))The
client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>in the body of the request.
The elements used in each method are explained below:
request: TheHttpServletReqeust, which is the incoming request to the endpointbodyParams: List out the body parameters of the incoming request.OAuthClientAuthnContext: The context used to store and maintain the status of the authentication flow.
Implementing a new authenticator
Implementing an OAuth client authenticator is as straightforward as implementing an Interface. Let's take a look at how to create a sample OAuth client authenticator that only expects to have the client id and secret as two separate HTTP headers.
Let's get started!
Create a Java class and extend the
AbstractOAuthClientAuthenticator.public class OAuthSampleClientAuthenticator extends AbstractOAuthClientAuthenticator {In this sample, you are implementing the
authenticateClient,canAuthenticate, andgetClientIdmethods and overriding thegetPrioirtyandgetNamemethods.
Let's get to know each of these methods:authenticateClientThis method checks the validity of the given credentials. For example, if it’s client id and secret, you should validate the secret of the given client. If it is a JWT authentication you should do the JWT validation, such the signature validation.canAuthenticateThis method returns True if this authenticator can authenticate the incoming request based on the parameters and the content of the incoming request, else it return false. If true is returned, the authentication is handled by the authenticator, else the authenticator skips authenticating the user.getClientIdThis method extracts the client id of the calling client.
TheOAuthClientAuthnContextmaintains the state of authentication flow. It stores the information you derive in this method for future reference.getName
You need to override this method so that the authenticator you are implementing is registered with a new name.get Priority
Define the priority order of the authenticator. Make sure that the priority order ID is not taken up by another authenticator or implementation. Overriding this method is optional.
If the method is not overridden here, the configuration in the identity.xml file is taken into consideration when executing this authenticator. See step 3 for more information.isEnabled
Define if the authenticator is enabled of disabled. Overriding this method is optional.
If the method is not overridden here, the configuration in the identity.xml file is taken into consideration when executing this authenticator. See step 3 for more information.
public class OAuthSampleClientAuthenticator extends AbstractOAuthClientAuthenticator { public boolean authenticateClient(HttpServletRequest httpServletRequest, Map < String, List > map, OAuthClientAuthnContext oAuthClientAuthnContext) throws OAuthClientAuthnException { String clientId = httpServletRequest.getHeader("client_id"); String clientSecret = httpServletRequest.getHeader("client_secret"); try { return OAuth2Util.authenticateClient(clientId, clientSecret); } catch (IdentityOAuthAdminException | InvalidOAuthClientException | IdentityOAuth2Exception e) { throw new OAuthClientAuthnException("Error while authenticating client", "INVALID_CLIENT", e); } } public boolean canAuthenticate(HttpServletRequest httpServletRequest, Map < String, List > map, OAuthClientAuthnContext oAuthClientAuthnContext) { if (httpServletRequest.getHeader("client_id") != null && httpServletRequest.getHeader("client_secret") != null) { return true; } return false; } public String getClientId(HttpServletRequest httpServletRequest, Map < String, List > map, OAuthClientAuthnContext oAuthClientAuthnContext) throws OAuthClientAuthnException { return httpServletRequest.getHeader("client_id"); } @Override public int getPriority() { return 150; } @Override public String getName() { return "SampleOAuthClientAuthenticator"; } }If you did not override the
getPriorityorisEnabledmethods in the authenticator class, you can define it in the<IS_HOME>/repository/conf/identity/identity.xmlfile under the<EventListners>property.<EventListener type="org.wso2.carbon.identity.core.handler.AbstractIdentityHandler" name="org.wso2.carbon.identity.oauth.client.auth.sample.OAuthSampleClientAuthenticator.java" orderId="899" enable="true" />Register the authenticator as an OSGi service. For example, see here.
Build the OSGi bundle.
mvn clean installDeploy the authenticator by copying the build jar file to the
<IS_HOME>/repository/components/dropinsdirectory.Restart the server.
Try it out
To try out the sample implementation that was used in this guide, follow the steps given below to successfully get the token.
Navigate to the
is-samples/oauth-sample-client-authenticatordirectory.Build the sample.
mvn clean installCopy the
org.wso2.carbon.identity.oauth.client.auth.sample-1.0-SNAPSHOT.jarfile that is inis-samples/oauth-sample-client-authenticator/targetdirectory to the<IS_HOME>/repository/components/dropinsdirectory.Run the cURL command given below to get the token.
curl -k -d "grant_type=password&username=admin&password=admin" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:9443/oauth2/token -i -H "client_id: 0gP9suHvLpKZLhVdgtXKWfiybdca" -H "client_secret: PIOpiS1637JvSVHn2lDGIOACDNwa"The sample response:
"access_token":"8298afd0-7474-3ae2-837a-84d69ae0c107","refresh_token":"25b66aa7-253b-3704-9086-e53a5f386c1f","token_type":"Bearer","expires_in":3600"