Autentisering
OAuth 2.0 authorization code med PKCE, tokenförnyelse med rotation, livslängder och återkallning.
Klirr använder OAuth 2.0 med authorization code. Flödet speglar Fortnox apps.fortnox.se/oauth-v1. Det finns inga API-nycklar. Varje token är knuten till en organisation, den som användaren valde vid godkännandet, så du skickar aldrig något organisations-id.
| Endpoint | URL |
|---|---|
| Auktorisering | GET https://app.klirr.ai/api/v1/oauth-v1/auth |
| Token | POST https://app.klirr.ai/api/v1/oauth-v1/token |
| Metadata (RFC 8414) | https://app.klirr.ai/.well-known/oauth-authorization-server |
Livslängder
| Vad | Livslängd |
|---|---|
| Auktoriseringskod | 10 minuter, engångs |
| Access token | 1 timme (expires_in: 3600) |
| Refresh token | 45 dagar, engångs (roteras) |
Tokens är opaka strängar. Tolka dem inte.
Klientregistrering
Klirr registrerar klienten åt dig (se Snabbstart). Du får client_id, client_secret, de scopes klienten får begära och de redirect-URI:er som är registrerade.
Krav på redirect-URI:
- absolut URL, utan fragment (
#) och utan användarnamn eller lösenord https, med undantag förhttp://localhostochhttp://127.0.0.1- måste matcha den registrerade exakt
1. Skicka användaren till godkännandet
GET https://app.klirr.ai/api/v1/oauth-v1/auth
?response_type=code
&client_id=<client_id>
&redirect_uri=<redirect_uri>
&scope=invoice customer
&state=<slumpad_sträng>
&code_challenge=<code_challenge>
&code_challenge_method=S256| Parameter | Krav | Beskrivning |
|---|---|---|
response_type | obligatorisk | Måste vara code. |
client_id | obligatorisk | |
redirect_uri | obligatorisk | Exakt den registrerade. |
scope | obligatorisk | Mellanslagsseparerade scopes. Minst ett, alla måste vara tillåtna för klienten. |
state | obligatorisk | CSRF-skydd. Returneras oförändrat. Krävs alltid för konfidentiella klienter, precis som hos Fortnox. |
code_challenge | rekommenderad | PKCE: base64url, 43–128 tecken. |
code_challenge_method | med code_challenge | Bara S256. plain avvisas. |
PKCE är valfritt för konfidentiella klienter med client_secret, men skickar du en code_challenge måste du också skicka code_verifier när koden växlas. Vi rekommenderar PKCE för alla klienter.
Skapa verifier och challenge:
import { createHash, randomBytes } from 'node:crypto';
const codeVerifier = randomBytes(32).toString('base64url'); // 43 tecken
const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');Användaren loggar in i Klirr, väljer organisation och godkänner de scopes du begärt. Därefter skickas webbläsaren till:
<redirect_uri>?code=<code>&state=<state>Om något går fel efter att redirect-URI:n verifierats skickas användaren i stället tillbaka med ?error=...&error_description=...&state=... (till exempel invalid_scope, invalid_request eller unsupported_response_type). Ett okänt client_id eller en oregistrerad redirect-URI skickas aldrig vidare till din URI, utan användaren ser en felsida i Klirr.
Kontrollera alltid att state är det du skickade.
2. Växla koden mot tokens
Content-Type måste vara application/x-www-form-urlencoded. JSON avvisas.
Klientautentisering sker med HTTP Basic (client_id:client_secret, rekommenderat) eller med client_id och client_secret i kroppen. Använd inte båda samtidigt.
curl -X POST https://app.klirr.ai/api/v1/oauth-v1/token \
-u "<client_id>:<client_secret>" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code=<code> \
--data-urlencode redirect_uri=<redirect_uri> \
-d code_verifier=<code_verifier>redirect_uri måste vara samma som i steg 1.
Svar:
{
"access_token": "<access_token>",
"refresh_token": "<refresh_token>",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "invoice customer"
}3. Anropa API:t
GET /api/v1/3/invoices HTTP/1.1
Host: app.klirr.ai
Authorization: Bearer <access_token>4. Förnya med refresh token
curl -X POST https://app.klirr.ai/api/v1/oauth-v1/token \
-u "<client_id>:<client_secret>" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=refresh_token \
-d refresh_token=<refresh_token>Refresh tokens roteras. Varje förnyelse ger ett nytt par och förbrukar det gamla refresh token.
- Skickar du samma refresh token igen inom 30 sekunder (till exempel två processer som förnyar samtidigt) får du tillbaka samma par som första anropet gav.
- Återanvänds det efter 30 sekunder tolkas det som en stöld: hela kopplingen återkallas (
invalid_grant, "Refresh token har återanvänts. All åtkomst är återkallad av säkerhetsskäl.") och användaren måste godkänna på nytt.
Låt bara en process åt gången förnya, och spara det nya refresh token innan du använder access token.
Återkalla åtkomst
Det finns ingen revoke-endpoint för klienter. Användaren återkallar åtkomsten i Klirr under InställningarAnslutna appar med Återkalla. Därefter avvisas både access token och refresh token direkt (401 respektive invalid_grant). Samma sak gäller om Klirr stänger av klienten.
Fel från OAuth-endpoints
OAuth-endpointerna svarar enligt RFC 6749, inte i Fortnox-form:
{ "error": "invalid_grant", "error_description": "Auktoriseringskoden har gått ut" }error | Status | Exempel |
|---|---|---|
invalid_request | 400 | Fel Content-Type, code eller code_verifier saknas. |
invalid_client | 401 | Fel klientuppgifter. Svaret har WWW-Authenticate: Basic realm="klirr". |
invalid_grant | 400 | Koden är ogiltig, använd eller utgången; redirect_uri matchar inte; code_verifier stämmer inte; refresh token ogiltigt, utgånget eller återkallat. |
unsupported_grant_type | 400 | Annat än authorization_code eller refresh_token. |
invalid_request | 429 | För många anrop mot token-endpointen. |
server_error | 500 | Internt fel. |