Kanıt entegrasyon rehberi

Kanıt, kullanıcılarının Netflix gibi platformlardaki verilerini, şifrelerini ya da hesaplarını görmeden doğrulamanı sağlar. Sana sadece istediğin alanlar ve bunların attestor imzalı kanıtı döner.

1Backend'in App Key + Secret ile bir doğrulama oturumu açar → verifyUrl ve listenToken alır.
2Uygulaman (web ya da mobil) verifyUrl'i açar ve listenToken ile socket'ten dinlemeye başlar.
3Kullanıcı senin logonla açılan sayfada platforma giriş yapar ve paylaşacağı içeriği seçer.
4Kanıt üretilir. Sonuç socket ile anında, webhook ile backend'ine gelir. Varsa kullanıcı redirectUrl ile uygulamana döner.

Hesap ve uygulama

  1. Geliştirici hesabı oluştur.
  2. Panelde Yeni uygulama de. App Key, App Secret ve Webhook Secret sadece bu anda gösterilir: kopyala, backend'inin ortam değişkenlerine koy.
  3. Uygulama sayfasında İstenebilecek veriler bölümünden istediğin veri türlerini aç (ör. Netflix · İzleme geçmişi).
  4. İstersen Webhook URL gir.
App Secret asla web sitene, mobil uygulamana ya da bir repoya girmemeli. Mobil uygulamalar da oturumu kendi backend'leri üzerinden açar.

Logo ve marka

Kullanıcı doğrulama sayfasında senin uygulama adını ve logonu görür: "Uygulaman, Netflix hesabındaki izleme geçmişini doğrulamak istiyor". Ayarlamak için:

  1. Panel → uygulamanı seç.
  2. Genel kartında Uygulama adını düzenle.
  3. Logo bölümünden kare bir PNG, JPG ya da WEBP yükle (en fazla 512KB, önerilen 256×256).

Güvenlik için SVG kabul edilmez. Dosya türü uzantıya değil, içeriğine bakılarak kontrol edilir.

1. Backend: oturum aç

Her doğrulama için backend'inde bir oturum aç. Dönen verifyUrl ve listenToken'ı uygulamana (web/mobil) gönder. Oturum 15 dakika geçerlidir ve tek kullanımlıktır.

npm install @kanit/sdk

import { KanitClient } from '@kanit/sdk'

const kanit = new KanitClient({
  appKey: process.env.KANIT_APP_KEY,
  appSecret: process.env.KANIT_APP_SECRET,
  baseUrl: 'https://portal.vuid.app',
})

// ör. POST /api/kanit/start (kendi endpoint'in)
const session = await kanit.createSession({
  provider: 'netflix',
  claim: 'viewing-history',
  reference: user.id,                    // opsiyonel, sonuçta geri döner
  redirectUrl: 'benimapp://kanit-tamam', // opsiyonel: mobil deep link ya da https
})

res.json({
  sessionId: session.sessionId,
  verifyUrl: session.verifyUrl,
  listenToken: session.listenToken,
})

2. Sonucu al

Sonucu almanın üç yolu var, birlikte de kullanılabilir:

YolNeredeNe zaman kullan
SocketWeb / mobil uygulamaEkranda anında "doğrulandı" göstermek için. Olaylar
WebhookBackendİndirim, rozet gibi kalıcı işlemler için. İmzalıdır. Doğrulama
GET /v1/sessions/:idBackendWebhook yoksa ya da tekrar kontrol için.
Kalıcı bir işlem yapmadan önce sonucu backend'inde doğrula (webhook ya da GET). İstemciden gelen veriye tek başına güvenme.

Web sitesi

Masaüstünde doğrulama yeni sekmede, telefonda aynı sekmede açılır.

import { listenSession, openVerification } from '@kanit/sdk/browser'

const session = await fetch('/api/kanit/start', { method: 'POST' }).then(r => r.json())

openVerification(session.verifyUrl)

const stop = listenSession({
  baseUrl: 'https://portal.vuid.app',
  sessionId: session.sessionId,
  listenToken: session.listenToken,
  onStatus: e => console.log('durum:', e.status),      // starting, login, select, proving
  onCompleted: e => showSuccess(e.fields),              // ör. { title, series, date }
  onFailed: e => showError(e.error),
})

Mobil uygulama

