ErtisAuth

Cihaz Kodu Akışı

Klavyesi olmayan cihazlarda giriş.

Cihaz kodu akışı, şifre yazmanın zahmetli olduğu cihazlarda kullanıcıların giriş yapmasını sağlar: akıllı TV'ler, set üstü kutular, kiosk'lar, oyun konsolları, komut satırı araçları. OAuth 2.0 device authorization grant modelini izler (RFC 8628).

  1. Cihaz ErtisAuth'tan bir kod ister. İki değer alır: ekranda gösterilecek kısa bir kullanıcı kodu (user code) ve kendinde tutacağı uzun bir cihaz kodu (device code).
  2. Kullanıcı, telefonunda ya da bilgisayarında zaten giriş yapmış olduğu web sitenizi veya uygulamanızı açar ve kullanıcı kodunu girer.
  3. Siteniz hangi cihazın istekte bulunduğunu gösterir ve kullanıcının onu onaylamasına ya da reddetmesine izin verir.
  4. Bu arada cihaz koduyla sürekli sorgulama yapan cihaz, o kullanıcı için bir token çifti alır.
akış
Cihaz                                     ErtisAuth                          Siteniz (kullanıcı girişli)
  │  POST /codes                              │                                          │
  │─────────────────────────────────────────▶ │                                          │
  │  { user_code: "K7Q2XD9M",                 │                                          │
  │    device_code: "…", interval: 5 }        │                                          │
  │◀───────────────────────────────────────── │                                          │
  │  ekranda K7Q2-XD9M                        │         kullanıcı K7Q2XD9M girer          │
  │                                           │   GET /codes/K7Q2XD9M  (cihaz bilgisi)    │
  │                                           │ ◀──────────────────────────────────────── │
  │                                           │   POST /codes/K7Q2XD9M/approve            │
  │                                           │ ◀──────────────────────────────────────── │
  │  POST /codes/token { device_code }        │                                          │
  │  (her `interval` saniyede)                │                                          │
  │─────────────────────────────────────────▶ │                                          │
  │  201 { access_token, … }                  │                                          │
  │◀───────────────────────────────────────── │                                          │

Neden iki kod? Kullanıcı kodunu ekranı görebilen herkes görür; bu yüzden yalnızca isteği tanımlar. Token yalnızca cihazdan hiç çıkmayan cihaz koduyla alınabilir.

Kod politikaları#

Kullanıcı kodlarının biçimini bir kod politikası (code policy) belirler; her membership kullandığı politikayı code_policy alanında belirtir.

json
{
	"_id": "66f1c0d2a4b5c6d7e8f90160",
	"name": "TV Codes",
	"slug": "tv-codes",
	"description": "8 characters, easy to read on a TV",
	"length": 8,
	"contains_letters": true,
	"contains_digits": true,
	"expires_in": 300,
	"membership_id": "66f1c0d2a4b5c6d7e8f90123"
}
AlanZorunluAçıklama
nameevetGörünen ad.
slughayırVerilmezse addan türetilir. Membership'in code_policy alanı bunu gösterir.
lengthevetHer kullanıcı kodunun karakter sayısı; her karakter kümesi için 5 ile 12 arası.
contains_letters, contains_digitsen az biriKarakter kümesi: harfler, rakamlar ya da ikisi birden. İkisini birden içeren kodlarda kolayca karıştırılan karakterler (0, O, 1, I) kullanılmaz.
expires_inevetBir kodun onaylanıp kullanılabileceği süre, saniye cinsinden; 1 ile 1800 (30 dakika) arası.

Bu sınırların dışındaki bir politika, oluşturulurken ya da güncellenirken 400 ModelValidationError ile reddedilir.

Uzunluğu ekranı düşünerek seçin: bir TV'de 5 ile 8 karakter rahatça okunur ve yazılır. Kullanıcı kodu tek başına token veremediği için kısa bir kod güvenlidir; daha uzun bir kod çoğunlukla, onay bekleyen başka birinin kodunu tahmin etmeyi zorlaştırır.

Endpoint'ler#

Tüm route'lar /memberships/{membershipId} altındadır.

MetotRouteYetki
GET/code-policies/{id}code-policies.read.{id}
GET/code-policiescode-policies.read
POST/code-policies/_querycode-policies.read
POST/code-policiescode-policies.create
PUT/code-policies/{id}code-policies.update.{id}
DELETE/code-policies/{id}code-policies.delete.{id}
DELETE/code-policiescode-policies.delete

Membership'in kullandığı bir politika silinemez (409 TokenCodePolicyInUse). Tekrarlanan bir slug 409 TokenCodePolicyAlreadyExists, değişiklik içermeyen bir güncelleme 409 IdenticalDocumentError döner.

