Encoding & Decoding
Encoding and decoding operations in variable substitution allow you to transform data between different formats, including Base64 encoding/decoding and URL encoding/decoding.
Overview
Encoding operations enable you to: - Encode data to Base64 format - Decode Base64 data back to original format - Encode special characters for URLs - Decode URL-encoded strings - Handle character encoding transformations
Base64 Encoding
Basic Base64 Encoding
Encode a string to Base64:
Syntax
Parameters:
- INPUT_STRING - String to encode to Base64
Examples
Encoding a client secret:
Encoding realm name:
Encoding from environment variable:
Result:
- HelloWorld! → SGVsbG9Xb3JsZCE=
- my-secret-password → bXktc2VjcmV0LXBhc3N3b3Jk
Base64 Decoding
Basic Base64 Decoding
Decode a Base64 string back to original format:
{
"realm": "$(base64Decoder:SGVsbG9Xb3JsZCE=)",
"secret": "$(base64Decoder:bXktc2VjcmV0LXBhc3N3b3Jk)"
}
Syntax
Parameters:
- BASE64_STRING - Base64 encoded string to decode
Examples
Decoding a stored secret:
{
"clients": [
{
"clientId": "my-app",
"secret": "$(base64Decoder:$(file:UTF-8:/run/secrets/encoded-secret))"
}
]
}
Decoding from environment variable:
Result:
- SGVsbG9Xb3JsZCE= → HelloWorld!
- bXktc2VjcmV0LXBhc3N3b3Jk → my-secret-password
URL Encoding
Basic URL Encoding
Encode special characters for safe use in URLs:
{
"redirectUri": "$(urlEncoder:Hello World!)",
"webOrigin": "$(urlEncoder:https://example.com/path with spaces)"
}
Syntax
Parameters:
- INPUT_STRING - String to URL encode
Examples
Encoding redirect URIs:
{
"clients": [
{
"clientId": "my-app",
"redirectUris": [
"$(urlEncoder:https://example.com/callback?param=value)",
"$(urlEncoder:https://example.com/path with spaces)"
]
}
]
}
Encoding web origins:
{
"clients": [
{
"clientId": "my-app",
"webOrigins": [
"$(urlEncoder:https://example.com)",
"$(urlEncoder:https://app.example.com)"
]
}
]
}
Result:
- Hello World! → Hello%20World%21
- https://example.com/path with spaces → https%3A%2F%2Fexample.com%2Fpath%20with%20spaces
URL Decoding
Basic URL Decoding
Decode URL-encoded strings back to original format:
{
"redirectUri": "$(urlDecoder:Hello%20World%21)",
"webOrigin": "$(urlDecoder:https%3A%2F%2Fexample.com)"
}
Syntax
Parameters:
- ENCODED_STRING - URL-encoded string to decode
Examples
Decoding redirect URIs:
{
"clients": [
{
"clientId": "my-app",
"redirectUris": [
"$(urlDecoder:https%3A%2F%2Fexample.com%2Fcallback%3Fparam%3Dvalue)"
]
}
]
}
Decoding from file:
Result:
- Hello%20World%21 → Hello World!
- https%3A%2F%2Fexample.com → https://example.com
Common Use Cases
Base64 for Secrets
Storing secrets in encoded format:
{
"clients": [
{
"clientId": "backend-api",
"secret": "$(base64Decoder:$(env:ENCODED_SECRET))"
}
]
}
Encode secret before deployment:
Encode
Expected output:
bXktc2VjcmV0LXBhc3N3b3Jk
Export
URL Encoding for Redirect URIs
Safe redirect URI handling:
{
"clients": [
{
"clientId": "my-app",
"redirectUris": [
"$(urlEncoder:$(env:APP_URL)/callback)",
"$(urlEncoder:$(env:APP_URL)/login?return=$(env:RETURN_URL))"
]
}
]
}
Chaining Operations
Encode then decode (for demonstration):
{
"original": "Hello World!",
"encoded": "$(base64Encoder:Hello World!)",
"decoded": "$(base64Decoder:$(base64Encoder:Hello World!))"
}
URL encode from file:
Character Encoding Considerations
UTF-8 Handling
Base64 with UTF-8 characters:
{
"realm": "$(base64Encoder:Production-Realm-中文)",
"displayName": "$(base64Encoder:Application-special-chars-é)"
}
URL encoding with UTF-8:
Special Characters
Common special characters:
- Space → %20
- ! → %21
- # → %23
- & → %26
- = → %3D
- ? → %3F
Example:
Best Practices
Base64 Usage
- For Transmission Only: Use Base64 for data transmission, not security
- Document Encoding: Clearly document when and why Base64 is used
- Consistent Encoding: Use the same encoding method throughout
- Test Decoding: Verify decoding works after encoding
URL Encoding Usage
- Always Encode URLs: Always URL-encode user-provided URLs
- Encode Components: Encode URL components, not entire URLs
- Validate After Decoding: Validate URLs after decoding
- Use HTTPS: Always use HTTPS for sensitive redirects
General Practices
- Prefer File Operations: For secrets, use file operations instead of encoding
- Test Thoroughly: Test encoding/decoding with real data
- Handle Errors: Implement proper error handling
- Document Dependencies: Document external encoding/decoding requirements
Performance Considerations
Encoding Overhead
- Base64: ~33% size increase
- URL Encoding: Variable size increase depending on special characters
- Processing Time: Minimal overhead for typical operations
Optimization Tips
- Encode Once: Encode values once and store, don't encode on every import
- Cache Results: Cache encoded/decoded values when possible
- Batch Operations: Process multiple values in single operation
- Monitor Performance: Profile encoding/decoding in large configurations
Complete Examples
Client Configuration with Encoding
secure-encoding-realm.json:
{
"realm": "secure-encoding-test",
"displayName": "$(base64Decoder:U2VjdXJlIEVuY29kaW5nIFRlc3QgUmVhbG0)",
"enabled": true,
"clients": [
{
"clientId": "$(base64Decoder:ZnJvbnRlbmQtYXBw)",
"name": "$(base64Decoder:U2VjdXJlIEZyb250ZW5kIEFwcGxpY2F0aW9u)",
"enabled": true,
"publicClient": true,
"standardFlowEnabled": true,
"redirectUris": [
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZhcHAuc2VjdXJlLWV4YW1wbGUuY29tJTJGY2FsbGJhY2s)",
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZhcHAuc2VjdXJlLWV4YW1wbGUuY29tJTJGc2lsZW50LXJlbmV3)"
],
"webOrigins": [
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZhcHAuc2VjdXJlLWV4YW1wbGUuY29t)"
]
},
{
"clientId": "$(base64Decoder:YmFja2VuZC1hcGk)",
"name": "$(base64Decoder:U2VjdXJlIEJhY2tlbmQgQVBJ)",
"enabled": true,
"publicClient": false,
"standardFlowEnabled": true,
"directAccessGrantsEnabled": true,
"secret": "$(base64Decoder:YmFja2VuZF9hcGlfc2VjcmV0X2hpZ2hfc2VjdXJpdHlfMjAyNA)",
"redirectUris": [
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZhcGkuc2VjdXJlLWV4YW1wbGUuY29tJTJGYXV0aCUyRmNhbGxiYWNr)"
],
"webOrigins": [
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZhcGkuc2VjdXJlLWV4YW1wbGUuY29t)"
]
},
{
"clientId": "$(base64Decoder:YmFja2VuZC1hcGk)",
"name": "$(base64Decoder:U2VjdXJlIEJhY2tlbmQgQVBJ)",
"enabled": true,
"publicClient": false,
"standardFlowEnabled": true,
"directAccessGrantsEnabled": true,
"secret": "$(base64Decoder:YmFja2VuZF9hcGlfc2VjcmV0X2hpZ2hfc2VjdXJpdHlfMjAyNA)",
"redirectUris": [
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZhcGkuc2VjdXJlLWV4YW1wbGUuY29tJTJGYXV0aCUyRmNhbGxiYWNr)"
],
"webOrigins": [
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZhcGkuc2VjdXJlLWV4YW1wbGUuY29t)"
]
},
{
"clientId": "$(base64Decoder:bW9iaWxlLWFwcA)",
"name": "$(base64Decoder:U2VjdXJlIE1vYmlsZSBBcHBsaWNhdGlvbg)",
"enabled": true,
"publicClient": true,
"standardFlowEnabled": true,
"redirectUris": [
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZtb2JpbGUuc2VjdXJlLWV4YW1wbGUuY29tJTJGY2FsbGJhY2s)",
"$(urlDecoder:bXlzZWN1cmVhcHAlM0ElMkYlMkY)"
],
"webOrigins": [
"$(urlDecoder:aHR0cHMlM0ElMkYlMkZtb2JpbGUuc2VjdXJlLWV4YW1wbGUuY29t)"
]
}
],
"roles": {
"realm": [
{
"name": "$(base64Decoder:YWRtaW4)",
"description": "$(base64Decoder:U3lzdGVtIGFkbWluaXN0cmF0b3Igd2l0aCBmdWxsIGFjY2Vzcw)"
},
{
"name": "$(base64Decoder:bW9kZXJhdG9y)",
"description": "$(base64Decoder:Q29udGVudCBtb2RlcmF0b3Igd2l0aCBtYW5hZ2VtZW50IHJpZ2h0cw)"
},
{
"name": "$(base64Decoder:dXNlcg)",
"description": "$(base64Decoder:U3RhbmRhcmQgdXNlciB3aXRoIGJhc2ljIGFjY2Vzcw)"
}
]
},
"users": [
{
"username": "$(base64Decoder:c2VjdXJlX2FkbWlu)",
"email": "$(base64Decoder:YWRtaW5Ac2VjdXJlLWV4YW1wbGUuY29t)",
"enabled": true,
"firstName": "$(base64Decoder:U2VjdXJl)",
"lastName": "$(base64Decoder:QWRtaW4)",
"realmRoles": ["$(base64Decoder:YWRtaW4)"],
"credentials": [
{
"type": "password",
"value": "$(base64Decoder:U2VjdXJlQWRtaW5QYXNzMTIzIQ)",
"temporary": false
}
]
},
{
"username": "$(base64Decoder:bW9kZXJhdG9yX3VzZXI)",
"email": "$(base64Decoder:bW9kZXJhdG9yQHNlY3VyZS1leGFtcGxlLmNvbQ)",
"enabled": true,
"firstName": "$(base64Decoder:TW9kZXJhdG9y)",
"lastName": "$(base64Decoder:VXNlcg)",
"realmRoles": ["$(base64Decoder:bW9kZXJhdG9y)", "$(base64Decoder:dXNlcg)"],
"credentials": [
{
"type": "password",
"value": "$(base64Decoder:TW9kZXJhdG9yUGFzczQ1Ng)",
"temporary": false
}
]
},
{
"username": "$(base64Decoder:ZW5kX3VzZXI)",
"email": "$(base64Decoder:dXNlckBzZWN1cmUtZXhhbXBsZS5jb20)",
"enabled": true,
"firstName": "$(base64Decoder:RW5k)",
"lastName": "$(base64Decoder:VXNlcg)",
"realmRoles": ["$(base64Decoder:dXNlcg)"],
"credentials": [
{
"type": "password",
"value": "$(base64Decoder:RW5kVXNlclBhc3M3ODk)",
"temporary": false
}
]
}
]
}
Step 1: Encode Your Values
Before creating the JSON file, encode your sensitive values:
To encode use this syntax for Base64
echo -n "Secure Encoding Test Realm" | base64
echo -n "my_super_secret_jwt_key_2024" | base64
echo -n "admin@secure-example.com" | base64
To encode use this syntax for UrlEncoding
python3 -c "import urllib.parse; print(urllib.parse.quote('https://secure.example.com/webhooks/callback'))"
python3 -c "import urllib.parse; print(urllib.parse.quote('https://app.secure-example.com/callback'))"
Step 2: Run Import
java -jar ./target/keycloak-config-cli.jar \
--keycloak.url="http://<keycloak-url>" \
--keycloak.user="<admin-username>" \
--keycloak.password="<admin-password>" \
--import.var-substitution.enabled=true \
--import.files.locations=secure-encoding-realm.json
Step 3: Verify
Verify in UI
In the Keycloak Admin Console, verify:
- Realm name:
secure-encoding-test - Display name:
Secure Encoding Test Realm - Clients:
frontend-app,backend-api, andmobile-appcreated successfully - Users:
secure_admin,moderator_user, andend_usercreated successfully

