Monday, May 11, 2015

Writing a custom Grant Handler for WSO2 APIM

Here is a how to guide for writing custom grant handler to WSO2 APIM

I have used WSO2 APIM 1.8 for this example

Simply what you have to do is as follows

1) Implement the "org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationGrantHandler" api class in bundle "org.wso2.carbon.identity.oauth" versoin "4.3.2". Maven dependency for this would be



            org.wso2.carbon.identity

            org.wso2.carbon.identity.oauth

            4.3.2



to simplify, instead of implementing the above api class you can extend the "org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler" class which will be an abstract class implemented on "AuthorizationGrantHandler" api. This class will have the basic implementation we need. So we can simply extend this class, override methods we need, call the super method withing those implementations so that default implementation(which is in abstract class "AbstractAuthorizationGrantHandler") will get called.

Basic method we need to override will be "public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx)
            throws IdentityOAuth2Exception" method.

Below is a sample implementation of this scenario

public class CustomGrantHandler extends AbstractAuthorizationGrantHandler {    

    @Override
    public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx)
            throws IdentityOAuth2Exception {        

        super.validateGrant(tokReqMsgCtx);

        //Things you need to do 
        return true;
    }

    @Override
    public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {
        ScopesIssuer scopesIssuer = new ScopesIssuer();
        return scopesIssuer.setScopes(tokReqMsgCtx);
    }

    @Override
    public boolean authorizeAccessDelegation(OAuthTokenReqMessageContext tokReqMsgCtx)
            throws IdentityOAuth2Exception {
        
        //things you need to do
        return true;
    }   
}

Here within the "tokReqMsgCtx" object you will have all the request parameters you need. as a array of "org.wso2.carbon.identity.oauth2.model.RequestParameter" objects.
You can access this object array as follows

tokReqMsgCtx.getOauth2AccessTokenReqDTO().getRequestParameters();


2) Implement  "org.apache.amber.oauth2.common.validators.OAuthValidator" api class in bundle "amber" which will be imported via above mentioned "oauth" dependency. Then override required methods.

3) bundle them to a jar file and deploy it into "<APIM_HOME>/repository/components/lib" folder

4) add this custom authenticator to "<APIM_HOME>/repository/conf/identity.xml" file under "<SupportedGrantTypes>" element as follows.


    {grant_type_name}
    {your custom grant handler implementation}
    {your custom oauth validator implemention}
 

sample would be as follows

        
 custom_grant
        com.custom.grant.handler.handlers.CustomGrantHandler
        com.custom.grant.handler.handlers.CustomValidator



Restart APIM and you are set. Invoke the token api with your custom request with providing grant type as "custom_grant" and this handler will get invoked. Sample will be as follows

curl -k -d "grant_type=custom_grant" -H "Authorization: Basic YlB5NzZGNmYyRHYzMmJLeXFSaXVnVWJmM1pRYTpueXFWZ3Y0TTRldFdhRV9JS2NFNXBPYmYyVEVh, Content-Type: application/x-www-form-urlencoded" https://localhost:8244/token

There is an important point you have to take into notice. If you are extending "org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler" class instead of implementing "org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationGrantHandler" api, then make sure you are overriding the method "public boolean authorizeAccessDelegation(OAuthTokenReqMessageContext tokReqMsgCtx)
            throws IdentityOAuth2Exception" and not invoking the super method within the implementation. Reason is, in the "AbstractAuthorizationGrantHandler" abstract class, there is a implementation for above method which validates the grant type against wso2 custom grant types and oauth2 grant types. Since which we write is a custom grant type, it won't be there in the default wso2 implementations. So the validation fails. Overriding the method will resolve that problem as mentioned above.

Another side note if you are going to use IS as keymanager setup.
Then you'll need to have this custom implementation in IS instead of APIM. for that, do the following.(Needs to have IS 5 for this)

1) Create a IS as a keymanager setup as instructed in [1]

2) copy the jar bundle you created with your custom implementations to "<IS_HOME>/repository/components/lib" folder

3) follow the step 4) for the APIM instructions above and change "identity.xml" file inside "<IS_HOME>/repository/conf" folder and add the "SupportedGrantType" as instructed.

Restart the IS and you are set.

Hope this will be some help for the people who struggles trying to write custom grant handlers for APIM or IS

[1] - https://docs.wso2.com/display/CLUSTER420/Configuring+WSO2+Identity+Server+as+the+Key+Manager


1 comment :

Unknown said...

Hi,

can i set two mandatory parameters for my custom grant type?

so that access token has to generate with the combination of 2 parameters along with client credentials.

thanks in Advance