Custom Authorizer in Java

Hello,
I am trying to implement a custom authorizer using Java.
I am able to generate a valid Auth Policy and validated its correct. When the client calls the endpoint, client is receiving a 500 exception.

My authorizer is not throwing the exception. Not sure where that 500 error code is being thrown. Can someone please help me?

Its a simple HTTPS get call to an API Gateway which has this custom authorizer.

Thank you in advance.

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.log4j.Logger;

import java.util.Map;

public class CustomAuthorizer implements RequestHandler<Map<String, Object>, ApiGatewayResponse> {

private static final Logger LOGGER = Logger.getLogger(CustomAuthorizer.class);
private static volatile AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient();
@Override
public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
    LOGGER.debug(input);
    String type = input.get("type").toString();
    String authorizationToken = input.get("authorizationToken").toString();
    String methodArn = input.get("methodArn").toString();
    LOGGER.debug("type: " + type);
    LOGGER.debug("autohrozation token: " + authorizationToken);
    LOGGER.debug("methodARN: " + methodArn);


    Object result = null;
    try {
        DecodedJWT jwt = JWT.decode(authorizationToken);

        LOGGER.debug("header: "+ jwt.getHeader());
        LOGGER.debug("Payload: "+ jwt.getPayload());
        LOGGER.debug("Signature: "+ jwt.getSignature());
        LOGGER.debug("Id : "+ jwt.getSubject());
        String principalId = jwt.getSubject();
        String[] arnPartials = methodArn.split(":");
        String region = arnPartials[3];
        String awsAccountId = arnPartials[4];
        String[] apiGatewayArnPartials = arnPartials[5].split("/");
        String restApiId = apiGatewayArnPartials[0];
        String stage = apiGatewayArnPartials[1];
        String httpMethod = apiGatewayArnPartials[2];
        String resource = ""; // root resource
        if (apiGatewayArnPartials.length == 4) {
            resource = apiGatewayArnPartials[3];
        }
   result = new AuthPolicy(principalId, AuthPolicy.PolicyDocument.getDenyAllPolicy(region, awsAccountId,
                restApiId, stage));
        LOGGER.debug(ApiGatewayResponse.builder()
                .setStatusCode(200)
                .setObjectBody(result)
                .build().getBody());

    } catch (JWTDecodeException exception){
        LOGGER.error(exception.getMessage(), exception);
        return ApiGatewayResponse.builder()
                .setStatusCode(500)
                .build();
    } catch (Exception exception) {
        LOGGER.error(exception.getMessage(), exception);
        return ApiGatewayResponse.builder()
                .setStatusCode(500)
                .build();
    }

    return ApiGatewayResponse.builder()
            .setStatusCode(200)
            .setObjectBody(result)
            .build();
}

}

Hi @pgali,
Unless something changed here recently, the response is not the usual lambda-proxy response (body, status, headers). You basically need to return the policy directly.

You can find some example for my serverless java framework JRestless, here:

The authorizer is not specific for that framework: https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-custom-authorizer/src/main/java/com/jrestless/aws/examples/CustomAuthorizerHandler.java

Hope this helps!

@bbliger - Thank you very much. Helped a lot. I have been on this for almost a week and couldn’t figure out what I was doing wrong. Your explanation helped.

Ironically, I did review your project and glanced it over without realizing that’s how we are supposed to support custom authorizer in java i was still trying to get it working using lambda-proxy.

Also, you had mentioned using JS why? because of cold start issues? Also, how did you implement policies in your project? Did you use dynamodb (SUB->policy mapping) or did you just do it inline by using the token, custom attributes to figure out the policy?

You made my day!!

@pgali
Glad to hear that it works now.

Yes, I’d rather implement a (simple) custom authorizer in JS because of cold start time. But as always: If your authorizer is called constantly then that is not really an issue.
I rarely used custom authorizers so far but when I used them I created the policy inline.