Entegrasyon örnekleri

v2.3 login: Browser SDK Mode A + müşteri backend Pending Login / Login Result (accepted). SDK JWT, imza veya sertifika döndürmez.

Tüm örnekleri indir (.zip) Swagger UI CDN demo

Akış

Browser → Müşteri: Pending Login → correlation_id
Browser → api.ksign.tr: challenge (Publishable Key + Origin + correlation_id)
Browser ↔ Agent: WebSocket LOGIN_START … LOGIN_SUCCESS
api → Müşteri: Login Result (KSign JWT + user)
Müşteri → api: { success, status: "accepted", correlation_id }
Müşteri: kendi uygulama oturumu (cookie / session JWT)

Kategori

Tarayıcıda Agent keşfi + WebSocket Mode A login. Müşteri origin üzerinde host edin.

Araç

cdn.ksign.tr — ekstra build yok.

cdn-login.html ham dosya
<!DOCTYPE html>
<html lang="tr">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>KSign — Browser Login Örneği</title>
  <style>
    :root { color-scheme: light dark; font-family: "Segoe UI", system-ui, sans-serif; line-height: 1.5; }
    body { max-width: 40rem; margin: 2rem auto; padding: 0 1rem; }
    h1 { font-size: 1.35rem; margin-bottom: 0.25rem; }
    p.sub { color: #666; margin-top: 0; }
    label { display: block; font-weight: 600; margin-top: 1rem; }
    input, button {
      width: 100%; box-sizing: border-box; margin-top: 0.35rem;
      padding: 0.55rem 0.65rem; font: inherit;
    }
    .actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }
    button { width: auto; min-width: 9rem; cursor: pointer; }
    button:disabled { opacity: 0.55; cursor: not-allowed; }
    pre {
      background: #111; color: #eee; padding: 1rem; border-radius: 8px;
      overflow: auto; min-height: 7rem; white-space: pre-wrap; word-break: break-word;
    }
    .ok { color: #0a7; }
    .err { color: #c33; }
    a { color: #3d8bfd; }
    .note {
      margin-top: 1rem; padding: 0.75rem 0.9rem; border-radius: 8px;
      background: color-mix(in srgb, #3d8bfd 12%, transparent);
      font-size: 0.9rem;
    }
  </style>
</head>
<body>
  <p><a href="/examples/">← Örnekler</a></p>
  <h1>KSign Browser Login</h1>
  <p class="sub">v2.3 WebSocket Mode A — CDN: <code>cdn.ksign.tr</code></p>

  <div class="note">
    Bu sayfa referans içindir. Tam login için sayfayı <strong>müşteri origin</strong>
    (Allowed Origin) üzerinde host edin. PIN yalnızca yerel Agent’a gider; SDK JWT döndürmez.
  </div>

  <label for="backendUrl">KSign API</label>
  <input id="backendUrl" type="url" value="https://api.ksign.tr" />

  <label for="publishableKey">Publishable Key</label>
  <input id="publishableKey" type="text" value="ksign_pk_test_019f49100001700080000000000100000000000000000001" autocomplete="off" />

  <label for="pendingUrl">Pending Login URL (müşteri backend, opsiyonel)</label>
  <input id="pendingUrl" type="url" placeholder="https://app.example/api/esign/pending" />

  <label for="correlationId">correlation_id</label>
  <input id="correlationId" type="text" placeholder="Pending’den veya elle UUID" autocomplete="off" />

  <label for="pin">Token PIN</label>
  <input id="pin" type="password" autocomplete="off" placeholder="USB token PIN" />

  <label for="certificateId">Certificate thumbprint (opsiyonel)</label>
  <input id="certificateId" type="text" placeholder="SHA-256 — boşsa tek sertifika seçilir" />

  <div class="actions">
    <button id="btnPending" type="button">Pending Login</button>
    <button id="btnDetect" type="button">Detect Agent</button>
    <button id="btnLogin" type="button">Login with e-Sign</button>
  </div>

  <label for="output">Sonuç</label>
  <pre id="output">Hazır.</pre>

  <script src="https://cdn.ksign.tr/browser.min.js"></script>
  <script>
    (function () {
      const $ = (id) => document.getElementById(id);
      const out = $('output');

      function log(msg, kind) {
        out.textContent = (kind === 'err' ? '[HATA] ' : kind === 'ok' ? '[OK] ' : '') + msg;
        out.className = kind === 'err' ? 'err' : kind === 'ok' ? 'ok' : '';
      }

      $('btnPending').addEventListener('click', async () => {
        try {
          const url = $('pendingUrl').value.trim();
          if (!url) {
            $('correlationId').value = crypto.randomUUID();
            log('Yerel correlation_id üretildi (Pending URL yok).\n' + $('correlationId').value, 'ok');
            return;
          }
          const res = await fetch(url, {
            method: 'POST',
            headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
            credentials: 'include',
            body: '{}',
          });
          const data = await res.json().catch(() => ({}));
          if (!res.ok) throw new Error(data.message || ('HTTP ' + res.status));
          const id = data.correlation_id || data.correlationId;
          if (!id) throw new Error('correlation_id yok');
          $('correlationId').value = id;
          log('Pending OK\n' + JSON.stringify(data, null, 2), 'ok');
        } catch (e) {
          log(e instanceof Error ? e.message : String(e), 'err');
        }
      });

      $('btnDetect').addEventListener('click', async () => {
        try {
          if (!window.KSignSDK) throw new Error('KSignSDK yüklenemedi');
          const result = await window.KSignSDK.discoverAgent();
          log(
            'Agent bulundu\npingUrl: ' + result.pingUrl +
            '\nagentBaseUrl: ' + result.agentBaseUrl +
            '\nwsLoginUrl: ' + result.wsLoginUrl,
            'ok'
          );
        } catch (e) {
          log(e instanceof Error ? e.message : String(e), 'err');
        }
      });

      $('btnLogin').addEventListener('click', async () => {
        $('btnLogin').disabled = true;
        try {
          if (!window.KSignSDK) throw new Error('KSignSDK yüklenemedi');
          const publishableKey = $('publishableKey').value.trim();
          const backendUrl = $('backendUrl').value.trim().replace(/\/+$/, '');
          const pin = $('pin').value;
          const correlationId = $('correlationId').value.trim() || crypto.randomUUID();
          if (!publishableKey) throw new Error('publishableKey gerekli');
          if (!pin) throw new Error('PIN gerekli');

          const client = new window.KSignSDK.KSign({ publishableKey, backendUrl });
          const options = {
            pin,
            correlationId,
            onEvent: (ev) => console.log('[ksign]', ev.type, ev),
          };
          const cert = $('certificateId').value.trim();
          if (cert) options.certificateId = cert;

          const result = await client.login(options);
          log(
            'Login tamamlandı (JWT yok)\n' + JSON.stringify(result, null, 2) +
            '\n\nUygulama oturumu: müşteri backend Login Result accepted sonrası.',
            'ok'
          );
        } catch (e) {
          const body = e && e.code
            ? { code: e.code, message: e.message, challengeId: e.challengeId, backendCode: e.backendCode }
            : String(e);
          log('Login başarısız\n' + JSON.stringify(body, null, 2), 'err');
        } finally {
          $('btnLogin').disabled = false;
        }
      });

      log(
        'Sayfa origin: ' + location.origin + '\n' +
        '1) Pending Login → correlation_id\n' +
        '2) Detect Agent → /ping\n' +
        '3) Login → challenge + WS … LOGIN_SUCCESS\n' +
        'Kaynak: /examples/browser/login.js'
      );
    })();
  </script>
</body>
</html>

Zip: ./scripts/pack-docs-examples.sh · Deploy: cd update && make update-docs · CDN: cdn.ksign.tr