Search code examples
restkeycloakapigee

Secure Apigee Edge proxy with keycloak?


We are using two-way TLS communication between Apigee Edge and Backend server (which is exposed using NginxIngress in Kubernetes). However, we want to integrate Apigee Edge with keycloak to secure the Apigee Endpoint endpoint (e.g https://org-name-env.apigee.net/path).

I am new to Apigee and Keycloack and after searching a lot, I am posting this question to get proper documentation on using Keycloak with Apigee Edge. Any article, community answers, suggestions, direction, documentation or POC will be helpful.


Solution

  • Below is the document I created to do the setup and created a markdown document for the same which looks something like below:

    1 Generating JWT token using KeyCloak
    • Assuming the basic setup of KeyCloak like Realm, Roles, Users etc being done, create JWT token for a user. (You can validate this JWT token from jwt.io using the public key of KeyCloak realm to make sure the JWT token is valid and signed). The public key can be found in Realm Settings. Refer to this image to get the public key.
      Add -----BEGIN PUBLIC KEY----- and append -----END PUBLIC KEY----- to this copied public key to use it in Apigee configuration and on jwt.io. Here is how a valid and usable public key will look like :
    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhAj9OCZd0XjzOIad2VbUPSMoVK1X8hdD2Ad+jUXCzhZJf0RaN6B+79AW5jSgceAgyAtLXiBayLlaqSjZM6oyti9gc2M2BXzoDKLye+Tgpftd72Zreb4HpwKGpVrJ3H3Ip5DNLSD4a1ovAJ6Sahjb8z34T8c1OCnf5j70Y7i9t3y/j076XIUU4vWpAhI9LRAOkSLqDUE5L/ZdPmwTgK91Dy1fxUQ4d02Ly4MTwV2+4OaEHhIfDSvakLBeg4jLGOSxLY0y38DocYzMXe0exJXkLxqHKMznpgGrbps0TPfSK0c3q2PxQLczCD3n63HxbN8U9FPyGeMrz59PPpkwIDAQAB
    -----END PUBLIC KEY-----
    

    Refer this post from medium.com for more details on JWT generation with KeyCloak.

    2 Using VerifyJWT policy in Apigee
    • Assuming basic Apigee policy created for the server endpoint, add a AssignMessage policy to give the public key in the PreFlow section of the Proxy, so that all the requests will go via this policy and a public key of KeyCloak will be assigned to a variable.
      Click here to know more about configuring flows in Apigee.
      AssignMessage policy XML will look something like this:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <AssignMessage async="false" continueOnError="false" enabled="true" name="Assign-Message-1">
        <DisplayName>Assign Message-1</DisplayName>
        <Properties/>
        <AssignVariable>
            <Name>public.key</Name>
            <Value>-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhAj9OCZd0XjzOIad2VbUPSMoVK1X8hdD2Ad+jUXCzhZJf0RaN6B+79AW5jSgceAgyAtLXiBayLlaqSjZM6oyti9gc2M2BXzoDKLye+Tgpftd72Zreb4HpwKGpVrJ3H3Ip5DNLSD4a1ovAJ6Sahjb8z34T8c1OCnf5j70Y7i9t3y/j076XIUU4vWpAhI9LRAOkSLqDUubRX/ZdPmwTgK91Dy1fxUQ4d02Ly4MTwV2+4OaEHhIfDSvakLBeg4jLGOSxLY0y38DocYzMXe0exJXkLxqHKMznpgGrbps0TPfSK0c3q2PxQLczCD3n63HxbN8U9FPyGeMrz59PPpkwIDAQAB
    -----END PUBLIC KEY-----</Value>
            <Ref/>
        </AssignVariable>
        <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
        <AssignTo createNew="false" transport="http" type="request"/>
    </AssignMessage>
    

    Note: It is always recommended to use KeyValueMap instead of directly using the values like private key or secret etc.

    • Next step is to use JWTPolicy to verify the JWT token using the public key assigned in the previous step. Mention the variable name which has the public key as its value in PublicKey tag. The final XML file will look something like below.
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <VerifyJWT async="false" continueOnError="false" enabled="true" name="Verify-JWT-1">
        <DisplayName>Verify JWT-1</DisplayName>
        <Algorithm>RS256</Algorithm>
        <PublicKey>
            <Value ref="public.key"/>
        </PublicKey>
        <Subject>Subject from the JWT token</Subject>
        <Issuer>http://issue-of-the-token.com</Issuer>
        <Audience>aud1,aud2</Audience>
    </VerifyJWT>
    

    Note : Additional inputs can be verified using AdditionalClaims tag.
    Click on AssignMessage, JWTPolicy or KeyValueMap to know more.