Access Token
This guide documents the implementation of the Access Token step in an OAuth 2.0 flow customized for the Interactive Brokers (IBKR) Web API. Unlike standard OAuth 2.0 client credentials grants that transmit a static client secret, this implementation uses a signed JWT client assertion (per RFC 7523, the JWT Bearer grant extension), constructed as a compact JWS and signed with RSA-SHA256.
This is the first of two OAuth 2.0 steps in the IBKR flow:
- Access Token (documented here)
- Bearer Token / SSO Session establishment (exchanges the Access Token for a gateway session — a separate flow)
Construct the Endpoint URL
The Access Token endpoint is always accessed via POST over HTTPS, using application/x-www-form-urlencoded content.
Assemble the JWT Header and Claims
Implementation note: compute_client_assertion() is a shared helper reused later for the Bearer Token step, where it builds a different claim set (ip, credential, exp of 24 hours) based on the target url. Only the branch matching {oauth2Url}/api/v1/token is relevant to this step.
Base64URL-Encode the Header and Claims
Implementation details:
- Both
headerandclaimsare serialized to compact JSON (no whitespace) before encoding, to ensure a deterministic byte representation. - Encoding uses base64url (per RFC 4648 §5), not standard base64 —
+and/are substituted with-and_, and trailing=padding is stripped. This is required by the JWS compact serialization spec, and standardbase64.b64encodeoutput must be manually converted, as shown. - The header and claims segments are joined with a literal
.to form the unsignedpayload.
Sign the Payload with RSA-SHA256
Process:
- Encode the
payload(encoded_header.encoded_claims) to UTF-8 bytes. - Compute the SHA-256 digest.
- Sign the digest using PKCS#1 v1.5 padding with your RSA private key (
jwtPrivateKey— aCrypto.PublicKey.RSAkey object). - Base64URL-encode the raw signature bytes using the same encoding helper as the header/claims — not standard base64.
Assemble the Client Assertion (JWS)
Concatenating encoded_header, encoded_claims, and encoded_signature with . separators produces the compact JWS serialization:
This full string is the client_assertion value submitted in the token request. It is self-contained and stateless — no separate signing request or nonce exchange is required, unlike the OAuth 1.0a Request Token flow.
Construct the Token Request Body
Unlike the OAuth 1.0a Request Token step, no Authorization header is used here — all credentials are conveyed via the signed assertion in the form body.
Execute the Request and retrieve the access_token
The request is sent as a standard form-encoded POST; the signed assertion inside form_data carries all authentication material.
The returned access_token should be retained for the subsequent Bearer Token / SSO Session step — it is passed as a Bearer credential in that request’s Authorization header and is not a long-lived credential; treat it as scoped to the immediate session-establishment exchange.

