Kimlik doğrulama ve oturum yönetimi için SPA en iyi uygulamaları


308

Angular, Ember, React, vb. Gibi çerçeveler kullanarak SPA tarzı uygulamalar geliştirirken, insanlar kimlik doğrulama ve oturum yönetimi için en iyi uygulamaların ne olduğuna inanıyorlar? Soruna yaklaşmayı düşünmenin birkaç yolunu düşünebilirim.

  1. API ve kullanıcı arayüzünün aynı başlangıç ​​alanına sahip olduğunu varsayarak, normal bir web uygulamasıyla kimlik doğrulamasından farklı şekilde davranmayın.

    Bu muhtemelen bir oturum çerezi, sunucu tarafı oturum depolaması ve muhtemelen kimliği doğrulanmış web kullanıcı arayüzünün kişiselleştirmeye yardımcı olmak için mevcut kullanıcı bilgilerini almak veya hatta istemci tarafında rolleri / yetenekleri belirlemek için vurabileceği bazı oturum API'si uç noktalarına sahip olmayı içerir. Sunucu elbette verilere erişimi koruyan kuralları zorunlu kılacaktı, kullanıcı arayüzü bu bilgiyi sadece deneyimi özelleştirmek için kullanacaktı.

  2. Herkese açık bir API kullanan herhangi bir üçüncü taraf istemcisi gibi davranın ve OAuth'a benzer bir tür belirteç sistemi ile kimlik doğrulaması yapın. Bu belirteç mekanizması, istemci kullanıcı arabirimi tarafından sunucu API'sine yapılan her isteğin kimliğini doğrulamak için kullanılır.

Burada gerçekten bir uzman değilim, ancak # 1 vakaların büyük çoğunluğu için tamamen yeterli görünüyor, ancak daha deneyimli bazı görüşler duymak istiyorum.


Bu şekilde perfer yapıyorum, stackoverflow.com/a/19820685/454252
allenhwkim

Yanıtlar:


477

Bu soru, biraz farklı bir biçimde, uzunluk olarak burada ele alınmıştır:

RESTful Kimlik Doğrulaması

Ancak bu sunucu tarafından ele alınır. Buna müşteri tarafından bakalım. Bunu yapmadan önce, önemli bir başlangıç ​​var:

Javascript Kripto Umutsuz

Matasano'nun bu konudaki makalesi ünlüdür, ancak içerdiği dersler oldukça önemlidir:

https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/

Özetlemek:

  • Ortadaki bir adam, kripto kodunuzu önemsiz bir şekilde değiştirebilir <script> function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
  • Ortadaki adam saldırısı, SSL olmayan bir bağlantı üzerinden herhangi bir kaynağı sunan bir sayfaya karşı önemsizdir.
  • SSL aldıktan sonra, gerçek kripto para kullanıyorsunuz.

Ve kendime ait bir sonuç eklemek için:

  • Başarılı bir XSS saldırısı, SSL kullansanız bile, saldırganın müşterinizin tarayıcısında kod yürütmesine neden olabilir. başkasının tarayıcısındaki herhangi bir javascript kodu.

Bu, bir JavaScript istemcisi kullanmak istiyorsanız birçok RESTful kimlik doğrulama düzenini imkansız veya aptal hale getirir. Haydi bakalım!

HTTP Temel Yetkilendirme

İlk ve en önemlisi, HTTP Temel Yetkilendirme. En basit şemalar: her istekte bir ad ve şifre iletmeniz yeterlidir.

Bu, elbette kesinlikle SSL gerektirir, çünkü her istekte bir Base64 (geri dönüşümlü olarak) kodlanmış ad ve şifre geçirirsiniz. Hatta dinleyen herkes önemsiz bir şekilde kullanıcı adı ve şifre alabilir. "Temel Yetkilendirme güvensizdir" argümanlarının çoğu, "HTTP Üzerinden Temel Yetkilendirme" den gelen korkunç bir fikirdir.

Tarayıcı, pişmiş HTTP Temel Kimlik Doğrulama desteği sağlar, ancak günah gibi çirkindir ve muhtemelen uygulamanız için kullanmamalısınız. Alternatif, JavaScript'te kullanıcı adı ve parolayı saklamaktır.

