kong

KONG Same Route with Both JWT and API Key Authentication, How to Make Both Work Simultaneously?


I am currently using KONG Gateway, and I've enabled two authentication mechanisms on the same Route in a Service: JWT Authentication and API Key Authentication. When I use one of the authentication methods, the other one causes the request to be rejected.

Specifically:

Here is my configuration:

  1. Enable JWT Authentication Plugin:

    curl -i -X POST http://localhost:8001/routes/my-route/plugins \
         --data name=jwt
    
  2. Enable API Key Authentication Plugin:

    curl -i -X POST http://localhost:8001/routes/my-route/plugins \
         --data name=key-auth
    

I want to be able to use either JWT or API Key authentication based on what the request carries, rather than being limited to just one authentication method.

My question:


Solution

  • You could create a consumer which will be used to identify as "Anonymous" and configured both authentication plugin to use that customer to "pass" authentication.

    First, create an anonymous consumer:

    curl -sX POST localhost:8001/consumers \
    --data '{"username": "anonymous"}'
    

    Afterward, use the id of this newly created anonymous consumer and add it to config.anonymous field of both authentication plugins:

    curl -i -X PUT http://localhost:8001/routes/my-route/plugins/{key-auth-plugin-id} \
       --data '{"name": "key-auth", "config": { "anonymous": "{anonymous-consumer-id}"}}'
    
    curl -i -X PUT http://localhost:8001/routes/my-route/plugins/{jwt-plugin-id} \
       --data '{"name": "jwt", "config": { "anonymous": "{anonymous-consumer-id}"}}'
    

    This will essentially create an OR flow between both authentication plugin, when the first plugin failed (jwt), Kong will understand that the request is not authenticated and use key-auth to perform authentication again.

    Afterward, add a Request Termination plugin to the anonymous consumer:

    curl -sX POST localhost:8001/consumers/anonymous/plugins/ \
      --data '{"name": "request-termination", "config": { "status_code": 401, "content_type": "application/json; charset=utf-8", "body": "{\"error\": \"Authentication required\"}"} }'
    

    This will cause the request that failed every authentication plugins to get a 401 error back with Authentication required in the body.