passport.js RESTful kimlik doğrulaması


155

Passport.js kullanarak kimlik doğrulaması (örneğin yerel ve Facebook), bir web arayüzü yerine RESTful API aracılığıyla nasıl işlenir?

Özel kaygılar, geri aramalardan verilerin RESTful yanıtına (JSON) aktarılmasıyla karşılaştırıldığında tipik bir res.send ({data: req.data}) kullanmak, Facebook'a yönlendiren bir başlangıç ​​/ giriş bitiş noktası oluşturmaktır (/ login yapılamaz) AJAX üzerinden erişilir, çünkü bu bir JSON yanıtı değildir - geri aramayla Facebook'a bir yönlendirmedir).

Https://github.com/halrobertson/test-restify-passport-facebook buldum , ancak anlamakta güçlük çekiyorum.

Ayrıca, passport.js kimlik doğrulama bilgilerini nasıl saklar? Sunucu (ya da hizmet mi?) MongoDB tarafından desteklenmektedir ve orada kimlik bilgileri (giriş & tuzlu pw hash) orada saklanmasını beklenir, ancak passport.js bu tür bir yeteneği olup olmadığını bilmiyorum.


Eğer Düğüm yeni olduğunuzdan, kolay başlatmak ve kontrol örneği uygulamayı için passport-facebook. Bunu çalıştırdıktan sonra, bir sonraki adım Passport'un nasıl çalıştığını ve kimlik bilgilerini nasıl sakladığını anlamaya başlamaktır. Restify'e bağlamak ( bahsettiğiniz sürümün güncellenmiş bir sürümü için buraya bakın ) son adımlardan biri olacaktır (veya Express'te REST arayüzünü uygulayabilirsiniz).
robertklep

Yanıtlar:


312

Burada sorulan birçok soru var ve sorular Node ve passport.js bağlamında sorulsa bile, gerçek sorular iş akışı ile ilgili olarak belirli bir teknoloji ile nasıl yapılacağından daha fazla.

Ek güvenlik için biraz değiştirilmiş @Keith örnek kurulumunu kullanalım:

  • Adresindeki web sunucusu https://example.comtek bir sayfa Javascript istemci uygulaması sunuyor
  • Adresindeki RESTful web hizmeti, https://example.com/apizengin istemci uygulamasına sunucu desteği sağlar
  • Sunucu Düğüm ve passport.js'de uygulandı.
  • Sunucu "kullanıcılar" tablosu ile bir veritabanı (herhangi bir tür) vardır.
  • Kullanıcı adı / şifre ve Facebook Connect kimlik doğrulama seçenekleri olarak sunulur
  • Zengin istemci, REST isteklerini https://example.com/api
  • Adresindeki web hizmetini kullanan, https://example.com/apiancak adresindeki web sunucusunu bilmeyen başka istemciler (örneğin telefon uygulamaları) olabilir https://example.com.

Güvenli HTTP kullandığımı unutmayın. Bence parolalar ve yetkilendirme simgeleri gibi hassas bilgiler istemci ve sunucu arasında geçtiği için, açık olan tüm hizmetler için bir zorunluluktur.

Kullanıcı adı / şifre doğrulaması

İlk önce eski kimlik doğrulamanın nasıl çalıştığına bakalım.

  • Kullanıcı şunlara bağlanır: https://example.com
  • Sunucu, ilk sayfayı oluşturan zengin bir Javascript uygulaması sunar. Somehwere sayfada bir giriş formu var.
  • Bu tek sayfa uygulamasının bölümlerinin çoğunda kullanıcının oturum açmaması nedeniyle veriler bulunmuyor. Tüm bu bölümlerde "oturum açma" etkinliğinde bir olay dinleyicisi var. Tüm bunlar istemci tarafı şeyler, sunucu bu olayları bilmiyor.
  • Kullanıcı oturum açma adı ve parolasını girer ve kullanıcı adı ve parolasını istemci tarafı değişkenlerine kaydetmek için bir Javascript işleyicisini tetikleyen gönder düğmesine basar. Sonra bu işleyici "giriş" olayını tetikler. Yine, bu tüm istemci tarafı eylem, kimlik bilgileri henüz sunucuya gönderilmedi .
  • "Login" etkinliğinin dinleyicileri çağrılır. Artık bunların her birinin https://example.com/api, sayfada oluşturulacak kullanıcıya özgü verileri elde etmek için RESTful API'sına bir veya daha fazla istek göndermesi gerekiyor . Web hizmetine gönderdikleri her istek, muhtemelen HTTP Temel kimlik doğrulaması biçiminde kullanıcı adını ve parolayı içerecektir , çünkü RESTful olan hizmetin bir istemden diğerine istemci durumunu korumasına izin verilmez. Web hizmeti güvenli HTTP'de olduğundan, aktarım sırasında parola güvenli bir şekilde şifrelenir.
  • Adresindeki web hizmeti https://example.com/api, her biri kimlik doğrulama bilgilerine sahip bir grup bireysel istek alır. Her istekte bulunan kullanıcı adı ve parola kullanıcı veritabanına göre kontrol edilir ve doğru bulunursa istenen işlev yürütülür ve veriler istemciye JSON biçiminde döndürülür. Kullanıcı adı ve parola eşleşmezse, istemciye 401 HTTP hata kodu biçiminde bir hata gönderilir.
  • İstemcileri her istekte kullanıcı adı ve parola göndermeye zorlamak yerine, RESTful hizmetinizde kullanıcı adını ve parolayı alan ve benzersiz ve biraz sona eren bir tür şifreleme karma olan bir jetonla yanıt veren bir "get_access_token" işlevine sahip olabilirsiniz. tarih. Bu jetonlar her kullanıcıyla birlikte veritabanında saklanır. Sonra istemci sonraki isteklerde erişim belirteci gönderir. Erişim belirteci daha sonra kullanıcı adı ve parola yerine veritabanıyla doğrulanır.
  • Telefon uygulamaları gibi tarayıcı olmayan istemci uygulamaları, yukarıdakiyle aynı şeyi yapar, kullanıcıdan web hizmetine her istekle kimlik bilgilerini girmesini (veya onlardan oluşturulan bir erişim belirtecini) göndermesini ister.

Bu örnekten önemli nokta, RESTful web hizmetlerinin her istekte kimlik doğrulaması gerektirmesidir .

Bu senaryoda ek bir güvenlik katmanı, kullanıcı kimlik doğrulamasına ek olarak istemci uygulaması yetkisi de ekler. Örneğin, web istemcisine sahipseniz, iOS ve Android uygulamalarının tümü web hizmetini kullanıyorsa, sunucunun, kimliği doğrulanmış kullanıcının kim olduğuna bakılmaksızın, belirli bir isteğin üç istemcisinden hangisinin olduğunu bilmesini isteyebilirsiniz. Bu, web hizmetinizin belirli işlevleri belirli istemcilerle kısıtlamasını sağlayabilir. Bunun için API anahtarlarını ve sırlarını kullanabilirsiniz, bu konuda bazı fikirler için bu cevaba bakın .

Facebook kimlik doğrulaması

Facebook üzerinden giriş yapmanın Facebook'un kendisi için üçüncü bir tarafı olduğu için yukarıdaki iş akışı Facebook bağlantısı için çalışmaz. Giriş prosedürü, kullanıcının kimlik bilgilerinin kontrolümüz dışında girildiği Facebook web sitesine yönlendirilmesini gerektirir.

Öyleyse işlerin nasıl değiştiğini görelim:

  • Kullanıcı şunlara bağlanır: https://example.com
  • Sunucu, ilk sayfayı oluşturan zengin bir Javascript uygulaması sunar. Sayfada "Facebook ile Giriş Yap" butonunu içeren bir giriş formu bulunmaktadır.
  • Kullanıcı yalnızca (örneğin) adresine yönlendiren bir bağlantı olan "Facebook ile Giriş Yap" düğmesini tıklar https://example.com/auth/facebook.
  • https://example.com/auth/facebookRota passport.js tarafından işlenir (bakınız belgeler )
  • Kullanıcının gördüğü tek şey sayfanın değiştiği ve şimdi web uygulamamıza giriş yapması ve yetkilendirilmesi gereken Facebook tarafından barındırılan bir sayfada olması. Bu tamamen bizim kontrolümüz dışında.
  • Facebook şimdi örneğin aşağıdaki passport.js kurulumu yapılandırılmış olduğu geri arama URL'ye geri yönlendirir böylece Facebook'a kullanıcı günlükleri ve bizim uygulamaya izin verir belgelerin olduğunuhttps://example.com/auth/facebook/callback
  • https://example.com/auth/facebook/callbackGüzergahın passport.js işleyicisi , Facebook erişim belirteci alan geri arama işlevini ve kullanıcının e-posta adresi de dahil olmak üzere Facebook'tan bazı kullanıcı bilgilerini alır.
  • E-posta ile kullanıcıyı veritabanımızda bulabilir ve Facebook erişim kodunu onunla birlikte depolayabiliriz.
  • Facebook geri çağrısında yaptığınız son şey, zengin istemci uygulamasına geri yönlendirmektir, ancak bu sefer kullanıcı adını ve erişim kodunu istemciye geçebilmemiz için istemciye iletmemiz gerekir. Bu birkaç yolla yapılabilir. Örneğin, Javascript değişkenleri sayfaya bir sunucu tarafı şablon motoru aracılığıyla eklenebilir veya bu bilgiyle bir çerez döndürülebilir. (başlangıçta önerdiğim gibi, bu verileri URL'ye geçirmeyle ilgili güvenlik sorunlarını işaret ettiği için @RyanKimber'e teşekkürler).
  • Şimdi tek sayfa uygulamasını bir kez daha başlatıyoruz, ancak istemcinin kullanıcı adı ve erişim belirteci var.
  • İstemci uygulaması hemen "login" olayını tetikleyebilir ve uygulamanın farklı bölümlerinin web servisinden ihtiyaç duydukları bilgileri talep etmesine izin verebilir.
  • Gönderilen tüm istekler https://example.com/api, kimlik doğrulama için Facebook erişim belirtecini veya uygulamanın REST API'sindeki bir "get_access_token" işlevi aracılığıyla oluşturulan Facebook erişim belirtecini içerir.
  • Tarayıcı olmayan uygulamalar burada biraz daha zor, çünkü OAuth giriş yapmak için bir web tarayıcısı gerektiriyor. Bir telefondan veya masaüstü uygulamasından giriş yapmak için Facebook'a yönlendirmeyi yapmak için bir tarayıcı başlatmanız gerekecek ve daha da kötüsü, tarayıcının Facebook erişim kodunu bazı mekanizmalarla uygulamaya geri geçirmesi için bir yol gerekir.

Umarım bu soruların çoğuna cevap verir. Elbette Facebook'u Twitter, Google veya başka bir OAuth tabanlı kimlik doğrulama hizmetiyle değiştirebilirsiniz.

Birisinin bununla başa çıkmanın daha basit bir yolu olup olmadığını bilmek isterim.


5
Ayrıntılı yanıtınız için teşekkür ederiz. Sadece bir soru: bunu söyledin Every single request they send to the web service will include the username and passwordve yine de söyledin you can have a "get_access_token" function in your RESTful service. REST'in durumsuz olması gerektiğini söylemek çelişkili görünmektedir, ancak erişim belirteçleri sunucu tarafının saklanması tamamdır, çünkü erişim belirteçlerini saklama eylemi, sunucunun artık durumlu olduğu anlamına gelir. Bununla ilgili herhangi bir açıklama veya gerekçeyi takdir ediyorum. Teşekkürler! :)
ryanrhee

6
Vatansız gereksinimi düşündüğümde, bir müşteriyle belirli bir oturumun durumunu düşünürüm. Bir kullanıcıyla ilişkili verileri parola veya erişim belirteci gibi bir veritabanında depolamanın en azından "oturum durumu" değil, "durum" olarak görmüyorum. Sunucunuzun, kullanıcıların kim olduğunu ve şifrelerini bilmesi gerektiği açıktır, ancak bu, bir oturumla ilişkili olmayan uygulama verileridir. Bununla birlikte, birçok insan sözde RESTful hizmetlerinde çerezleri kullanır, bu nedenle REST spesifikasyonuna uymak ne kadar katı olunur gerçekten her uygulayıcıya bağlıdır.
Miguel

1
@Dexter: Geleneksel giriş durumunda, kullanıcı bir forma kullanıcı adı ve parola girer ve Gönder düğmesine bastığında bu bilgiler bir web sunucusuna gönderilir. Bu durumda bu gerçekleşmez, kullanıcı formu doldurur ve vurduğunda bir Javascript işleyicisi gönder (Gönder düğmesindeki bir onClick olayı) verileri yakalar ve istemci bağlamında tutar. Göstermeye hazır bir örneğim
Miguel

2
Bu çok iyi düşünülmüş bir yazmadır, ancak önemli bir gözetim veya hata içerir. Facebook girişini (veya Github, twitter, vb.) Kullanırken, bir çerezde jetonu istemciye geri göndermek ve daha sonra keşfedildikten sonra istemci tarafındaki çerezi silmek çok tercih edilir. Simgeyi URL dizesinin bir parçası olarak geçirmek, bu URL'yi tarayıcı geçmişine ekler ve (işler yanlış işlenirse) bu URL'nin tarayıcı tarafından istenmesine neden olabilir. Ya simgeyi görünür yapar. Daha sonra URL'yi kopyalayan herkes bu kullanıcıyı başvurunuzda taklit edebilir.
Ryan Kimber

1
@Nathan: https üzerinden temel yetkilendirme güvenli, bu yüzden evet, bu kabul edilebilir bir mekanizma.
Miguel

11

@ Miguel'in her durumda tam akışla ilgili açıklamasını çok takdir ediyorum, ancak Facebook Kimlik Doğrulama bölümüne biraz eklemek istiyorum.

Facebook, doğrudan istemci ucunda erişim belirtecini almak için kullanabileceğiniz, daha sonra sunucuya iletilen ve tüm kullanıcı bilgilerini Facebook'tan daha fazla çekmek için kullanılan bir Javascript SDK sağlar . Yani temel olarak herhangi bir yeniden yönlendirmeye ihtiyacınız yok.

Ayrıca, aynı API uç noktasını mobil uygulamalar için de kullanabilirsiniz. Facebook için Android / iOS SDK'sını kullanmanız, istemci tarafında Facebook erişim_onunu almanız ve sunucuya aktarmanız yeterlidir.

İlgili durum bilgisi doğa açıklandığı gibi get_access_token bir belirteç ve müşteri geçirilen üretmek için kullanıldığı zaman, bu belirteç sunucuda depolanır. Yani bir oturum jetonu kadar iyi ve bu durumun durum bilgisi olmasını sağlıyor mu?

Sadece 2 sentim ..


1
Bu çok önemlidir, çünkü bu şekilde facebook kullanarak tek sayfalık sadece ajax yetkilendirmesi yapabilirsiniz. Belirteç, oturum kimlik doğrulaması olarak EQUALLY güvenlidir, tek fark, bir belirtecin başka bir etki alanına geçirilebilmesi ve oturumun yalnızca belirli bir etki alanında kullanılabilmesidir. Expressjs ve pasaport kullanırken, devleti kurtaran bir api yapabilir ve oturum kimlik doğrulamasını kullanabilirsiniz.
jperelli

Javascript api, Facebook'a karşı eylemler gerçekleştirmek için kullanıcının kimliğini doğrulamak istiyorsanız harika, ancak anlayabildiğim kadarıyla kullanıcıyı sunucunuza / veritabanınıza doğrulamak istiyorsanız kendi başına işe yaramaz.
James Westgate

4
Yukarıda Miguel tarafından açıklanan yöntemi de kullanabilirsiniz, ancak istemciyi yetkilendirme geri çağrısında yeniden yönlendirirken kendi JWT simgenizi bir çerez olarak yayınlayabilirsiniz. Bu, her iki dünyanın en iyisini mümkün kılar - tek sayfalık uygulamanız yalnızca bir tür kimlik doğrulaması (JWT) hakkında endişelenirken, aynı düzeyde güvenlik sağlar ve herhangi bir sosyal oturum açmayı kullanmak zorunda kalmadan destekleme esnekliği sağlar her sosyal ağ için belirli JavaScript API'ları (Facebook, Twitter, LinkedIn, Google vb.). Ayrıca kullanıcı adı / şifre ve REST erişimi için AJAX tarzı desteği korumanıza izin verir.
Ryan Kimber

Facebook Javascript SDK şu anda Chrome iOS ile çalışmıyor. Belki bazıları için bir sorun.
demisx

@RyanKimber bunun tamamen örnek olarak yapıldığını gösteren küçük bir git repo ya da benzeri bir şey yazabilir
miyim

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.