OAuth

OAuth

Benarkan orang log masuk ke klien anda dengan akaun Atli mereka, dan bertindak bagi pihak mereka, dengan OAuth 2.1 standard: penemuan, PKCE, token muat semula yang berputar dan pembatalan. Mana-mana klien boleh menggunakannya: aplikasi, bot, laman web, pelayan atau pembantu AI.

Bila perlu menggunakannya

  • Pembantu AI ialah salah satu klien sedemikian. Apabila menyambung ke pelayan MCP Atli, mereka melog masuk orang dengan cara ini dengan sendirinya, jadi tiada apa yang perlu dibina untuk mereka. Aliran yang sama digunakan oleh setiap klien.

  • Mana-mana klien yang bertindak bagi pihak seseorang: aplikasi telefon, laman web, bot atau pelayan yang menunjukkan eSIM seseorang atau membeli satu untuknya, dengan akaun Atli mereka sendiri. Daftarkan klien anda sendiri, dan tokennya berfungsi pada API Atli.

  • Orang yang log masuk melalui klien milik anda, atau di alamat rakan kongsi anda pada pelayan MCP, boleh dikaitkan dengan anda sebagai rujukan anda. Ciri ini dimatikan secara lalai, dan Atli boleh menghidupkannya untuk akaun anda. Walau apa pun, klien anda boleh sendiri mengkreditkan orang yang dibawanya kepada anda: lihat "Dapatkan kredit untuk orang yang anda bawa" di bawah.

  • Hanya akaun yang boleh dilog masuk semula di tempat lain boleh disambungkan: akaun dengan e-mel, termasuk melalui Google, Apple atau Facebook, atau dengan Telegram atau WhatsApp.

Cara ia berfungsi

API Atli ialah pelayan kebenaran. Log masuk dan skrin persetujuan berada di heyatli.com, di /connect, jadi aplikasi anda tidak pernah melihat kata laluan. Baca setiap endpoint daripada metadata, jangan tulis terus dalam kod. Alamat di sini mengikut suis Sandbox dan Produksi.

Daftarkan klien sekali. Kemudian, untuk setiap orang: hantar mereka ke endpoint kebenaran dengan cabaran PKCE, ambil kod yang mereka bawa balik, tukarkan dengan token dan panggil API dengan token akses. Muat semula apabila ia tamat tempoh, dan batalkan apabila mereka log keluar.

curl https://api.heyatli.com/.well-known/oauth-authorization-server

{
  "issuer": "https://api.heyatli.com",
  "authorization_endpoint": "https://api.heyatli.com/oauth2/authorize",
  "token_endpoint": "https://api.heyatli.com/oauth2/token",
  "revocation_endpoint": "https://api.heyatli.com/oauth2/revoke",
  "registration_endpoint": "https://api.heyatli.com/oauth2/register",
  "jwks_uri": "https://api.heyatli.com/oauth2/jwks",
  "scopes_supported": ["api", "offline_access"],
  "code_challenge_methods_supported": ["S256"],
  "client_id_metadata_document_supported": true,
  …
}

Untuk apa sesuatu token

Setiap permintaan menyatakan alamat yang menjadi sasaran tokennya, sebagai resource (RFC 8707), dan token hanya berfungsi di situ. Alamat yang bukan salah satu daripada ini, atau kod rujukan yang tidak wujud, ditolak dengan invalid_target, jadi kedua-duanya tidak boleh diteka.

AlamatSiapa boleh memintanyaApa yang dilakukan token
API Atli
https://api.heyatli.com
Hanya klien milik anda

Token bearer untuk API, yang bertindak sebagai orang itu, seperti token daripada /login.

Pelayan MCP Atli
https://mcp.heyatli.com
Mana-mana klien

Membolehkan pembantu bertindak bagi pihak orang itu melalui alat MCP.

Alamat rakan kongsi anda
https://mcp.heyatli.com/r/YOUR_CODE
Mana-mana klien

Sama, dan orang itu boleh dikaitkan dengan anda sebagai rujukan anda, setelah ciri itu dihidupkan untuk akaun anda.

Mendaftar klien

