Oturum yönetimi veya session management; tasarladığınız bir uygulamadaki kullanıcıları yetkilendirmek istediğinizde mutlaka uygulamamız gereken bir sistemdir. Oturum yönetimi için birçok farklı yöntem mevcuttur ve uygulamamız için en uygununu seçmek istiyorsak acaba hangisini seçmeliyiz?

Her bir kullanıcıya özel servis sunulabilmesi için, her kullanıcının kendisine özel bir kimliği olmalıdır. Bunu genelde kullanıcı adı/şifre, e-posta/şifre, veya üçüncü bir servis tarafından sağlanan benzersiz bir ID ile yapıyoruz. Her bir kullanıcıya özel sunulan servislere ise “oturum” veya “session” ismini veriyoruz.

Oturum yönetiminde kullanacağımız yöntem, sunduğumuz servise göre değişkenlik gösterebilir. Örnek olarak bir banka uygulamasında oturumlar olabildiğince kısa tutulmalı ve gerektiğinde oturumun iptali (revocation) sağlanabilmeliyken, müşterilerinize ücretli olarak sunduğunuz bir servisin oturum yönetimini ise JWT gibi stateless standartlar üzerinden sağlayabilirsiniz.

Şimdi olası yöntemlerden bahsedelim. Oturum yönetimini stateful ve stateless olarak iki ayrı dala ayırabiliriz. State (durum anlamında kullanılan), bilgisayar biliminde kullanıcı etkileşimlerinin veya önceki olayların hafızada (dosya sistemi, veritabanı, Redis vs.) tutulmasına verilen isimdir. Yani yapılacak işlemler sadece o anki input’a göre değil, daha önce hafızaya kaydedilen input’lara göre yapıldığında bu stateful bir işlem sayılır. Tam tersi, yalnızca o anki input’a göre işlem yaparsak bu stateless bir işlem sayılmaktadır.

Stateful yöntemler en çok kullanılan oturum yönetimi yöntemleridir. Birçok web framework ve programlama dili oturum yönetimi için stateful yöntemler kullanır. Mesela J2EE gibi web framework’ler rastgele oluşturulan opak token’ı JSESSIONID isminde bir çereze yerleştirir. Başka bir örnek ise PHP, built-in oturum yönetimine sahiptir ve opak token oluşturup bunu PHPSESSID isimli bir çereze kaydeder. Yetki kontrolü yapılmak istendiğinde, kullanıcıdan gelen bu opak token hafızada sorgulanır; önce geçerli olup olmadığı, ardından ise ilişkili kullanıcının gerekli izne sahip olup olmadığı sorgulanır. Adım adım örnek vermek gerekirse; bir kullanıcı, sunduğumuz servise geçerli bir kullanıcı adı/şifre kombinasyonunu gönderdiğinde yani her başarılı yetkilendirme isteğinde kullanıcı ile ilişkilendirilmiş bir token oluşturup (opak token), bunu da hafızaya kaydettikten sonra, kullanıcıya yetkilendirme gerekli olacak, yetkilendirme gereken tüm isteklerde kendisi ile ilişkilendirilmiş olan bu token’ı göndermesini isteriz. Gönderilen token’ı önce hafızada olup olmadığını, iptal edilmediğini ve ilişkilendirilmiş kullanıcının bu işlemi yapmaya yetkili olup olmadığının kontrolünü sağlarız.

