Skip to main content

I need to connect to an api that requires a bearer token in the header for authentication.

This token should be generated with a jwk.

 

Example to request a token (there are public available examples from the service, so no secrets from my side):

POST /op/v1/token HTTP/1.1
Host: authenticatie.vlaanderen.be
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&
audience=8ed36a78-8443-11ec-b334-83e86b606670&
audience=9e6a512c-8443-11ec-ae2c-8700eb2a0cde&
scope=org_api_appread%20org_api_appwrite&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
client_assertion=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIyODM1ODgxNC01YzIwLTRjMTMtYmJmZi1kYjVkZDhjNGFlOTMiLCJzdWIiOiIyODM1ODgxNC01YzIwLTRjMTMtYmJmZi1kYjVkZDhjNGFlOTMiLCJhdWQiOiJodHRwczovL2F1dGhlbnRpY2F0aWUudmxhYW5kZXJlbi5iZS9vcCIsImV4cCI6MTU5MjIwODA2MCwianRpIjoiRGt6bmpzdTQzZHprZDN6amQ1IiwiaWF0IjoxNTkyMjA4MDAwfQ.3dPodaVhJ2d3cXWn0v2YGeZqs5XScJF2lm4MaweDnf4

 

the client assertion is a jwt that contains the following:
 

{
"iss": "28358814-5c20-4c13-bbff-db5dd8c4ae93",
"sub": "28358814-5c20-4c13-bbff-db5dd8c4ae93",
"aud": "https://authenticatie.vlaanderen.be/op",
"exp": 1592208060,
"jti": "Dkznjsu43dzkd3zjd5",
"iat": 1592208000
}

 

The client assertion is an encrypted string where a private key (a pem file) is used to encode the jwt.

Is there a way this can be achieved in FME? Currently this is done in an old python script so looking for a way to either achieve this in FME or looking into upgrading the python script.

(used python libs are pyjwt & cryptography)

Not that i’ve had to authenticate with an API like this previously, but it is something you’d need to do in Python. I would suggest you submit an idea for this: https://community.safe.com/ideas

 

the pyjwt library isn’t a default library that's part of FMEs Python, so you would either need to install that, or create it using default libraries (see below for an example - thanks ChatGPT). You cna use the PythonCaller transformer to include Python code into your workspace.

 

import base64
import hmac
import hashlib
import json

# Helper function for Base64Url encoding
def base64url_encode(data: bytes) -> str:
return base64.urlsafe_b64encode(data).rstrip(b'=').decode('utf-8')

# Helper function for Base64Url decoding
def base64url_decode(encoded_data: str) -> bytes:
padded_data = encoded_data + '=' * (4 - len(encoded_data) % 4)
return base64.urlsafe_b64decode(padded_data)

# Create JWT Header and Payload
header = {
"alg": "HS256", # HMAC using SHA-256 hash algorithm
"typ": "JWT"
}

payload = {
"sub": "1234567890",
"name": "John Doe",
"admin": True
}

secret = "your-256-bit-secret"

# Encode Header and Payload
encoded_header = base64url_encode(json.dumps(header).encode())
encoded_payload = base64url_encode(json.dumps(payload).encode())

# Create the Signature
message = f"{encoded_header}.{encoded_payload}".encode()
signature = hmac.new(secret.encode(), message, hashlib.sha256).digest()
encoded_signature = base64url_encode(signature)

# Create JWT Token
jwt_token = f"{encoded_header}.{encoded_payload}.{encoded_signature}"
print(jwt_token)

 


Thanks for the information, I will suggest an idea about this. Funny thing, copilot (as chat gpt isn’t allowed in the company as it uses the prompt to train itself further, while copilot claims it doesn’t (when logged in)) gives something different but similar :)

It works in my use case so now I have a miniconda env with the necessary python lib, as I’m not a big fan on installing extra python stuff in the FME python folder).

The scripts generates a textfile that contains my bearer token which I read via attribute file reader. I’ve put this in a custom transformer so that I can re-use it where I need it.

 

Brings me to the next challenge: I got a timeout on the bearer of 1 hour. I need to do thousands of api calls (need to fetch 300k features while the limit per call is 100). So wondering what the best approach would be here as I don’t want to use the CT every api call (seems a bit a lazy approach and generates overhead at my side but also at server side).
So using the http caller with multiple threads will speed up the process, but as soon as I pass the hour I’ll get 401 errors. 

So does someone have an idea on how to do this kind of looping but still have multi threaded api calls?


Edit, will post this as a new question


Reply