Bu en RESTful çözümüdür. Sunucu herhangi bir durum bilgisi gerektirmez ve kullanıcı ile her bir etkileşimin kimliğini doğrular. Bazı REST meraklıları (çoğunlukla saman adamlar), herhangi bir devleti sürdürmenin sapkın olduğunu ve başka bir kimlik doğrulama yöntemi düşünürseniz ağızda köpüreceğini ısrarla vurguluyor. Bu tür standartlara uygunluğun teorik faydaları vardır - kutunun dışında Apache tarafından desteklenir - kalbinizi isterseniz, nesnelerinizi .htaccess dosyaları tarafından korunan klasörlerde saklayabilirsiniz!

Sorun ? İstemci tarafında bir kullanıcı adı ve parola önbelleğe alıyorsunuz. Bu, evil.ru'ya daha iyi bir çatlak verir - en temel XSS güvenlik açıkları bile, istemcinin kullanıcı adını ve şifresini kötü bir sunucuya ışınlamasına neden olabilir. Parolayı karma yaparak ve tuzlandırarak bu riski hafifletmeyi deneyebilirsiniz, ancak unutmayın: JavaScript Kripto Umutsuzdur . Bu riski Tarayıcı Temel Kimlik Doğrulama desteğine bırakarak hafifletebilirsiniz, ancak daha önce de belirtildiği gibi çirkin günah.

HTTP Özet Yetkisi

JQuery ile Özet kimlik doğrulaması mümkün müdür?

Daha "güvenli" bir kimlik doğrulama, bu bir istek / yanıt karma sorusudur. JavaScript Kripto dışında Umutsuz , bu yüzden sadece SSL üzerinde çalışır ve hala istemci tarafında kullanıcı adını ve şifreyi önbelleğe almanız gerekir, bu da HTTP Temel Yetkilendirme'den daha karmaşık hale gelir, ancak daha güvenli değildir .

Ek İmza Parametreleriyle Sorgu Kimlik Doğrulaması.

Parametrelerinizi nonce ve zamanlama verileriyle şifrelediğiniz (tekrarlama ve zamanlama saldırılarına karşı korumak için) başka bir daha "güvenli" kimlik doğrulama. Bunun en iyi örneklerinden biri, bildiğim kadarıyla bir REST sunucusunda kimlik doğrulaması uygulamak için oldukça çarpıcı bir yol olan OAuth 1.0 protokolüdür.

http://tools.ietf.org/html/rfc5849

Oh, ancak JavaScript için OAuth 1.0 istemcisi yok. Neden?

JavaScript Kripto Umutsuz , unutmayın. JavaScript OAuth 1.0'a SSL olmadan katılamaz ve istemcinin kullanıcı adını ve şifresini yerel olarak depolamanız gerekir - bu da Digest Auth ile aynı kategoriye girer - HTTP Temel Kimlik Doğrulama'dan daha karmaşıktır, ancak artık güvenli değildir .

Jeton

Kullanıcı bir kullanıcı adı ve parola gönderir ve karşılığında isteklerin kimliğini doğrulamak için kullanılabilecek bir belirteç alır.

Bu, HTTP Temel Yetkilendirme'den biraz daha güvenlidir, çünkü kullanıcı adı / şifre işlemi tamamlanır tamamlanmaz hassas verileri atabilirsiniz. Jetonlar "durum" teşkil ettiği ve sunucu uygulamasını daha karmaşık hale getirdiği için de daha az RESTful'dir.

SSL Sabit

Ancak, bir jeton almak için hala ilk kullanıcı adını ve şifreyi göndermeniz gerekiyor. Hassas bilgiler hala tehlikeye atılabilir JavaScript'inize dokunuyor.

Kullanıcılarınızın kimlik bilgilerini korumak için, saldırganları JavaScript'inizden uzak tutmanız ve yine de kablo üzerinden bir kullanıcı adı ve şifre göndermeniz gerekir. SSL Gerekli.

Jetonun Sona Ermesi

"Hey, bu simge çok uzun olduğunda, atın ve kullanıcının tekrar kimlik doğrulaması yap" gibi simge politikalarını uygulamak yaygındır. veya "Bu belirteci kullanmasına izin verilen tek IP adresinin olduğundan eminim XXX.XXX.XXX.XXX". Bu politikaların çoğu oldukça iyi fikirlerdir.

Firesheeping

Bununla birlikte, SSL olmadan bir belirteç kullanmak, 'sidejacking' adlı bir saldırıya karşı hala savunmasızdır: http://codebutler.github.io/firesheep/