Stateless ise hafıza işlemini tamamen kullanıcıya bıraktığımız, genellikle kriptografi ile halledilen oturum yönetimi yöntemleridir. Stateless için verebileceğimiz en doğru (en azından bir standarda sahip) örnek ise JWT’dir. JWT (JSON Web Token), HMAC algoritmasını doğrulama işlemleri yapmak, SHA256 gibi tek taraflı hash algoritmasını ise signature oluşturmak için kullanan, kriptografik tabanlı kimlik doğrulama standardıdır. Başarılı yetkilendirme isteğinde kullanıcıya bir JWT token oluştururuz fakat bunu hafızaya kaydetmeden direkt olarak kullanıcıya veririz. Çünkü JWT token tüm kullanıcı kimliğini (payload) kendi içerisinde zaten barındırıyor. JWT, üç farklı bölümden oluşur: header + payload + signature. Header’da signature’un hangi algoritma ile oluşturulduğu bilgisi yer alırken, payload içerisinde ise kullanıcıya ait bilgiler ve JWT token’ın oluşturulma/sona erme zamanı yer almaktadır. JWT’nin signature’u payload’daki veriler kullanılarak oluşturulduğu için, herhangi bir değişiklik yapıldığında ve geçersiz bir HMAC secret key kullanıldığında veya payload’daki bitiş zamanı dolduğunda bu token doğrulamayı geçemeyecektir. Doğrulamanın yapılabilmesi için signature’un oluşturulduğu HMAC secret key’in biliniyor olması gerekmektedir. Eğer payload ile oluşturulan doğrulama signature’u ile token’daki signature birbirine eşit ise veriler oynanmamış sayılır. Kullanıcı her işlemden önce kendisine verilen bu JWT token’ı gönderir, ve eğer sunucu tarafından doğrulanırsa yetkilendirme sağlanmış olur.

Stateful

Avantajlar

  • Her an iptal edilebilir / güncellenebilirler
  • Oturum başına yönetim sağlanabilir
  • Opak token’lar rastgele string ile yaratılabilir (decrypt edilemezler)

Dezavantajlar

  • Hafıza için depolama alanı gerektirir
  • Uygulama sunucuları horizontal olarak esnetilmesi durumunda bazı sorunlar çıkabilir

Stateless

Avantajlar

  • Uygulama sunucuları birbirinden bağımsız olarak çalışabilir

Dezavantajlar

  • Anında iptal edilemezler (sadece süresi dolunca iptal olabilir)
  • HMAC secret key yetkisiz kişilerin eline geçerse istenilen kimlikle oturum açılabilir
  • Kullanıcı bilgileri token’a sahip olan herkes tarafından görüntülenebilir

Stateless tek başına oturum yönetmek için kullanılmasını işte bu sebeplerden ötürü tavsiye etmiyorum. Kullanıcının sistemi istismar etmesi, bir hesabın başka birisi tarafından ele geçirilmesi veya şifre değişikliği gibi durumlarda oturumların herhangi bir zamanda iptal edilebilir olması gerekir. Fakat yalnızca geçerli bir sebebiniz varsa; örnek olarak ücretli olarak bir servis veriyorsanız ve kullanabildiği kadar kullansın tarzı bir yetkilendirme yapılacaksa JWT gibi stateless yöntemleri kullanmak mantıklı olabilir.

Stateful yöntemler ise oturumların daha kontrollü olarak yönetilmesini sağlar. Bir kullanıcıya ait tüm oturumları yönetmek mümkün hale gelebilir. Kullanıcı kendisiyle ilişkili tüm oturumları görebilir ve gerektiğinde her birinin iptalini sağlayabilir. Ancak stateful yöntemler stateless yöntemlere göre daha masraflıdır çünkü oturum sayısı arttıkça hafıza için gerekli kaynak miktarı da doğal olarak artacaktır. Ayrıca uygulama sunucuları load balancer ile scale edilmişse oturum yönetimi daha kompleks hale gelebilir. Eğer oturum yönetimi için kullandığımız token’ları ortak bir yerde tutmazsak veya “sticky session” yöntemi kullanmazsak oturumlar ansızın kapanacaktır. Yine de bu sorunların kolayca çözülebilir olduğunu düşünüyorum.

Diğer bir yöntem ise JWT ile stateful oturumu birlikte kullanmak. Yetkilendirme için kullanılacak olan opak token’ları eğer JWT gibi HMAC ile doğruluğu sağlanabilir standartlar ile imzalayıp kullanıcılara verirsek, opak token’ları değiştirip göndermelerini engelleyebiliriz; ki brute force gibi yöntemler denense bile önce secret key’in biliniyor olması gerekecektir. Böylece oturum güvenliğini ekstra olarak arttırabiliriz.