Bir mobil uygulama, kullanıcının bir kimlik sağlayıcıyla oturum açmasını sağlar ve access token'ı backend'inize iletir; backend de sağlayıcının profil uç noktasını çağırır, bir e-posta adresi alır ve bir oturum oluşturur. Bütün testler geçer. Ne var ki bu kurgu, kullanıcının aynı sağlayıcıyla oturum açtığı başka herhangi bir uygulamanın da kendi access token'ıyla uygulamanıza o kullanıcı olarak giriş yapmasına izin verir; çünkü token'ın hangi uygulamaya verildiğini hiçbir şey kontrol etmez.
OpenID Connect (OIDC) bu açığı kapatır. OAuth 2.0'a bir ID token ekler: sağlayıcının, kullanıcının kim olduğunu, token'ın hangi uygulama için olduğunu ve kullanıcının ne zaman oturum açtığını beyan ettiği imzalı bir JWT.
Bu yazı, PKCE'li yetkilendirme kodu akışını (authorization code flow) bir sıralama diyagramı olarak çiziyor ve OIDC'nin neler eklediğini ele alıyor: openid scope'u, nonce, ID token doğrulama, discovery, anahtar rotasyonu, UserInfo ve oturum kapatma.
OAuth 2.0 ile OpenID Connect karşılaştırması
OAuth 2.0 erişimle ilgilidir: kullanıcı adına bir API'yi çağırmak için bir token. OpenID Connect ise kimlikle ilgilidir: kimin oturum açtığı.
| OAuth 2.0 | OpenID Connect | |
|---|---|---|
| Yanıtladığı soru | Bu uygulama bu API'yi çağırabilir mi? | Kullanıcı kim ve ne zaman oturum açtı? |
| Token | Access token | ID token |
| Token kimin için | API | Uygulamanız |
| Token biçimi | Tanımlanmamış: opak ya da JWT | İmzalı bir JWT |
| Nasıl istenir | API'nin tanımladığı scope'lar | scope içinde openid bulunur |
| Tanımladıkları | Grant türleri ve uç noktalar | Claim'ler, UserInfo, discovery, oturum kapatma |
Ağ trafiğine bakıldığında bir OIDC girişi, scope'unda openid bulunan bir OAuth yetkilendirme isteğidir ve token yanıtı, access token'ın yanında bir id_token da taşır. OAuth 2.0 akış diyagramı işin OAuth tarafını ayrıntılı olarak ele alıyor.
Adım adım akış
OpenID Connect Core 1.0 uygulamanızı relying party (RP), yetkilendirme sunucusunu ise OpenID sağlayıcısı (OpenID provider, OP) olarak adlandırır. Tarayıcıdan geçen her şey, yani ön kanal (front channel), URL'lere, tarayıcı geçmişine ve loglara sızabilir; backend'inizden sağlayıcıya yapılan çağrılar, yani arka kanal (back channel), sızamaz. Numaralar diyagramla aynıdır.
- Başlangıç (1–3). Kullanıcı “Giriş yap” düğmesine tıklar. Uygulamanız oturuma yeni bir
state,nonceve PKCEcode_verifierkaydeder ve tarayıcıyı sağlayıcıya yönlendirir. - Kimlik doğrulama isteği (4). Tarayıcı yönlendirmeyi izler:
GET /authorize?response_type=code
&client_id=orders-web
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&scope=openid%20profile%20email
&state=7fJq2LbX9aQe
&nonce=n-0S6_WzA2Mj
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256 HTTP/1.1
Host: op.example.com
- Giriş ve onay (5). Sağlayıcı kullanıcının kimliğini doğrular (parola, geçiş anahtarı, MFA ya da mevcut bir oturumla) ve onay ister. Uygulamanız kimlik bilgilerini hiçbir zaman görmez.
- Kodun dönüşü (6–7). Sağlayıcı, kısa ömürlü bir
codeve aynıstateile kayıtlıredirect_uriadresine yönlendirir; uygulamanız bu değeri oturumdakiyle karşılaştırır. - Token isteği (8–9). Backend'iniz
code,redirect_urivecode_verifierdeğerlerini istemci kimlik bilgileriyle birlikte POST eder. Sağlayıcı verifier'ı challenge ile karşılaştırır ve birid_token, biraccess_tokenve çoğu zaman birrefresh_tokendöndürür. - Doğrulama (10). Uygulamanız ID token'ı doğrular; imzalama anahtarlarını yalnızca token'ın işaret ettiği anahtar önbellekte yoksa çeker.
- UserInfo (11–12), isteğe bağlı. Yalnızca ID token'da ihtiyaç duyduğunuz claim'ler eksikse.
- Oturum (13). Uygulamanız kendi oturumunu oluşturur ve bir çerez ayarlar.
state, nonce ve PKCE neye karşı korur
| Değer | Taşındığı yer | Kontrol eden | Engellediği |
|---|---|---|---|
state |
4. adım ve geri yönlendirme | Uygulamanız | Kullanıcının hiç başlatmadığı bir giriş yanıtı (CSRF) |
nonce |
4. adım, ardından ID token'ın içi | Uygulamanız | ID token'ın tekrar oynatılması (replay) ve gizli istemcilerde yetkilendirme kodu enjeksiyonu |
code_verifier |
4. adımda SHA-256 özeti, 8. adımda kendisi | Sağlayıcı | Çalınan bir kodun kullanılması |
OAuth için güncel en iyi güvenlik uygulamalarını tanımlayan RFC 9700, bazı durumlarda birinin diğerinin yerini tutmasına izin verir; ama her biri yalnızca bir rastgele değere mal olur, bu yüzden üçünü de gönderin. Tek sayfalı uygulamalar ve mobil uygulamalar gibi açık istemciler (public client), PKCE'yi (RFC 7636) S256 ile kullanmak zorundadır.
ID token'ın içinde
Çözümlenmiş hâliyle, 9. adımda gelen ID token:
{
"iss": "https://op.example.com",
"sub": "248289761001",
"aud": "orders-web",
"nonce": "n-0S6_WzA2Mj",
"iat": 1793736400,
"exp": 1793740000,
"auth_time": 1793736390
}
| Claim | Anlamı | Uygulamanız |
|---|---|---|
iss |
Issuer (yayıncı), bir https URL'si | Discovery'den alınan issuer ile birebir aynı olmalı |
sub |
Kullanıcı kimliği; aynı issuer içinde asla başkasına atanmaz, en fazla 255 ASCII karakter | Hesap anahtarı olarak iss ile sub ikilisini kullanır |
aud |
Audience (hedef kitle), bir string ya da dizi | İçinde kendi client_id değerini bulmalı |
exp, iat |
Unix saniyesi cinsinden son geçerlilik ve düzenlenme zamanı | Süresi dolmuş ya da çok eski token'ları reddeder |
nonce |
4. adımda gönderilen değer | Oturumdakiyle eşleşmeli |
auth_time |
Kullanıcının gerçekte kimlik doğruladığı an | max_age gönderdiğinizde bunu kontrol eder |
acr, amr |
Güvence düzeyi ve yöntemler, örneğin pwd ya da mfa |
Hassas işlemlerden önce bunları kontrol eder |
Core bunu açıkça belirtir: bir kullanıcıyı yalnızca iss ile sub ikilisi tanımlar; e-posta adresleri değişir ve başkasına yeniden atanabilir.
ID token'ı doğrulamak
Core'un 3.1.3.7 numaralı bölümü kuralları sıralar:
- Algoritmayı sabitleyin (varsayılan RS256);
algbaşlığına güvenmeyin venonedeğerini asla kabul etmeyin. - İmzayı doğrulayın:
kidile belirtilen JWKS anahtarını kullanın. Token doğrudan token uç noktasından geldiği için Core, kod akışındaki bir istemcinin bunun yerine TLS'e güvenmesine izin verir; ama doğrulamanın maliyeti düşüktür. issdeğerini kontrol edin: discovery'den alınan issuer ile karakteri karakterine aynı olmalı.auddeğerini kontrol edin: içindeclient_iddeğeriniz bulunmalı; güvenmediğiniz audience'ları reddedin.expveiatdeğerlerini kontrol edin; birkaç saniyeden birkaç dakikaya kadar saat kaymasına izin verin.noncedeğerini kontrol edin: oturumdakiyle eşleşmeli; ardından onu silin.auth_timeveacrdeğerlerini kontrol edin; tabii onları istediyseniz.
Oturumu ancak bundan sonra oluşturun. Node.js'te jose kütüphanesiyle:
import { createRemoteJWKSet, jwtVerify } from 'jose'
// issuer and jwks_uri come from the discovery document.
// The key set is cached; an unknown kid triggers a refetch
// (at most once every 30 seconds by default).
const JWKS = createRemoteJWKSet(new URL(oidc.jwks_uri))
const { payload } = await jwtVerify(tokens.id_token, JWKS, {
issuer: oidc.issuer, // exact match
audience: CLIENT_ID, // must appear in aud
algorithms: ['RS256'], // never trust the header alone
clockTolerance: 60, // seconds of clock skew
maxTokenAge: 600, // rejects an old iat
})
if (payload.nonce !== session.nonce) throw new Error('nonce mismatch')
Discovery ve anahtar rotasyonu
OpenID Connect Discovery 1.0, bir sağlayıcının ayarlarını, issuer URL'sinin sonuna /.well-known/openid-configuration eklenerek ulaşılan tek bir JSON belgesinde toplar. Bu yazının yazıldığı tarihte (Kasım 2026) Google'ınki, bu akışın kullandığı alanlara indirgenmiş hâliyle şöyle:
{
"issuer": "https://accounts.google.com",
"authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
"token_endpoint": "https://oauth2.googleapis.com/token",
"userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
"jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
"id_token_signing_alg_values_supported": ["RS256"],
"code_challenge_methods_supported": ["plain", "S256"]
}
issuer, belgeyi çektiğiniz issuer URL'siyle ve her ID token'ın iss değeriyle birebir aynı olmalıdır. Beklenen issuer'ı kendiniz yapılandırın; onu asla doğrulamadığınız bir token'dan almayın.
Anahtarlar jwks_uri üzerinden döner: Sağlayıcı yeni bir anahtar ekler, onunla imzalar ve eskisini bir süre daha yayında tutar (Core, bölüm 10.1.1). Anahtar kümesini önbelleğe alın, Cache-Control başlığına uyun, tanımadığınız bir kid geldiğinde kümeyi yeniden çekin ve bu yeniden çekmelere hız sınırı koyun. JWT kimlik doğrulama akış diyagramı aynı mekanizmayı access token'lar için ele alıyor.
UserInfo
UserInfo'yu access token ile çağırdığınızda, verilen scope'lara (profile, email, address, phone) ait claim'leri döndürür. Yanıtında her zaman sub bulunur; bu değer ID token'daki sub ile birebir eşleşmelidir, aksi hâlde yanıtı atarsınız.
Oturum kapatma seçenekleri
Oturum kapatmayı, nihai (final) statüdeki üç OpenID spesifikasyonu ele alır:
| Spesifikasyon | Nasıl çalışır | Dikkat edilmesi gereken |
|---|---|---|
| RP-Initiated Logout 1.0 | Uygulamanız id_token_hint ile sağlayıcının end_session_endpoint adresine yönlendirir |
Uygulamanız kendi oturumunu da sonlandırmalıdır |
| Front-Channel Logout 1.0 | Sağlayıcı her uygulamanın logout URL'sini bir iframe içinde yükler | Üçüncü taraf çerezlerin engellenmesi bunu bozabilir |
| Back-Channel Logout 1.0 | Sağlayıcı her uygulamaya imzalı bir logout token'ı POST eder | Uygulamanız oturumu sunucu tarafında bulup sonlandırmalıdır |
Core ayrıca, ID token'daki exp değerinin oturum süresiyle ilgisi olmadığını da belirtir.
İncelemelerde karşılaşılan hatalar
- Kimlik kanıtı olarak access token. Yazının başındaki senaryo. Kullanıcıların oturumunu yalnızca backend'inizin token uç noktasından aldığı ve doğruladığı bir ID token ile açın.
audya danoncekontrolünü atlamak. Aynı sağlayıcıya kayıtlı her uygulama, aynıissdeğerine sahip ve geçerli şekilde imzalanmış ID token'lar alır; bir token'ın size verildiğini yalnızcaaudsöyler ve onu bu girişe yalnızcanoncebağlar.- Implicit akış.
response_type=id_token token, token'ları URL fragment'ına koyar; RFC 9700, istemcilerin yetkilendirme yanıtında access token döndüren yanıt türlerini kullanmaması gerektiğini söyler. Tek sayfalı uygulamalarda da PKCE ile birliktecodekullanın. - API'lere gönderilen ID token'lar. API'ler yalnızca kendileri için verilmiş access token'ları kabul etmelidir; API gateway mimari diyagramı bu kontrolün genellikle nerede yapıldığını gösteriyor.
OpenID Connect akış diyagramı
Diyagram içeriği
- User
- Browser
- Relying party (your app)
- OpenID provider
- all checks must pass
- claims missing from the ID token
- ID token: for your app (aud = client_id)
- Access token: for UserInfo and APIs
- 1. Click Sign in
- 2. GET /login
- 3. 302 to the provider's /authorize
- 4. GET /authorize: scope=openid, state, nonce, code_challenge
- 5. Log in (password, passkey, MFA) and consent
- 6. 302 to redirect_uri with code, state
- 7. GET /callback?code&state
- 8. POST /token: code, code_verifier, client auth
- 9. id_token, access_token
- 10. GET jwks_uri (when kid is not cached)
- 11. GET /userinfo, Bearer access_token
- 12. Claims; sub must match the ID token
- 13. 302 to the app, Set-Cookie: session
Nasıl okunur:
- Dört katılımcı: kullanıcı, tarayıcı, uygulamanız (relying party) ve OpenID sağlayıcısı. Zaman yukarıdan aşağıya akar.
- Renkler kanalı gösterir: mavi tarayıcı üzerinden geçenleri, camgöbeği backend'inizden sağlayıcıya gidenleri, mor da kullanıcının eylemlerini. Kesikli oklar yanıtlar ve yönlendirmelerdir.
- 3. ve 4. adımlar
scope=openid,state,nonceve PKCE challenge'ını taşır; 8. adım ise verifier'ı taşır. criticalparçası, anahtarın çekilmesini ve oturum oluşmadan önce geçilmesi gereken kontrolleri içerir.optparçası UserInfo çağrısıdır.- Sağdaki sütun discovery alanlarını adımlarla eşleştirir, PKCE parametrelerini listeler, bir ID token'ı çözümlenmiş olarak gösterir ve hangi token'ın kimin için olduğunu belirtir.
OpenID Connect diyagramlarını net çizmek
- Tarayıcıya kendi yaşam çizgisini verin. Ön kanal ile arka kanal arasındaki ayrım, bu akışın güvenlik hikâyesinin ta kendisidir.
- Kontrol edilen parametreleri okların üzerine yazın:
state,nonce,code_challenge,code_verifier. - Doğrulamayı açık açık yazın. “Token'ı doğrula” incelenemez; “imza, iss, aud, exp, iat, nonce” incelenebilir.
- Hangi token'ın nereye gittiğini belirtin, audience'ıyla birlikte. Pek çok OIDC hatası, yanlış tarafa gönderilmiş bir token'dır.
- Diyagram başına tek akış. Girişi, token yenilemeyi ve oturum kapatmayı ayrı ayrı çizin; kimlikler ve token'lar için yer tutucu değerler kullanın.
Sıralama diyagramı örneği gösterimi ele alıyor; SAML SSO akış diyagramı ise kurumsal müşterilerin hâlâ istediği XML tabanlı protokolü gösteriyor.
Archboard'da oluşturun
- Google ya da GitHub ile giriş yapın ve bir diyagram oluşturun.
- Sequence paketinden kullanıcı için bir Aktör ve eşit yükseklikte üç Yaşam çizgisi düğümü ekleyin: Browser, Relying party (your app) ve OpenID provider.
- 13 mesajı yukarıdan aşağıya düz ve numaralı kenarlar olarak çizin. Yanıtları kesikli yapın; ön kanal ile arka kanalı farklı renklere boyayın.
- Sequence paketinden, anahtar çekme adımını ve kontrolleri çevreleyen
criticaloperatörlü bir Parça ve UserInfo çağrısını çevreleyenoptoperatörlü ikinci bir Parça ekleyin. - Oturum değerleri ve kontroller için relying party'nin yanına Temel paketinden Metin ekleyin; bir de renk açıklaması ekleyin.
- Discovery, PKCE ve çözümlenmiş bir ID token için Temel paketinden bir Markdown bloğu; ID token ve access token için de Güvenlik paketinden iki Jeton düğümü ekleyin.
Örnek 9 diyagram düğümü kullanıyor ve Free planın sınırları içinde kalıyor. AI ajanınız da bunu MCP üzerinden çizebilir.
SSS
OAuth 2.0 ile OpenID Connect arasındaki fark nedir?
OAuth 2.0 bir uygulamaya, bir API'yi çağırması için access token verir. OpenID Connect bunun üzerine oturum açmayı ekler: openid scope'u, kullanıcının kim olduğunu söyleyen bir ID token ve standart discovery ile UserInfo uç noktaları.
ID token ile access token aynı şey mi? Hayır. ID token, uygulamanız için düzenlenen ve kimin oturum açtığını söyleyen imzalı bir JWT'dir. Access token ise UserInfo dahil API'ler içindir. ID token'ları asla API'lere göndermeyin, access token'ları da asla giriş kanıtı olarak kabul etmeyin.
Zaten nonce gönderiyorsam PKCE'ye ihtiyacım var mı? İkisini de kullanın. RFC 9700, açık istemciler için PKCE'yi zorunlu tutar. Gizli bir istemci ek önlemler alarak nonce'a güvenebilir; ama PKCE çalınan bir kodun kullanılmasını engellerken nonce, enjekte edilmiş bir kodu ancak token yanıtından sonra fark eder.
Bir ID token nasıl doğrulanır?
İmzayı kid değeriyle eşleşen JWKS anahtarıyla doğrulayın; ardından iss değerinin issuer'a eşit olduğunu, aud değerinin client ID'nizi içerdiğini, exp süresinin geçmediğini, iat değerinin yakın tarihli olduğunu ve nonce değerinin oturumla eşleştiğini kontrol edin.
/.well-known/openid-configuration nedir?
OpenID Connect discovery belgesidir. Bir sağlayıcının issuer'ını, uç noktalarını, algoritmalarını ve jwks_uri değerini listeler; böylece uygulamanız kendini tek bir URL'den yapılandırabilir.