: Enable logging on the token exchange but redact code_verifier and refresh_token before persisting. 7. Comparison with Other Accounting APIs | Feature | lexoffice | DATEV | Xero | QuickBooks | |---------|-----------|-------|------|-------------| | OAuth2 | ✅ PKCE | ✅ PKCE | ✅ PKCE | ✅ PKCE | | Refresh token rotation | ✅ (recommended) | ❌ | ✅ | ✅ | | Sandbox environment | ✅ | ✅ | ✅ | ✅ | | Scope discovery via metadata | ✅ OIDC Discovery | ❌ | ✅ | ✅ |
# Exchange data = "grant_type": "authorization_code", "code": auth_code, "redirect_uri": self.redirect_uri, "client_id": self.client_id, "code_verifier": self.code_verifier resp = requests.post(self.TOKEN_URL, data=data) resp.raise_for_status() tokens = resp.json() return tokens # contains access_token, refresh_token, expires_in lexoffice.login
def handle_callback(self, callback_url): """Parse callback, verify state, exchange code for tokens.""" parsed = urlparse(callback_url) query = parse_qs(parsed.query) if "state" not in query or query["state"][0] != self.state: raise ValueError("Invalid state parameter – possible CSRF attack") if "code" not in query: raise ValueError("No authorization code received") auth_code = query["code"][0] : Enable logging on the token exchange but
lexoffice’s strength is strict PKCE enforcement and well‑structured OpenID Connect Discovery ( /.well-known/openid-configuration ). The lexoffice.login mechanism is a robust implementation of OAuth 2.0 + PKCE, suitable for both server‑side and public client applications. Developers must correctly generate the PKCE pair, validate the state parameter, and store tokens securely. By following the reference implementation and security recommendations in this paper, integration can achieve both usability and a high security level. The lexoffice