Ada tiga cara. Untuk aplikasi anda sendiri, daftarkan klien anda sendiri: hanya jenis ini yang boleh meminta API Atli.

  1. Klien anda sendiri

    Selepas log masuk dengan akaun anda sendiri, panggil POST /user/oauth-clients. Anda boleh ada 10. Pilih public untuk apa-apa yang berjalan pada peranti orang lain, seperti aplikasi telefon atau halaman dalam pelayar mereka, dan confidential untuk pelayan yang boleh menyimpan rahsia.

    client_secret klien sulit ada dalam jawapan ini dan tiada di tempat lain. Jika anda kehilangannya, gantikan dengan POST /user/oauth-clients/{id}/rotate-secret. Akaun anda perlu ada e-mel, kerana klien memerlukan kod rujukan; satu kod akan dibuat untuk anda jika anda belum ada.

    curl https://api.heyatli.com/user/oauth-clients \
      -H 'Authorization: Bearer YOUR_TOKEN' \
      -H 'Content-Type: application/json' \
      -d '{ "name": "Travel Bot",
            "redirect_uris": ["https://bot.example/oauth/callback"],
            "client_type": "confidential" }'
    
    {
      "client_id": "atli_client_7f3a9c2e…",
      "client_secret": "…",
      "client_type": "confidential",
      …
    }
  2. Pendaftaran dinamik

    POST /oauth2/register (RFC 7591), tanpa log masuk. Begitulah kebanyakan pembantu mendaftar. Ia membenarkan 10 pendaftaran sejam dari satu alamat, dan klien yang tidak pernah disambungkan oleh sesiapa dipadam selepas 30 hari.

    curl https://api.heyatli.com/oauth2/register \
      -H 'Content-Type: application/json' \
      -d '{ "client_name": "Travel Bot",
            "redirect_uris": ["https://bot.example/oauth/callback"] }'
    
    {
      "client_id": "atli_client_…",
      "token_endpoint_auth_method": "none",
      …
    }
  3. Dokumen metadata ID klien

    Gunakan alamat https yang anda hos sebagai client_id, yang menyajikan dokumen JSON yang menerangkan klien. Atli membacanya apabila seseorang log masuk, jadi tiada apa yang perlu didaftarkan. Spesifikasi MCP lebih mengutamakan cara ini berbanding pendaftaran dinamik.

    // Served at https://bot.example/oauth/client.json
    {
      "client_id": "https://bot.example/oauth/client.json",
      "client_name": "Travel Bot",
      "redirect_uris": ["https://bot.example/oauth/callback"],
      "token_endpoint_auth_method": "none"
    }
  • URI ubah hala dipadankan dengan tepat. Setiap satu ialah https, atau http pada localhost, 127.0.0.1 atau [::1], di mana hanya port boleh berbeza, tanpa serpihan. Satu klien boleh ada sehingga 10.

Melog masuk seseorang

Aliran kod kebenaran, dengan PKCE (S256), yang digunakan oleh setiap klien, awam atau sulit.

  1. Buat pasangan PKCE

    Simpan verifier untuk pertukaran kod, dan hantar cabaran SHA-256nya bersama permintaan. Buat pasangan baharu, dan state baharu, untuk setiap log masuk.

    const base64url = (bytes) =>
      btoa(String.fromCharCode(...bytes))
        .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
    
    const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
    const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));
    const challenge = base64url(new Uint8Array(digest));
    const state = base64url(crypto.getRandomValues(new Uint8Array(16)));
  2. Hantar mereka untuk log masuk

    Buka endpoint kebenaran dalam pelayar mereka. scope ialah api, dan offline_access menambah token muat semula. Mereka log masuk dan bersetuju di heyatli.com/connect, yang menunjukkan nama klien anda, ke mana ia menghantar mereka kembali, dan sama ada mereka akan menjadi rujukan seseorang. Permintaan sah selama 10 minit.

    const url = new URL('https://api.heyatli.com/oauth2/authorize');
    url.search = new URLSearchParams({
      response_type: 'code',
      client_id: CLIENT_ID,
      redirect_uri: 'https://bot.example/oauth/callback',
      scope: 'api offline_access',
      state,
      code_challenge: challenge,
      code_challenge_method: 'S256',
      // Atli's API, for a client you own; or the MCP server, https://mcp.heyatli.com
      resource: 'https://api.heyatli.com',
    }).toString();
    window.location.assign(url);
  3. Ambil kod yang mereka bawa balik

    Mereka kembali ke URI ubah hala anda dengan code, state anda dan iss. Semak bahawa state ialah milik anda dan iss ialah pengeluarnya. Jika mereka menolak, ia membawa error=access_denied sebaliknya.

    https://bot.example/oauth/callback?code=4bd81f…&state=…&iss=https%3A%2F%2Fapi.heyatli.com
    
    https://bot.example/oauth/callback?error=access_denied&state=…&iss=https%3A%2F%2Fapi.heyatli.com
  4. Tukar kod dengan token

    Hantar kod bersama verifier, redirect_uri dan resource yang sama, serta kelayakan klien anda jika ada. Kod sah selama 60 saat dan berfungsi sekali sahaja: menghantarnya dua kali, atau dengan verifier yang salah, menamatkan akses orang itu, kerana mungkin orang lain memilikinya.

    Token akses sah selama expires_in saat, iaitu 15 minit. Token muat semula sentiasa disertakan bersamanya.

    curl https://api.heyatli.com/oauth2/token \
      -u 'CLIENT_ID:CLIENT_SECRET' \
      -d grant_type=authorization_code \
      -d code=THE_CODE \
      -d code_verifier=THE_VERIFIER \
      -d redirect_uri=https://bot.example/oauth/callback \
      -d client_id=CLIENT_ID \
      -d resource=https://api.heyatli.com
    
    {
      "access_token": "…",
      "token_type": "Bearer",
      "expires_in": 900,
      "refresh_token": "…",
      "scope": "api offline_access"
    }

