Kimlik doğrulama mekanizması

Daha önce iki yazımda, HTTP protokolünde kimlik doğrulama işleminin nasıl yapıldığından kısaca bahsetmiştim. Ancak gelen yoğun ilgiye istinaden bunun detaylarından bahsetme gereği duydum.

  1. Tüm istekler önce "anonim" gönderilir!

    Tarayıcıdan ve karşıdaki web sunucusundan bağımsız olarak, normal koşullarda, sunucuya gönderilen ilk istek, hiçbir kimlik bilgisi içermez. Bunun da aslında çok basit ve mantıklı bir nedeni vardır: İstekte bulunduğumuz web sunucusunun, istekte bulunduğumuz kaynak için kimlik doğrulama isteyip istemeyeceğini nereden bilebiliriz? Cevap kolay, bilemeyiz. Bu nedenle tüm tarayıcılar, önce anonim olarak bir istekte bulunur. Aşağıda örnek bir isteğin başlık (header) bilgileri bulunuyor:

    GET /default.aspx HTTP/1.1
    Accept-Language: en-us
    UA-CPU: x86
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; .NET CLR 2.0.50727; .NET CLR 1.1.4322; NET CLR 3.0.04506; .NET CLR 3.5.21022;)
    Connection: Keep-Alive
    Host: www.contoso.com

    Yukarıdaki satırlardan sadece ilk ve son satırlar zorunludur. Bu nedenle şu aşamada diğer satırların ne anlama geldiği üzerinde durmayacağım. İlk satırda, hangi "verb" ile istekte bulunduğumuz (ki burada GET kullanmışız; veri gönderiyor olsaydık POST olacaktı), görüntülemek istediğimiz sayfanın adını ve son olarak da kullanmak istediğimiz HTTP versiyonunu belirtiyoruz. Son satırda da, istekte bulunduğumuz sayfanın bulunduğu web sitesinin adını veriyoruz.

    Yukarıdaki satırların hiçbiri, kimlik bilgisi içermez. Zaten başta da belirttiğim gibi, ilk istekler neredeyse hiçbir zaman kimlik bilgisi içermez.

    Eğer istediğimiz sayfaya "anonim" olarak erişilebiliyorsa, sunucu bize içeriği gönderecektir. Ancak eğer sadece belirli kişiler görüntüleyebiliyorsa o sayfayı, sunucu bize aşağıdaki gibi bir yanıt döner:

    HTTP/1.1 401 Unauthorized
    Content-Length: 1656
    Content-Type: text/html
    Server: Microsoft-IIS/6.0
    WWW-Authenticate: Negotiate
    WWW-Authenticate: NTLM

    X-Powered-By: ASP.NET
    Date: Fri, 2 Jan 2009 06:38:47 GMT

    Yukarıda görüldüğü gibi, bir "401 Unauthorized" hatası aldık. Gelen yanıtın içeriğinde bu hatanın tam olarak "HTTP Error 401.2 - Unauthorized: Access is denied due to server configuration." olduğunu görecektik. Burada önemli olan "WWW-Authenticate" başlıklarıdır. Bu başlıklarla sunucu bize hangi tür kimlik doğrulama yöntemlerini desteklediğini söyler. Burada "Negotiate" ve "NTLM" desteklediğini görüyoruz. Bunların dışında "Basic" ve "Digest" gibi türler de olabilirdi.

    Bazen, yukarıda olduğu gibi, bir web sunucusu birden fazla tür kimlik denetimi destekleyebilir. Tarayıcı, duruma göre "kullanabileceği" en "güvenli" yöntemi tercih eder. Bu, eğer mümkünse "Negotiate", yani "Kerberos" veya "NTLM"dir.

    Tarayıcımız yukarıdaki durum için "Negotiate" kullanmaya karar vermiş olsun. Şimdi bizim adımıza ikinci bir karar vermesi gerekmektedir: Bize kullanıcı adı ve şifre mi soracaktır, yoksa kendisi mi bu işi halledecektir? Buna karar verirken bakacağı yer (bu, Internet Explorer'da değiştirilebilen bir ayardır) istekte bulunulan sitenin "yerel intranet" sitesi olup olmadığıdır. Buna karar verirken de, önce o sitesnin kendisindeki "yerel intranet" siteleri listesinde olup olmadığına bakar. Burada yoksa adreste nokta (.) karakteri geçip geçmediğine bakar. Eğer geçmiyorsa yine "yerel intranet" sitesi olduğunu varsayar.

    Eğer sonuç olarak "yerel intranet" sitesi olduğuna karar verirse, bize şifre sormaz ve geri kalan adımları kendisi halleder. Aksi takdirde bize bu aşamada kullanıcı adımızı ve şifremizi sorar ve biz giriş yaptıktan sonra aşağıdaki adımlara devam eder.

  2. İkinci defa 401 hatası aldık!

    Devam etmeden önce, eğer "Basic" kullanacak olsaydık ne olurdu, bundan bahsedelim: "Basic" kimlik doğrulama metodunda, kullanıcı adı ve şifre direkt olarak sunucuya gönderilir. Tarayıcımız bunu bilemeyeceğinden bize mutlaka sorar. Sonra açık olarak (şifrelemeden) sunucuya gönderir (bu nedenle SSL'siz kullanımı önerilmez). Eğer ilgili kaynağa erişim hakkımız varsa, direkt olarak bu ikinci adımda sayfa içeriğini alırız. Yani işlem burada biter.

    "NTLM" ve "Negotiate" yöntemlerinde (yani "integrated windows authentication" seçili olan durumda) şifrenin kendisi değil, bir "jeton" (token) gönderilir. Bu da iki aşamada gerçekleşir. İlk aşamada, yani bu adımda, tarayıcı, aşağıdakine benzer bir istekte bulunur:

    GET /default.aspx HTTP/1.1
    Accept-Language: en-us
    UA-CPU: x86
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506; .NET CLR 3.5.21022;)
    Authorization: Negotiate TlRMTVNTUAABAAAAAAAA4gAAAAAAAAAAAAAAAAAAAAAGAAXEAAAADw==
    Connection: Keep-Alive
    Host: www.contoso.com

    Yukarıda da görüldüğü üzere, önceki isteğin aynısı yeniden gönderiliyor. Tek fark, daha öncekinde olmayan "Authorization" başlığının da bulunmasıdır. Burada, tarayıcımızın "Negotiate" kullanmaya karar verdiğini görüyoruz. Sonrasında gördüğümüz karakter dizisi ise bizim kullanıcı adımız, makine adımız ve bağlı olduğumuz alan adımızı içeriyor olacaktır. Buna yanıt olarak da web sunucusu aşağıdaki gibi bir tane daha 401 hatası dönecektir:

    HTTP/1.1 401 Unauthorized
    Content-Length: 1539
    Content-Type: text/html
    Server: Microsoft-IIS/6.0
    WWW-Authenticate: Negotiate TlRMTVNTUAAAAAAAAAAAAAAAAAAVgOONPEAQ+EUPD
    sYAAAAAAAAAAAIBAgFIAAAAaaaaaaaaAAAAAAAAAAAAAE4ARQBSAFMAAgAQAFAAQQBSAF
    ...
    HQAqwerewqwerewqwerewqwAGMAcgBvAHMAbwAAAAAAAAAAAAAAbQAFACwAZQB4AHQAcg
    BhAG4AZQB0ACQQQQQQQQQQQQQvAHMAbwBmAHQALgBjAG8AbQAAAAAA
    X-Powered-By: ASP.NET
    Date: Fri, 02 Jan 2009 07:48:51 GMT

    Bu seferki 401 hatasının tam açıklaması ise şöyledir: "HTTP Error 401.1 - Unauthorized: Access is denied due to invalid credentials." Aslında bu da çok mantıklı, çünkü biz henüz şifre veya jeton (token) göndermedik. Web sunucunun bize gönderdiği "WWW-Authentıcate" başlığındaki değer de duruma göre ya "ticket granting ticket"tır, ya da "challenge"dır (NTLM mi, Kerberos mu kullanıldığına göre değişir). Bunların ne olduğunun detayları HTTP protokolü açısından bakıldığında bizi ilgilendirmediğinden burada bahsetmeyeceğim. İlgilenenler yazımın sonundaki makalelerde bu detayları bulabilirler.

  3. Sonunda başardık!

    İkinci defa 401 hatası aldıktan sonra tarayıcımız bir istek daha gönderir:

    GET / HTTP/1.1
    Accept-Language: en-us
    UA-CPU: x86
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506; .NET CLR 3.5.21022;)
    Host: www.contoso.com
    Connection: Keep-Alive
    Authorization: Negotiate TlRMTVNTUAADAAAAGAAYAIIAAABmAWYBmgAAABQAFABY
    AAAACgAKAGwAAAAMABABABABABABABAAAAAAAAAAAAAAAABBBBAAAAAABBBKztSI/+IDo
    mk69k0ASQBEAEQATABFAEUAQWBYSAAEEVJHKDRSSAWEAGMARQBOAEsAMAA4ADHlK0Du5P
    ...
    ALgBjAG8AbQAWEBXasdaweGHJSSDSDFhdgjd0AC4AbQAACCCCAAGSAFMAbwBmAHQALgBj
    AG8AbQAIADAAMAAAAAAAAAAAAAAAADAAAIpoewZRe+AAAAAAAAAAAAAAAAAAAAAAAAAAA
    usZrrr1AAAAAAAAAAD7FFSas/AASDDcfasshcp

    Bu defa tarayıcımızın gonderdiği "Authorization" başlığı, Kerberos kullanılıyorsa bizim "ticket"ımız, NTLM kullanılıyorsa şifremiz ve sunucudan alınan "challenge"ın matematiksel bir karşımıdır. Sunucu bunu aldıktan sonra kontrol ettirir (kullanıcı yerel bir kullanıcı ise Windows'a değilse "Domain Controller"a sorar). Eğer kullanıcının bilgileri doğruysa, ve ilgili kaynağa erişim hakkı varsa istenilen içerik kullanıcıya gönderilir. Aksi takdirde, yine duruma göre bir tane daha 40 hatası gönderilir. Bu durumda, tarayıcımız bize yeniden kullanıcı adı ve şifre sorabilir veya 401 hatasını direkt olarak bize gösterebilir.

SONUÇ

Tüm bunları toparlayacak olursak, IIS loglarında göreceğimiz her 401 hatası, sorun olduğu anlamına gelmez. Sonraki iki isteğin yanıtını da kontrol etmemiz gerekir.

Bu arada bir dipnot: Aynı kimlik doğrulama mekanizması "proxy"ler için de geçerlidir, çünkü onlar da HTTP protoklünü kullanırlar. Yani, örneğin ISA Server loglarında göreceğimiz "407 - Proxy authentication required." hataları için de yukarıdakiler geçerlidir.

REFERANSLAR

401.1 and 401.2-Authentication Problems (IIS 6.0)
https://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/8feeaa51-c634-4de3-bfdc-e922d195a45e.mspx?mfr=true

How IIS authenticates browser clients
https://support.microsoft.com/?id=264921

Kerberos authentication and troubleshooting delegation issues
https://support.microsoft.com/?id=907272

How to troubleshoot Kerberos-related issues in IIS
https://support.microsoft.com/?id=326985

CENK ISCAN