🔐 Using the ACF Plugin to Generate a JWT Authentication Header
When integrating with APIs, it’s common to encounter a requirement for JWT-based authentication. JSON Web Tokens (JWT) are a compact and secure way to pass claims between systems and are commonly used in modern web APIs.
A JWT consists of three parts:
- A base64URL-encoded JSON header
- A base64URL-encoded JSON payload (the “claims”)
- A base64URL-encoded signature of the two previous parts, signed using a private key or a shared secret
These parts are concatenated with periods (.), resulting in a structure like:
<base64url(header)>.<base64url(payload)>.<base64url(signature)>
Let’s build this directly in the ACF language using the new SignWithCert() function.
🧪 Example: ACF Function to Generate a JWT
Here’s a complete ACF function that generates a JWT using a private key stored in a container field (PEM or PKCS#12 format):
Note: Requre ACF-Plugin version 1.7.5.4 or later to run
function GenJWTtoken (container cert)
string pass = "secret123"; // The certificate password
JSON header = JSON ("alg", "RS256", "typ", "JWT");
// Optional: Add certificate to the header for verification
header ["x5c"] = ExtractCertChainBase64(cert, pass);
// Define the payload.
JSON payload = JSON(
"sub", "1234567890",
"name", "John Doe",
"admin", true,
"iat", long(Now(0)), // Unix timestamp in Zulu Time
"exp", long(Now(0) + 3600));
// Option 3 = base64url, no newlines.
string encodedHeader = Base64_Encode(string(header), 3);
string encodedPayload = Base64_Encode(string(payload), 3);
string jwttosign = encodedHeader + "." + encodedPayload;
string signature = SignWithCert(jwttosign, cert, 3, pass);
string jwt = jwttosign + "." + signature;
return jwt;
end
🔍 What this function does:
- Accepts a certificate as a container field (PEM or PKCS#12 format).
- Constructs a JWT header and payload (hardcoded here for testing).
- Encodes both parts using base64url format.
- Signs the header and payload using the provided certificate and password.
- Returns the full JWT string.
You could of course parameterize sub, name, or expiration logic for real-world usage.
🔑 Creating a Test Certificate
To test this, you can generate a self-signed certificate and convert it into a PKCS#12 bundle using OpenSSL:
# Generate private key
openssl genpkey -algorithm RSA -aes256 -pass pass:secret123 -out testkey.pem -pkeyopt rsa_keygen_bits:2048
# Generate self-signed cert
openssl req -new -x509 -key testkey.pem -passin pass:secret123 -out testcert.pem -days 365 -subj "/CN=ACF-Test"
# Bundle key and cert into PKCS#12 format
openssl pkcs12 -export -inkey testkey.pem -in testcert.pem -out testbundle.p12 -passin pass:secret123 -passout pass:secret123
# Optional: Extract public key for verification
openssl rsa -in testkey.pem -pubout -passin pass:secret123 -out public.pem
Now you can insert testbundle.p12 into a container field in FileMaker and use it with your ACF function.
🧪 Running the Function in FileMaker
In a test layout, add the container field and a button to run the function below.

Create a script to call your JWT function like this:
Set Field [ Test::Result ; ACF_Run("GenJWTtoken"; Test::testcontainer) ]
Click the button and check the result. You’ll get something like:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTc1MjM4OTQ4OCwiZXhwIjoxNzUyMzkzMDg4fQ.nwlwSeb-z...
To verify it, paste the result into jwt.io

✅ Using the JWT in an API Call
Now that we have a valid JWT, let’s use it in a login request:
function DoLoginToOurAPI (container cert, string somePostContent)
string url = "https://someapiservice.com/login/v2";
string header1 = "Content-Type: application/json";
string auth = "Authorization: Bearer " + GenJWTtoken(cert);
string res = HTTP_POST(url, somePostContent, header1, auth);
return res;
end
This example uses HTTP_POST() to call the login endpoint, setting the content type and adding the Authorization header.
🔐 For Real-World Usage
In a real-world solution, the container field holding the certificate is typically stored in a preference table that is related to your main data table. The container field does not need to be visible on the current layout. You can manage it from a preferences layout, updating or replacing the certificate when it expires. For example, the certificate might be accessed via a relationship like:
Invoices_Preferences::CertContainer
You can customize the GenJWTtoken function to accept additional parameters for values to be included in the JWT payload. Alternatively, you can access FileMaker fields or variables directly from within the function.
Your actual use case or API documentation will specify the exact structure of the header and payload—what claims are required, expiration rules, and so on. Be sure to adapt the function to match those requirements carefully.
⚠️ Version Check:
Before using the JWT function, your script should verify that the correct version of the ACF plugin is installed. This ensures the client isn’t running the code with an outdated version that lacks necessary functions. You can do this in your script like so:

🎯 Summary
With the ACF plugin’s new signing functions, generating and using JWTs in FileMaker is now quick, secure, and fully scriptable.
You can:
- Sign JWTs with PEM or PKCS#12 private keys
- Use the
SignWithCert()andSignWithSecret()functions - Pass JWTs in the
Authorizationheader to authenticate API calls - Handle time-based claims like
iatandexpusing native ACF functions
This opens up a world of modern integrations with APIs using secure, industry-standard authentication — directly from FileMaker.