Kekalkan mereka log masuk

Apabila token akses tamat tempoh, minta yang baharu dengan token muat semula. Anda boleh meminta scope yang lebih sempit, tetapi tidak sekali-kali yang lebih luas.

Token muat semula berubah setiap kali digunakan, jadi simpan yang baharu setiap kali. Jika sesuatu jawapan tidak pernah sampai kepada anda, menghantar token lama sekali lagi dalam tempoh singkat akan mendapat jawapan yang sama. Selepas itu, token lama bermakna ia telah disalin, dan akses orang itu tamat.

curl https://api.heyatli.com/oauth2/token \
  -u 'CLIENT_ID:CLIENT_SECRET' \
  -d grant_type=refresh_token \
  -d refresh_token=THE_REFRESH_TOKEN \
  -d client_id=CLIENT_ID \
  -d resource=https://api.heyatli.com

Gunakan token

Hantar sebagai Authorization: Bearer ACCESS_TOKEN, ke alamat yang menjadi sasaran token itu dikeluarkan dan tidak ke tempat lain.

Token untuk API Atli bertindak sebagai orang itu pada setiap laluan API, seperti token daripada /login. Anggap ia legap: kandungannya boleh berubah.

Token untuk pelayan MCP ialah JWT yang ditandatangani dengan EdDSA. Pelayan menyemaknya dengan kunci di /oauth2/jwks, berdasarkan kidnya, dan menyemak bahawa audnya ialah alamatnya sendiri. Ia tidak mengandungi e-mel atau butiran lain: hanya sub (id orang itu), scope, grant_id dan masa-masanya.

curl https://api.heyatli.com/esims \
  -H 'Authorization: Bearer ACCESS_TOKEN'

Dapatkan kredit untuk orang yang anda bawa

Mengaitkan orang yang log masuk melalui klien anda, atau di alamat rakan kongsi anda, dengan anda dimatikan secara lalai, dan Atli boleh menghidupkannya untuk akaun anda. Sama ada ia hidup atau tidak, klien anda boleh sendiri mengaitkan orang yang telah log masuk dengan kod rujukan anda, menggunakan token akses mereka: POST /user/referral/redeem dengan code anda.

result menyatakan apa yang berlaku: ok bermakna mereka telah dikaitkan, already bermakna mereka sudah ada perujuk, notnew bahawa mereka pernah membeli, own bahawa ia kod anda sendiri, dan notfound bahawa kod itu tidak wujud. Hanya orang tanpa perujuk yang belum membeli boleh dikaitkan, dan sekali sahaja.

curl https://api.heyatli.com/user/referral/redeem \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "code": "YOUR_CODE" }'

{
  "success": true,
  "result": "ok",
  "message": "…",
  "discount_percent": 10
}

Log keluar dan tarik balik akses

Apabila seseorang log keluar daripada aplikasi anda, batalkan token muat semula mereka. Itu menamatkan akses mereka dalam klien anda, bersama setiap token padanya. Ia menjawab 200 walaupun untuk token yang tidak dikenalinya, jadi ia tidak boleh digunakan untuk mengetahui token mana yang wujud.

Orang juga boleh melihat aplikasi yang telah mereka sambungkan dan menarik balik akses sendiri (GET /user/oauth-grants, DELETE /user/oauth-grants/{id}). Sejak itu klien anda tidak boleh mendapat token baharu, jadi anggap muat semula yang ditolak sebagai log keluar.

curl https://api.heyatli.com/oauth2/revoke \
  -u 'CLIENT_ID:CLIENT_SECRET' \
  -d token=THE_REFRESH_TOKEN \
  -d client_id=CLIENT_ID

Ralat

Endpoint token, pembatalan dan pendaftaran menjawab dengan format ralat OAuth sendiri, {"error": "invalid_grant", "error_description": "…"}, dan bukan format biasa API. Buat keputusan berdasarkan error, jangan sekali-kali berdasarkan penerangan. Setiap jawapan daripada endpoint token membawa Cache-Control: no-store.

  • invalid_grant: kod telah digunakan atau tamat tempoh, verifier salah, atau token muat semula digunakan semula selepas tempoh tenggangnya. Log masuk orang itu semula.

  • invalid_target: resource bukan alamat yang boleh menjadi sasaran token, atau menamakan kod rujukan yang tidak wujud.

  • invalid_client: kelayakan klien salah atau tiada. Setiap jenis gagal dengan cara yang sama.

  • invalid_scope: muat semula meminta lebih daripada yang dibenarkan oleh orang itu.