HTTP client for BankID API with mTLS (mutual TLS) support.
This module provides a native Elixir implementation for communicating with the Swedish BankID API.
Features
- mTLS authentication using client certificates
- Support for both test and production environments
- Certificate validation using BankID's CA certificates
- JSON request/response handling
- Proper error handling for BankID API errors
Usage
# Create a client (test mode by default)
client = BankID.HTTPClient.new()
# Make a request
{:ok, response} = BankID.HTTPClient.post(client, "/auth", %{endUserIp: "192.168.1.1"})
Summary
Functions
Convert known BankID API keys to atoms safely.
Convert map with string keys to atom keys (deep conversion).
Create a new HTTP client for BankID API.
Make a POST request to the BankID API.
Resolve certificate path from the bundled certificates.
Types
@type t() :: %BankID.HTTPClient{ base_url: String.t(), cacerts_der: [binary()], cert_der: binary(), key_der: {atom(), binary()}, test_server: boolean() }
BankID HTTP client struct containing configuration for API communication.
Fields
base_url- Base URL for the BankID API endpointtest_server- Boolean indicating if using test servercert_der- Client certificate in DER formatkey_der- Client private key in DER format with key typecacerts_der- List of CA certificates in DER format for server verification
Functions
Convert known BankID API keys to atoms safely.
Only known BankID API keys are converted to atoms to prevent atom exhaustion attacks. Unknown keys remain as strings.
Parameters
key- String key to convert
Returns
Atom key if known, otherwise the original key
Convert map with string keys to atom keys (deep conversion).
This function safely converts JSON response keys from strings to atoms for consistency within the application. Only known BankID API keys are converted to atoms to prevent atom exhaustion attacks.
Parameters
data- Any data structure containing string keys
Returns
The same data structure with known string keys converted to atoms
Create a new HTTP client for BankID API.
Configuration
Certificates are configured via application config. Defaults point to bundled test certificates, so no configuration is needed for testing.
For Testing (Default)
No configuration needed - uses bundled test certificates:
# Uses test server and test certificates automatically
client = BankID.HTTPClient.new()For Production
You can configure certificates in two ways:
Option 1: Direct Certificate Content (Recommended for Serverless)
Provide certificate content directly from environment variables. This is ideal for serverless deployments (AWS Lambda, Google Cloud Functions, etc.) where file system access is limited.
Add to your config/runtime.exs:
config :bankid,
base_url: "https://appapi2.bankid.com/rp/v6.0",
cert: System.get_env("BANKID_CERT"),
key: System.get_env("BANKID_KEY"),
cacert: System.get_env("BANKID_CACERT")Then set environment variables with full PEM content:
export BANKID_CERT="-----BEGIN CERTIFICATE-----
MIIEyjCCArKgAwIBAgIIG8/maByOzV4w...
-----END CERTIFICATE-----"
export BANKID_KEY="-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAAS...
-----END PRIVATE KEY-----"Option 2: File Paths (Traditional)
Provide paths to certificate files on the file system:
Add to your config/runtime.exs:
config :bankid,
base_url: "https://appapi2.bankid.com/rp/v6.0",
cert_path: System.get_env("BANKID_CERT_PATH"),
key_path: System.get_env("BANKID_KEY_PATH")Then set environment variables:
export BANKID_CERT_PATH="/etc/bankid/production-cert.pem"
export BANKID_KEY_PATH="/etc/bankid/production-key.pem"Configuration Options
All configuration is via config :bankid. Certificate options have a priority order:
Priority 1: Direct Content
:cert- Client certificate PEM content (string):key- Client private key PEM content (string):cacert- CA certificate PEM content (string)
Priority 2: File Paths
:cert_path- Path to client certificate PEM file:key_path- Path to client private key PEM file:cacert_path- Path to CA certificate PEM file
Priority 3: Bundled Test Certificates
- If neither content nor paths are provided, bundled test certificates are used
Other Options
:base_url- BankID API endpoint (defaults to test server)
Examples
# Testing - uses defaults
client = BankID.HTTPClient.new()
# Production with direct content
client = BankID.HTTPClient.new()
# Production with file paths
client = BankID.HTTPClient.new()
Make a POST request to the BankID API.
Parameters
client- The HTTP client structpath- API endpoint path (e.g., "/auth", "/collect")body- Request body (will be JSON encoded)
Returns
{:ok, response_body}- Successful response with decoded JSON{:error, reason}- Error with reason
Resolve certificate path from the bundled certificates.
This is used internally to locate certificates in the priv/certs directory.