Saldırgan, kullanıcının kimlik bilgilerini almaz, ancak yine de sizin kullanıcı gibi davranabilir, bu da oldukça kötü olabilir.

tl; dr: Tel üzerinden şifrelenmemiş jetonlar göndermek, saldırganların bu jetonları kolayca yakalayabileceği ve kullanıcı gibi davranabileceği anlamına gelir. FireSheep bunu çok kolaylaştıran bir programdır.

Ayrı, Daha Güvenli Bir Bölge

Çalıştırdığınız uygulama ne kadar büyük olursa, hassas verileri işleme biçiminizi değiştiren bazı kodları enjekte edemeyeceklerinden kesinlikle daha zor olur. CDN'nize kesinlikle güveniyor musunuz? Reklamverenleriniz? Kendi kod tabanınız?

Kredi kartı bilgileri için ortaktır ve kullanıcı adı ve şifre için daha az yaygındır - bazı uygulayıcılar 'hassas veri girişini' uygulamalarının geri kalanından ayrı bir sayfada, olabildiğince sıkı bir şekilde kontrol edilebilecek ve kilitlenebilecek bir sayfa, tercihen bir ile kimlik avı yapmak zordur.

Çerez (sadece Jeton anlamına gelir)

Kimlik doğrulama jetonunu bir çereze koymak mümkündür (ve yaygındır). Bu, jetonla yetkinin hiçbir özelliğini değiştirmez, daha kolay bir şeydir. Önceki argümanların tümü hala geçerlidir.

Oturum (hala sadece Jeton anlamına gelir)

Oturum Kimlik Doğrulaması yalnızca Token kimlik doğrulamasıdır, ancak biraz farklı bir şey gibi görünmesini sağlayan birkaç farklılıkla:

  • Kullanıcılar, kimliği doğrulanmamış bir belirteçle başlar.
  • Arka uç, kullanıcının belirtecine bağlı bir 'durum' nesnesini korur.
  • Jeton bir çerezde sağlanır.
  • Uygulama ortamı detayları sizden uzaklaştırır.

Bununla birlikte, gerçekten, Token Auth'tan farklı değil.

Bu, RESTful uygulamasından daha da uzaklaşır - durum nesneleriyle, durum bilgisi olan bir sunucudaki düz R 'yolunda daha da ileri gidersiniz.

OAuth 2.0

OAuth 2.0 "Yazılım A, Yazılım B'nin Kullanıcı X'in oturum açma kimlik bilgilerine erişmesine gerek kalmadan Yazılım B'nin Kullanıcı X'in verilerine nasıl erişebileceğini" sorununa bakar.

Uygulama, bir kullanıcının bir jeton alması için standart bir yoldur ve daha sonra bir üçüncü taraf hizmetinin "evet, bu kullanıcı ve bu jetonla eşleşmesi" ve verilerinin bir kısmını bizden alabilirsiniz.

Temel olarak, OAuth 2.0 sadece bir token protokolüdür. Diğer belirteç protokolleriyle aynı özellikleri gösterir - bu belirteçleri korumak için yine de SSL'ye ihtiyacınız vardır - bu belirteçlerin nasıl üretildiğini değiştirir.

OAuth 2.0'ın size yardımcı olabileceği iki yol vardır:

  • Başkalarına Kimlik Doğrulama / Bilgi Sağlama
  • Kimlik Doğrulamasını / Diğerlerinden Bilgi Alma

Ama konu söz konusu olduğunda, sen sadece ... jeton kullanıyorsun.

Sorunuza geri dönün

Yani, sorduğunuz soru şudur: "Simgemi bir çerezde saklamalı mıyım ve ortamımın otomatik oturum yönetiminin ayrıntılarla ilgilenmesini sağlamalı mıyım yoksa jetonumu Javascript'te saklamalı ve bu detayları kendim ele almalı mıyım?"

Cevap: sizi mutlu eden her şeyi yapın .

Otomatik oturum yönetimi ile ilgili olan şey, sahnelerin arkasında sizin için çok fazla büyü olması. Genellikle bu ayrıntıları kendiniz kontrol etmek daha hoştur.

21 yaşındayım, bu yüzden SSL evet

Diğer cevap: Her şey için https kullanın veya brigandlar kullanıcılarınızın şifrelerini ve jetonlarını çalacaktır.