What This Demonstrates
This example demonstrates all encoding and decoding operations:
- Base64 Encoding: Converting secrets to Base64 format
- Base64 Decoding: Converting Base64 back to original format
- URL Encoding: Encoding URLs for safe transport
- URL Decoding: Decoding URLs back to original format
- Nested Operations: Using encode-then-decode chains
- Complex URLs: Encoding URLs with parameters and special characters
- Client Configuration: Using encoding in client secrets and URLs
- User Attributes: Storing encoded/decoded values in user attributes
Security Benefits
No Plain Text Secrets: Sensitive data never appears in plain text in configuration files
Version Control Safe: Encoded values can be safely committed to version control
Runtime Decoding: Values are only decoded in memory during import
Audit Trail: Encoded values maintain auditability without exposing secrets
Compliance: Helps meet security compliance requirements for secret management
Best Practices for Secure Encoding
- Use Strong Base64: Always use standard Base64 encoding
- Separate Keys: Store encoding keys separately from configuration
- Environment-Specific: Use different encoded values per environment
- Regular Rotation: Rotate and re-encode sensitive values regularly
- Access Control: Limit access to files with encoded values
- Validation: Validate decoded values during import process
Next Steps
- Overview - Variable substitution introduction
- File Operations - File content and properties
- Environment Variables - Environment variable access
- JavaScript Substitution - Advanced JavaScript evaluation