Missing authorization token in AWS Lambda with Jersey. Setup does not involve APIGateway

193 Views Asked by At

So I have been trying to make my sample Rest API work without using APIGateway. The routing is done by ALB to the lambda. I am new to this kind of setup. I have set up custom filters when initializing the jersey application. I tried to follow the setup as directed in

https://gitlab.com/jamietanna/jersey-servlet-filter-example/-/tree/master/src/main/java/com/amazonaws/serverless/sample/jersey

The LambdaStreamHandler class shows that I have Bearer token in authorization. The input stream does show what I am requesting but when it gets to the registered filter which looks for the AuthToken it fails to find it and I get unauthorized.


{
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:`account`:targetgroup/`targetGroupId`/`id`"
        }
    },
    "httpMethod": "GET",
    "path": "/api/1/users",
    "queryStringParameters": {
        "type": "default"
    },
    "headers": {
        "accept": "*/*",
        "accept-encoding": "gzip, deflate, br",
        "authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
        "cache-control": "no-cache",
        "connection": "keep-alive",
        "host": "localhost:54321",
        "postman-token": "44a40191-889e-4059-8e7d-0b57a00c403b",
        "user-agent": "PostmanRuntime/7.29.0",
        "x-amzn-trace-id": "Root=1-628e81cb-0b7bcdb36837c59b47862384",
        "x-forwarded-for": "104.1.102.155",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https"
    },
    "body": "",
    "isBase64Encoded": false
}

The filter I have setup looks like


public class AuthFilter implements Filter {

    public AuthFilter() {
    }

    @Override
    public void init(final FilterConfig arg0) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain)
        throws IOException, ServletException {
        final HttpServletRequest  httpReq  = request instanceof HttpServletRequest ? (HttpServletRequest) request : null;
        final HttpServletResponse httpResp = response instanceof HttpServletResponse ? (HttpServletResponse) response : null;

       
        if (httpReq == null || httpResp == null) {
            Log.warn("No http request or response found");
            return;
        }

        StringBuilder headers = new StringBuilder();
        Iterator<String> it = httpReq.getHeaderNames().asIterator();
        while (it.hasNext()) {
            headers.append(it.next());
            headers.append(" ");
        }

        StringBuilder params = new StringBuilder();
Iterator<String> it2 = httpReq.getParameterNames().asIterator();
        while(it2.hasNext()) {
            headers.append(it2.next());
            headers.append(" ");
        }


        String log = "\n" +
          "--------------------------------------------------" + "\n" +
          "Received request with pathInfo: " + httpReq.getPathInfo() + "\n" +
          "---queryString: " + httpReq.getQueryString() + "\n" +
          "---URI: " + httpReq.getRequestURI() + "\n" +
          "---parameterMap: " + httpReq.getParameterMap() + "\n" +
          "---headerNames: " + it + "\n" +
          "---method: " + httpReq.getMethod() + "\n" +
          "---translatedPath: " + httpReq.getPathTranslated() + "\n" +
          "---params: " + it2 + "\n" +
          "---servletPath: " + httpReq.getServletPath() + "\n" +
          "--------------------------------------------------" + "\n";

        Log.info(log);

        // if it's a pre-flight request, then let the request pass through
        if (httpReq.getMethod().equals("OPTIONS")) {
            logger.warn("Ignoring preFlight request");
            filterChain.doFilter(httpReq, httpResp);
            return;
        }

        final String authToken = httpReq.getHeader("Authorization");
        if (Strings.isNullOrEmpty(authToken) || !authToken.startsWith("Bearer")) {
            Log.info("AuthToken not found hence unauthorized!!");
            HttpUtils.sendErrorResponse(httpResp, Status.UNAUTHORIZED);
            return;
        }

        final TokenVerifier verifier = new TokenVerifier();
        try {
            final TokenInfo bti      = verifier.extractAndVerifyToken(httpReq, false);
            final AuthInfo        authInfo = verifier.getAuthInfo(bti.getToken());
            if (!Permissions.hasViewAccess(authInfo) && !Permissions.hasWriteAccess(authInfo)) {
                HttpUtils.sendErrorResponse(httpResp, Status.FORBIDDEN, "User does not have permission.");
            }
            httpReq.setAttribute("authInfo", authInfo);
            httpReq.setAttribute("token", authToken.replace("Bearer ", ""));


            filterChain.doFilter(httpReq, httpResp);
        } catch (IllegalAccessException | TokenAuthenticationException e) {
            HttpUtils.sendErrorResponse(httpResp, Status.UNAUTHORIZED);
        }
    }
}

The log entry I see is

--------------------------------------------------
Received request with pathInfo: /api/1/users
---queryString: null
---URI: /api/1/users
---parameterMap: 
{}

---headerNames: 
---method: GET
---translatedPath: null
---params: 
---servletPath: 
--------------------------------------------------

I am not seeing the authorization header anywhere or any header for that matter in the AWSProxyRequest class. Can you tell me what I am doing wrong here.

Debug Mode Snapshot

0

There are 0 best solutions below