3
Mükemmel cevap. Jeton kimlik doğrulaması sistemleri ve temel çerez kimlik doğrulaması (genellikle web çerçevesine dahil edilmiştir) arasındaki denkliği takdir ediyorum. Aradığım şey bu. Değerlendirilecek pek çok potansiyel konuyu ele aldığınız için teşekkür ederiz. Şerefe!
Chris Nicola

11
Bir süre geçtiğini biliyorum ama bunun JWT'yi içerecek şekilde genişletilmesi gerekip gerekmediğini merak ediyorum. auth0.com/blog/2014/01/07/…
Chris Nicola

14
Belirteç It's also less RESTful, as tokens constitute "state and make the server implementation more complicated." (1) REST, sunucunun vatansız olmasını gerektirir . Bir belirteç depolanan istemci tarafı , sunucu için anlamlı bir şekilde durumu temsil etmez. (2) Kenarda daha karmaşık olan sunucu tarafı kodunun RESTfulness ile bir ilgisi yoktur.
çorba köpeği

10
lol_nope_send_it_to_me_insteadBu işlevin adını sevdim: D
Leo

6
Göz ardı ettiğiniz bir şey: Çerezler httpOnly olarak işaretlendiğinde XSS güvenlidir ve güvenli ve aynı siteyle daha fazla kilitlenebilir. Çerez kullanımı çok daha uzun sürdü === daha fazla savaş sertleşti. Jeton güvenliğini işlemek için JS ve yerel depolamaya güvenmek aptalca bir oyundur.
Martijn Pieters

57

JWT (JSON Web Jetonları) ve SSL / HTTPS kullanarak kimlik doğrulama işleminin güvenliğini artırabilirsiniz .

Temel Kimlik Doğrulama / Oturum Kimliği şu şekilde çalınabilir:

  • MITM saldırısı (Ortadaki Adam) - SSL / HTTPS olmadan
  • Bir davetsiz misafir kullanıcının bilgisayarına erişim sağlar
  • XSS

JWT'yi kullanarak kullanıcının kimlik doğrulama bilgilerini şifreliyor ve istemcide saklıyorsunuz ve her istekle birlikte sunucunun / API'nin jetonu doğruladığı API'ya gönderiyorsunuz. Özel anahtar (sunucunun / API'nin gizlice sakladığı) olmadan Güncelleme okunamaz / okunamaz .

Yeni (daha güvenli) akış şöyledir:

Oturum aç

  • Kullanıcı oturum açar ve oturum açma kimlik bilgilerini API'ya gönderir (SSL / HTTPS üzerinden)
  • API giriş bilgilerini alır
  • Geçerliyse:
    • Veritabanına yeni bir oturum kaydetme Güncellemeyi oku
    • Kullanıcı Kimliği, Oturum Kimliği, IP adresi, zaman damgası vb. Bir JWT'de özel bir anahtarla şifreleyin.
  • API, JWT jetonunu istemciye geri gönderir (SSL / HTTPS üzerinden)
  • Müşteri JWT jetonunu alır ve localStorage / cookie'de depolar

API'ya yapılan her istek

  • Kullanıcı , HTTP üstbilgisinde depolanan JWT jetonu ile API'ya (SSL / HTTPS üzerinden) bir HTTP isteği gönderir
  • API, HTTP üstbilgisini okur ve özel anahtarıyla JWT jetonunun şifresini çözer
  • API, JWT jetonunu doğrular, HTTP isteğindeki IP adresini JWT jetonundaki adresle eşleştirir ve oturumun süresinin dolup dolmadığını kontrol eder
  • Geçerliyse:
    • İstenen içerikle yanıt gönder
  • Geçersizse:
    • İstisna atma (403/401)
    • Sisteme izinsiz giriş bildirme
    • Kullanıcıya bir uyarı e-postası gönderin.

Güncelleme 30.07.15:

JWT yükü / talepleri özel anahtar (gizli) olmadan okunabilir ve bunu localStorage'da saklamak güvenli değildir. Bu yanlış ifadeler için özür dilerim. Ancak bir JWE standardı (JSON Web Şifrelemesi) üzerinde çalışıyor gibi görünüyorlar .