Akışı açma#

  1. Bir politika oluşturun:
    shell
    curl -X POST https://auth.example.com/memberships/<membership_id>/code-policies \
    	-H 'Authorization: Bearer <access_token>' \
    	-H 'Content-Type: application/json' \
    	-d '{ "name": "TV Codes", "length": 8, "contains_letters": true, "contains_digits": true, "expires_in": 300 }'
  2. Membership'te "code_policy": "tv-codes" değerini ayarlayın.

Token kodları#

Tüm route'lar /memberships/{membershipId} altındadır.

MetotRouteAçıklamaKim çağırırYetki
POST/codesKod üretmecihaz (ya da backend'i)tokens.create
GET/codes/{user_code}Bir kodun cihazını göstermeonay sayfanıztokens.create, Bearer token
POST/codes/{user_code}/approveKodu onaylamaonay sayfanıztokens.create, Bearer token
POST/codes/{user_code}/denyKodu reddetmeonay sayfanıztokens.create, Bearer token
POST/codes/tokenCihaz koduyla token almacihazyok

1. Bir kod üretin#

http
POST /memberships/{membershipId}/codes
Authorization: Basic <application_id>:<secret>
X-IpAddress: 203.0.113.42
X-UserAgent: LivingRoomTV/2.4 (Tizen 7.0)

Cihaz bunu backend'iniz üzerinden ya da rolünde yalnızca tokens.create yetkisi olan, cihazlara ayrılmış bir uygulamanın kimlik bilgileriyle çağırır. Bir cihaza gömülen kimlik bilgileri çıkarılabilir; bu yüzden onlara başka hiçbir yetki vermeyin.

X-IpAddress ve X-UserAgent cihazı tanımlar; eksiklerse isteğin adresi ve user agent'ı kullanılır. Onaydan önce kullanıcıya gösterilir ve oturumla birlikte saklanır.

Yanıt 201 Created

json
{
	"_id": "66f1c0d2a4b5c6d7e8f90170",
	"user_code": "K7Q2XD9M",
	"device_code": "Qm9xZ1pWc2F0aE5vV2xvUjNjZ2dXbFFmZ3NtWm9Kdw",
	"status": "pending",
	"expires_in": 300,
	"interval": 5,
	"created_at": "2026-01-01T12:00:00Z",
	"expire_time": "2026-01-01T12:05:00Z",
	"client_info": { "ip_address": "203.0.113.42", "user_agent": "LivingRoomTV/2.4 (Tizen 7.0)" },
	"membership_id": "66f1c0d2a4b5c6d7e8f90123"
}
AlanKullanımı
user_codeOnay sayfanızın adresiyle birlikte ekranda gösterin. Okunabilirlik için bölebilirsiniz (K7Q2-XD9M): kullanıcı girerken büyük/küçük harf, tire ve boşluklar yok sayılır.
device_codeCihazın belleğinde tutun ve token almak için kullanın. Yalnızca bu yanıtta döner; ErtisAuth yalnızca hash'ini saklar. Asla göstermeyin ya da loglamayın.
intervalİki token isteği arasında beklenecek saniye.
expire_timeBu zamandan sonra kod kullanılamaz; yenisini isteyin.
HataNe zaman
404 TokenCodePolicyNotFoundMembership'in code_policy değeri yok ya da politika mevcut değil
503 TokenCodeCouldNotBeGeneratedKullanılmayan bir kullanıcı kodu bulunamadı; tekrar deneyin (politikanın çok az olası kodu yoksa pek olası değil)

2. Cihazı kullanıcıya gösterin#

Onay sayfanızda giriş yapmış kullanıcı kodu girer. Onaylamadan önce ona neye giriş yapmak üzere olduğunu gösterin:

http
GET /memberships/{membershipId}/codes/K7Q2XD9M
Authorization: Bearer <user_access_token>

Yanıt 200 OK: cihaz kodu olmadan kod; status (pending, approved ya da denied), created_at ve client_info ile birlikte:

203.0.113.42 adresinden, 1 dakika önce istenen LivingRoomTV/2.4 (Tizen 7.0) girişini onaylıyor musunuz?
HataNe zaman
404 TokenCodeNotFoundBilinmeyen ya da süresi dolmuş kod
400 TokenTypeNotSupportedToken bir Bearer token değil

Bu adım kullanıcıları kod oltalamasına (code phishing) karşı korur: bir saldırgan kendi cihazında bir kod üretir ve kurbanı bu kodu girmeye kandırır ("ödülünüzü almak için bu kodu girin"). Kullanıcı tanımadığı bir cihaz görürse isteği reddeder.

3. Onaylayın ya da reddedin#

http
POST /memberships/{membershipId}/codes/K7Q2XD9M/approve
Authorization: Bearer <user_access_token>
http
POST /memberships/{membershipId}/codes/K7Q2XD9M/deny
Authorization: Bearer <user_access_token>

Token bir kullanıcının Bearer token'ı olmalıdır: cihaz bu kullanıcı olarak giriş yapacaktır. Bir uygulamanın Basic token'ı 400 TokenTypeNotSupported ile reddedilir. Kullanıcının rolünde tokens.create yetkisi olmalıdır.

Yanıt 200 OK: artık approved ya da denied durumundaki kod ve user_id alanında kullanıcının id'si. Bir TokenCodeApproved ya da TokenCodeDenied olayı kaydedilir.

Bir kod yalnızca bir kez ve yalnızca beklemedeyken onaylanabilir ya da reddedilebilir: iki kişi aynı anda denerse yalnızca biri başarılı olur.

Scoped token ile onaylama. Onay bir scoped token ile yapıldığında (scope'ları tokens.create yetkisini kapsamalıdır) cihaz aynı scope'larla sınırlı bir token alır: bir cihaz, onu onaylayan oturumdan asla fazlasını alamaz. Böyle bir token membership'in scoped_token_expires_in süresi boyunca (varsayılan olarak 12 saat) geçerlidir ve yenilendiğinde scope'larını korur. Sıradan bir access token ile yapılan onay cihaza sıradan bir token verir.

HataNe zaman
400 TokenTypeNotSupportedToken bir Bearer token değil
401 TokenCodeExpiredKodun süresi dolmuş
404 TokenCodeNotFoundBilinmeyen kod
409 TokenCodeAlreadyAuthorizedKod zaten onaylanmış ya da reddedilmiş

4. Token'ı alın#

Cihaz bir token alana ya da kodun süresi dolana kadar her interval saniyede sorgulama yapar:

http
POST /memberships/{membershipId}/codes/token
Content-Type: application/json

{ "device_code": "Qm9xZ1pWc2F0aE5vV2xvUjNjZ2dXbFFmZ3NtWm9Kdw" }

Token gerekmez. Cihaz kodu, erişim log'larına düşmesin diye URL'de değil, gövdede gönderilir.

YanıtAnlamıCihazın yapacağı
Token çiftiyle 201 CreatedOnaylandıToken'ları saklar ve sorgulamayı bırakır
401 UnauthorizedTokenCodeHenüz onaylanmadıinterval saniye bekler ve yeniden sorgular
400 TokenCodeSlowDowninterval saniye geçmeden sorgulandıBir sonraki sorgudan önce daha uzun bekler
401 TokenCodeDeniedKullanıcı isteği reddettiDurur; bir mesaj gösterir, yeni bir kod önerir
401 TokenCodeExpiredKodun süresi dolduYeni bir kod ister
401 UserInactiveOnaylayan kullanıcı bu arada devre dışı bırakıldıYeni bir kod ister
401 InvalidTokenBilinmeyen ya da zaten kullanılmış cihaz koduYeni bir kod ister
  • Token çifti cihaz onu aldığında üretilir; bu yüzden geçerlilik süresi o anda başlar ve bir kez verilir: kod o anda silinir.
  • Oturum cihazın IP adresini ve user agent'ını kaydeder; böylece kullanıcının oturumları arasında kolayca tanınır.
  • Bundan sonra cihaz token'ını diğer istemciler gibi yeniler.

Örnek cihaz döngüsü#

javascript
const code = await post(`/memberships/${membershipId}/codes`); // through your backend
showOnScreen(code.user_code.replace(/(.{4})/, "$1-"), "https://example.com/tv");

let interval = code.interval;
while (Date.now() < Date.parse(code.expire_time)) {
	await sleep(interval * 1000);
	const response = await post(`/memberships/${membershipId}/codes/token`, { device_code: code.device_code });
	if (response.status === 201) return signIn(response.body);
	const { errorCode } = response.body;
	if (errorCode === "TokenCodeSlowDown") interval += 5;
	else if (errorCode !== "UnauthorizedTokenCode") break; // denied, expired, …
}
offerANewCode();

Güvenlik notları#

  • Kullanıcı kodu bir sır değildir; cihaz kodu ise sırdır. Cihaz kodunu yalnızca bellekte tutun ve HTTPS kullanın.
  • Onaydan önce her zaman cihaz bilgisini gösterin ve kullanıcıların tanımadıkları cihazları reddetmesine izin verin.
  • Cihazların kullandığı kimlik bilgilerine yalnızca tokens.create yetkisi verin.
  • POST /codes ve POST /codes/token endpoint'lerine gateway'inizde rate limiting uygulayın.

Dokümantasyonda bir hata mı buldunuz? Issue açın