Mobilde akış aynıdır, üç ek nokta var:

  1. Oturumu backend'in açar. App Secret uygulamanın içine asla konmaz.
  2. verifyUrl'i uygulama içi tarayıcıda aç. iOS'ta ASWebAuthenticationSession, Android'de Custom Tabs. WebView kullanma: sayfanın güvenliği için gerçek tarayıcı gerekir.
  3. redirectUrl'e uygulamanın deep link'ini ver (ör. benimapp://kanit-tamam). Kullanıcı bitirince uygulamana döner. URL'e ?kanit_session=…&kanit_status=completed|failed eklenir.

Sonucu socket ile anında dinleyebilir ya da kullanıcı döndüğünde backend'ine sorabilirsin.

// npm install @kanit/sdk socket.io-client react-native-inappbrowser-reborn
import InAppBrowser from 'react-native-inappbrowser-reborn'
import { listenSession } from '@kanit/sdk/browser'

async function verifyNetflix() {
  // backend'in createSession({ ..., redirectUrl: 'benimapp://kanit-tamam' }) yapar
  const s = await fetch('https://senin-backend.com/api/kanit/start', { method: 'POST' })
    .then(r => r.json())

  const stop = listenSession({
    baseUrl: 'https://portal.vuid.app',
    sessionId: s.sessionId,
    listenToken: s.listenToken,
    onCompleted: e => setVerified(e.fields),
    onFailed: e => Alert.alert('Doğrulanamadı', e.error ?? ''),
  })

  // doğrulama bitince 'benimapp://kanit-tamam?...' ile kendiliğinden kapanır
  await InAppBrowser.openAuth(s.verifyUrl, 'benimapp://kanit-tamam', {
    ephemeralWebSession: true,
  })
}

Socket olayları

Socket.IO kullanılır. Her dilde resmi istemcisi var (JS, Swift, Kotlin/Java, Dart, Python…). Bağlantı adresi: https://portal.vuid.app/sessions (namespace /sessions, transport: websocket).

Dinlemeye başla

Bağlanınca listen gönder. Ack olarak { ok: true } döner. Geç bağlansan bile o anki durum hemen gelir.

socket.emit('listen', { sessionId, listenToken }, ack => { /* { ok: true } */ })

Gelen olay: status

{
  "sessionId": "e8205...",
  "status": "completed",
  "reference": "user-42",
  "step": { "name": "generating-zk-proofs", "proofsDone": 2, "proofsTotal": 4 },  // sadece proving'de
  "fields": { "movieID": "81257204", "title": "Season 1: ...", "series": "Wednesday", "date": "10/16/26" },
  "proof": { ... },   // attestor imzalı kanıt
  "error": null
}
statusAnlamı
createdOturum açıldı, kullanıcı sayfayı henüz açmadı
startingGüvenli tarayıcı açılıyor
loginKullanıcı platforma giriş yapıyor
selectKullanıcı paylaşacağı içeriği seçiyor
provingKanıt üretiliyor (step ile ilerleme)
completedBitti: fields ve proof dolu
failed / expiredBaşarısız ya da 15 dakika doldu: error

Webhook

Uygulama ayarlarına Webhook URL girersen, oturum bitince (session.completed /session.failed) oraya POST yapılır. Başarısız olursa 3 kez denenir.

Her isteğin X-Kanit-Signature: t=<unix>,v1=<imza> başlığı vardır. İmza: HMAC_SHA256(webhookSecret, t + "." + hamGövde). 5 dakikadan eski isteği reddet.

import express from 'express'
import { verifyWebhook } from '@kanit/sdk'

// ham gövde gerekli: express.json() değil express.text()
app.post('/webhooks/kanit', express.text({ type: '*/*' }), (req, res) => {
  try {
    const event = verifyWebhook(req.body, req.get('x-kanit-signature'), process.env.KANIT_WEBHOOK_SECRET)
    if (event.status === 'completed') grantDiscount(event.reference, event.fields)
    res.sendStatus(200)
  } catch {
    res.sendStatus(400)
  }
})

HTTP API

Uç noktaYetkiAçıklama
POST /v1/sessionsApp Key + SecretOturum aç. Gövde: provider, claim, ops. reference, redirectUrl
GET /v1/sessions/:idApp Key + SecretOturumun durumu, fields ve proof
GET /v1/attestor—Kanıtları imzalayan attestor adresi (bağımsız doğrulama için)
GET /providers—Platformlar, veri türleri ve dönen alanlar

Yetki başlıkları: X-App-Key, X-App-Secret. Hatalar { statusCode, message } döner. 403: veri türü uygulamada açık değil ya da aylık kota doldu.

Veri türleri

providerclaimDönen alanlar
netflixviewing-history
İzleme geçmişi
movieIDtitleseriesdatewatchedAt
netflixviewing-history-all
İzleme geçmişi (tümü)
history
netflixmy-list
Listem
movieIDtitle
prime-videoYakında
disney-plusYakında
hbo-maxYakında

Güvenlik

  • Kullanıcının şifresi, oturum çerezi ve diğer verileri sana hiçbir zaman gelmez, bizde de saklanmaz.
  • Her doğrulama tek kullanımlık, izole bir tarayıcıda yapılır. İş bitince tarayıcı ve profili silinir.
  • Kanıt, oturuma bağlıdır (sessionId): başka bir oturumda tekrar kullanılamaz.
  • Gelen her kanıt, attestor imzası ve veri türünün izin verdiği alanlar açısından kontrol edilir. Sadece tanımlı alanlar sana iletilir.
  • listenToken sadece o oturumu dinleyebilir. App Secret yalnızca backend'de kalmalı.