Bunu iddiaları (userID, exp) bir JWT'de saklayarak, API / arka ucunun sadece bildiği ve istemcide güvenli bir HttpOnly çerezi olarak sakladığı özel bir anahtarla (gizli) imzalayarak uyguladım. Bu şekilde XSS aracılığıyla okunamaz ve değiştirilemez, aksi takdirde JWT imza doğrulamasında başarısız olur. Ayrıca güvenli bir HttpOnly çerezi kullanarak , çerezi yalnızca HTTP istekleri (komut dosyası tarafından erişilemez) yoluyla ve yalnızca güvenli bağlantı (HTTPS) yoluyla gönderdiğinizden emin olursunuz.

Güncelleme 17.07.16:

JWT'ler doğası gereği vatansızdır. Bu, kendilerini geçersiz kılar / süreleri dolar. SessionID değerini belirttiğiniz duruma ilişkin iddialara ekleyerek, geçerliliği artık yalnızca imza doğrulama ve son kullanma tarihine bağlı olmadığından, sunucudaki oturum durumuna da bağlıdır. Ancak tersi, daha önce vatansız JWT'lerle yapamayacağınız jetonları / oturumları kolayca geçersiz kılabilirsiniz.


1
Sonunda bir JWT, güvenlik açısından hala 'sadece bir jeton'. Sunucu yine de kullanıcı kimliği, IP adresi, zaman damgası vb. Bir opak oturum belirteciyle ilişkilendirilebilir ve JWT'den daha fazla veya daha az güvenli olmaz. Bununla birlikte, JWT'nin durumsuz doğası uygulamayı kolaylaştırır.
James

1
@ James JWT, doğrulanabilir olma ve önemli ayrıntıları taşıyabilme avantajına sahiptir. Bu, alanlar arası kimlik doğrulamanın gerektiği gibi çeşitli API senaryoları için oldukça kullanışlıdır. Bir oturumun iyi olmayacağı bir şey. Aynı zamanda, uygulamalar için yararlı olan tanımlanmış (veya en azından devam eden) bir spesifikasyondur. Bu, diğer iyi token uygulamalarından daha iyi olduğu anlamına gelmez, ancak iyi tanımlanmış ve kullanışlıdır.
Chris Nicola

1
@Chris Evet Tüm noktalarınıza katılıyorum. Bununla birlikte, yukarıdaki cevapta tarif edilen akış, bir JWT'nin kullanılması nedeniyle talep edildiği gibi doğal olarak daha güvenli bir akış değildir. Ayrıca, bir tanımlayıcıyı JWT ve sunucudaki durumla ilişkilendirmediğiniz sürece JWT, yukarıda açıklanan şemada iptal edilemez. Aksi takdirde, kullanıcı adı / şifre (kötü kullanıcı deneyimi) talep ederek düzenli olarak yeni bir JWT almanız veya çok uzun bir sona erme süresi olan bir jWT vermeniz gerekir (belirteç çalınırsa kötüdür).
James

1
Cevabım% 100 doğru değil, çünkü JWT aslında özel anahtar (gizli) olmadan şifresi çözülebilir / okunabilir ve localStorage içinde saklanması güvenli değildir. Bunu bir JWT'de iddiaları (userID, exp) saklayarak, API / arka ucunun sadece bildiği ve istemcide bir HttpOnly çerezi olarak sakladığı özel bir anahtarla (gizli) imzaladım. Bu şekilde XSS tarafından okunamaz. Ancak HTTPS kullanmak zorundasınız çünkü token MITM saldırısıyla çalınabilir. Bunun üzerine düşünmek için cevabımı güncelleyeceğim.
Gaui

1
@vsenko Çerez istemciden gelen her istekle gönderilir. Çerezden JS'den erişmezsiniz, istemciden API'ya yapılan her HTTP isteğiyle bağlantılıdır.
Gaui

7

İkinci belirteç sistemini seçerdim.

Ember-auth veya ember-simple-auth hakkında bir şeyler biliyor muydunuz ? İkisi de, ember-simple-auth durumları gibi jeton tabanlı sistemi kullanır:

Ember.js uygulamalarında belirteç tabanlı kimlik doğrulaması uygulamak için hafif ve göze batmayan bir kitaplık. http://ember-simple-auth.simplabs.com

Oturum yönetimine sahiptirler ve mevcut projelere de kolayca bağlanabilirler.

Ayrıca, ember-simple-auth uygulamasının bir Ember App Kit örnek sürümü vardır: OAuth2 kimlik doğrulaması için ember-simple-auth kullanan ember-app-kit çalışma örneği.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.