Search code examples
gravitee

How to base 64 encode a string using Gravitee EL


Context

In Gravitee 4.2, I'm configuring a V2 API for which I'm extracting the user id from an OAuth2 access token from the incoming request and add an Authorization Basic header to this request with the user:password encoded in base 64 before forwarding it to my backend.

Extracting the user id from the token is working fine using the JSON Web Tokens policy.

To add the Authorization header to the request I'm using the Transform Headers policy. But I cannot manage writing a working Gravitee Expression Language to add the header with the "user:password" part base 64 encoded. And I find it really hard to debug the EL. I didn't find built-in solution to base 64 encode a string.

The documentation states that GEL extends Spring EL but I couldn't find "advanced" example.

I'm trying to use the java.util.Base64 class for the encoding.

This EL doesn't work:

{T(java.util.Base64).getEncoder().encodeToString({T(java.lang.String).valueOf('test:test').getBytes()})}

But this subpart is working. It get the bytes array from the provided String :

{T(java.lang.String).valueOf('test:test').getBytes()}

Questions

  1. Is there another, simpler, way to add (dynamically) an authorization header to the requests ?
  2. Is it possible to write an EL to encode a String in base 64 ?

Solution

    1. Regarding your use case, I don't see an easier way to do it.
    2. Gravitee Expression Language does not come with all the java classes usable by default. For your use case, you need to whitelist the classes you need (java.util.Base64 and java.util.Base64$Encoder).

    With gravitee.yml On the gravitee.yml file of the gateway, you can configure the expression language whitelist in the dedicated section:

    el:
      # Allows to define which methods or classes are accessible to the Expression Language engine (/!\ caution, changing default whitelist may expose you to security issues).
      # A complete list of default whitelist methods can be found here (https://raw.githubusercontent.com/gravitee-io/gravitee-expression-language/master/src/main/resources/whitelist).
      whitelist:
        # Allows to define if the specified list of method or classes should be append to the default one or should replace it.
        # We recommend you to always choose 'append' unless you absolutely know what you are doing.
    #    mode: append
        # Define the list of classes or methods to append (or set) to made accessible to the Expression Language.
        # start with 'method' to allow a specific method (complete signature).
        # start with 'class' to allow a complete class. All methods of the class will then be accessible.
        list:
          # Ex: allow access to DateTimeFormatter.ofLocalizedDate(FormatStyle) method
          # - method java.time.format.DateTimeFormatter ofLocalizedDate java.time.format.FormatStyle
          # Ex: allow access to all methods of DateTimeFormatter class
           - class java.util.Base64
           - class java.util.Base64$Encoder
    

    With environment variables

    You can configure your gateway using those environment variables:

    gravitee.el.whitelist.list[0]=class java.util.Base64
    gravitee.el.whitelist.list[1]=class java.util.Base64$Encoder
    

    About the expression you used

    You can simplify it a bit like that (you do not need to use String.valueOf):

    {T(java.util.Base64).getEncoder().encodeToString('test:test'.getBytes())}
    

    Edit

    If the syntax java.util.Base64$Encoder used in the whitelist doesn't work, replacing the $ by a . might work instead (especially in case of environment variable declaration in a docker compose yaml file for example): java.util.Base64.Encoder

    Have a good day!