Olemme kaikki olleet siellä. Työskentelet API-taustapalvelun parissa ja olet tyytyväinen sen etenemiseen. Olet äskettäin valmistunut vähiten elinkelpoisen tuotteen (MVP), testit ovat läpäisseet, ja odotat innolla uusien ominaisuuksien käyttöönottoa.
Sitten pomo lähettää sinulle sähköpostia: ”Muuten, meidän on annettava ihmisten kirjautua sisään Facebookin ja Googlen kautta; heidän ei pitäisi joutua luomaan tiliä vain pienelle sivustollemme. '
Loistava. Laajuuden viruminen iskee jälleen.
Hyvä uutinen on, että OAuth 2 on noussut sosiaalisen ja kolmannen osapuolen todennuksen teollisuusstandardiksi (jota käyttävät esimerkiksi Facebook, Google jne.), Joten voit keskittyä kyseisen standardin ymmärtämiseen ja toteuttamiseen tukemaan laajaa joukkoa sosiaalisen todennuksen tarjoajat .
Todennäköisesti et tunne OAuth 2: ta; En ollut, kun tämä tapahtui minulle.
Kuten a Python-kehittäjä , vaisto voi johtaa sinuun pip , Python Package Index (PyPA) -suosittu työkalu Python-pakettien asentamiseen. Huono uutinen on, että pip tietää noin 278 pakettia, jotka käsittelevät OAuthia - joista 53 mainitaan erikseen Django . Se on viikon arvoinen työ vain vaihtoehtojen tutkimiseen, älä koskaan aloita koodin kirjoittamista.
Tässä opetusohjelmassa opit integroimaan OAuth 2 Djangoon tai Django Rest -kehys käyttämällä Python Social Auth . Vaikka tässä artikkelissa keskitytään Django REST Frameworkiin, voit käyttää tässä annettuja tietoja sen toteuttamiseksi useissa muissa yleisissä taustakehyksissä.
OAuth 2 suunniteltiin alusta alkaen verkkotodennusprotokollaksi. Tämä ei ole aivan sama kuin jos se olisi suunniteltu verkkotodennusprotokollaksi; se olettaa, että työkalut, kuten HTML-hahmontaminen ja selaimen uudelleenohjaukset, ovat käytettävissäsi.
Tämä on tietysti jokin este JSON-pohjaiselle sovellusliittymälle, mutta voit kiertää tämän.
Käy läpi prosessin ikään kuin kirjoittaisit perinteistä palvelinpuolen verkkosivustoa.
Ensimmäinen vaihe tapahtuu kokonaan sovellusvirran ulkopuolella. Projektin omistajan on rekisteröitävä hakemuksesi jokaiselle OAuth 2 -palveluntarjoajalle, jolle tarvitset kirjautumistunnuksia.
Rekisteröinnin aikana he toimittavat OAuth 2 -palvelun tarjoajalle a takaisinsoiton URI , jossa hakemuksesi on käytettävissä vastaanottamaan pyyntöjä. Vastineeksi he saavat a asiakasavain ja asiakkaan salaisuus . Nämä tunnukset vaihdetaan todennusprosessin aikana kirjautumispyyntöjen vahvistamiseksi.
Tunnukset viittaavat palvelinkoodiin asiakkaana. Isäntä on OAuth 2 -palvelun tarjoaja. Niitä ei ole tarkoitettu sovellusliittymän asiakkaille.
Kulku alkaa, kun sovelluksesi luo sivun, joka sisältää painikkeen, kuten 'Kirjaudu sisään Facebookilla' tai 'Kirjaudu sisään Google+: lla'. Pohjimmiltaan nämä eivät ole mitään muuta kuin yksinkertaisia linkkejä, joista kukin viittaa seuraavaan URL-osoitteeseen:
https://oauth2provider.com/auth? response_type=code& client_id=CLIENT_KEY& redirect_uri=CALLBACK_URI& scope=profile& scope=email
(Huomaa: Yllä olevaan URI: hen lisätyt rivinvaihdot luettavuuden vuoksi.)
Olet antanut asiakasavaimesi ja uudelleenohjauksen URI: n, mutta ei salaisuuksia. Vastineeksi olet sanonut palvelimelle, että haluat vastaukseksi todennuskoodin ja pääsyn sekä profiili- että sähköposti-alueisiin. Nämä laajuudet määrittelevät käyttäjältä pyytämäsi käyttöoikeudet ja rajoittavat saamasi käyttöoikeustunnuksen valtuutusta.
Vastaanotettuaan käyttäjän selain ohjataan dynaamiselle sivulle, jota OAuth 2 -palvelun tarjoaja hallitsee. OAuth 2 -palveluntarjoaja tarkistaa ennen jatkamista, että soittopyyntö URI ja asiakasavain vastaavat toisiaan. Jos näin tapahtuu, kulku vaihtelee hetkellisesti käyttäjän istuntomerkkien mukaan.
Jos käyttäjää ei ole tällä hetkellä kirjautuneena kyseiseen palveluun, häntä kehotetaan tekemään se. Kun hän on kirjautunut sisään, käyttäjälle näytetään valintaikkuna, joka pyytää lupaa antaa sovelluksesi kirjautua sisään.
Olettaen, että käyttäjä hyväksyy, OAuth 2 -palvelin ohjaa heidät takaisin antamaasi takaisinsoitto-URI: hen, mukaan lukien valtuutuskoodi kyselyparametreissa: GET https://api.yourapp.com/oauth2/callback/?code=AUTH_CODE
.
Valtuutuskoodi on nopeasti vanhentuva kertakäyttöinen tunnus; heti vastaanottamisen jälkeen palvelimesi tulee kääntyä ympäri ja tehdä uusi pyyntö OAuth 2 -palvelun tarjoajalle, joka sisältää sekä valtuutuskoodin että asiakassalaisuutesi:
POST https://oauth2provider.com/token/? grant_type=authorization_code& code=AUTH_CODE& redirect_uri=CALLBACK_URI& client_id=CLIENT_KEY& client_secret=CLIENT_SECRET
Tämän valtuutuskoodin tarkoituksena on todentaa yllä oleva POST-pyyntö, mutta vuon luonteen vuoksi se on reititettävä käyttäjän järjestelmän kautta. Sellaisena se on luonnostaan epävarma.
Valtuutuskoodin rajoitukset (eli että se vanhenee nopeasti ja että sitä voidaan käyttää vain kerran) ovat olemassa, jotta voidaan vähentää todentamistietojen välittämisen riskiä epäluotettavan järjestelmän kautta.
Tämä puhelu, joka soitetaan suoraan palvelimeltasi OAuth 2 -palveluntarjoajan palvelimelle, on OAuth 2 -palvelinpuolen kirjautumisprosessin avaintekijä. Puhelun hallinta tarkoittaa, että tiedät puhelun olevan TLS-suojattu, mikä auttaa suojaamaan sitä kuunteluhyökkäyksiltä.
Valtuutuskoodin sisällyttäminen varmistaa, että käyttäjä on nimenomaisesti myöntänyt suostumuksen. Asiakassalaisuuden sisällyttäminen, jota käyttäjät eivät koskaan näe, varmistaa, että tämä pyyntö ei ole peräisin jostakin käyttäjän järjestelmän viruksesta tai haittaohjelmasta, joka sieppasi valtuutuskoodin.
Jos kaikki täsmää, palvelin palauttaa käyttöoikeustunnus , jonka avulla voit soittaa kyseiselle palveluntarjoajalle todennettuna käyttäjänä.
Kun olet saanut käyttöoikeustunnuksen palvelimelta, palvelimesi ohjaa käyttäjän selaimen vielä kerran juuri kirjautuneiden käyttäjien aloitussivulle. On yleistä, että käyttöoikeustunnus pidetään käyttäjän palvelinpuolen istunnon välimuistissa, joten että palvelin voi soittaa tietylle sosiaaliselle palveluntarjoajalle tarvittaessa.
Käyttöoikeustunnusta ei saa koskaan asettaa käyttäjän saataville!
On enemmän yksityiskohtia, joihin voimme sukeltaa.
Esimerkiksi Google sisältää a päivitä tunnus joka pidentää käyttöoikeustunnuksesi käyttöikää, kun taas Facebook tarjoaa päätepisteen, jossa voit vaihtaa lyhytaikaisia käyttöoikeustunnuksia pidempään kestäviksi. Nämä yksityiskohdat eivät kuitenkaan välitä meille, koska emme aio käyttää tätä virtausta.
Tämä kulku on hankala REST-sovellusliittymälle. Vaikka käyttöliittymän asiakas voisi luoda alkuperäisen kirjautumissivun ja antaa käyttöliittymän antaa takaisinsoitto-URL-osoitteen, kohtaat lopulta ongelman. Haluat ohjata käyttäjän käyttöliittymän aloitussivulle, kun olet saanut käyttöoikeustunnuksen. Siihen ei ole selkeää, REST-tyyppistä tapaa.
Onneksi käytettävissä on toinen OAuth 2 -virta, joka toimii tässä tapauksessa paljon paremmin.
Tässä prosessissa käyttöliittymä on vastuussa koko OAuth 2 -prosessin käsittelystä. Se muistuttaa yleensä palvelinpuolen kulkua tärkeätä poikkeusta lukuun ottamatta - käyttöliittymät elävät koneissa, joita käyttäjät hallitsevat, joten heille ei voida antaa asiakkaan salaisuutta. Ratkaisu on yksinkertaisesti eliminoida koko prosessi.
Ensimmäinen vaihe, kuten palvelinpuolen prosessissa, on sovelluksen rekisteröinti.
Tässä tapauksessa projektin omistaja rekisteröi sovelluksen edelleen, mutta web-sovelluksena. OAuth 2 -palveluntarjoaja tarjoaa edelleen a asiakasavain , mutta ei saa antaa mitään asiakkaan salaisuutta.
Käyttöliittymä tarjoaa käyttäjälle sosiaalisen kirjautumispainikkeen, joka ohjaa verkkosivulle, jota OAuth 2 -palvelun tarjoaja hallitsee, ja pyytää sovelluksellemme lupaa käyttää tiettyjä käyttäjän profiilin osia.
URL näyttää tällä kertaa hieman erilaiselta:
https://oauth2provider.com/auth? response_type=token& client_id=CLIENT_KEY& redirect_uri=CALLBACK_URI& scope=profile& scope=email
Huomaa, että response_type
parametri tällä kertaa URL-osoitteessa on token
.
Entä uudelleenohjauksen URI?
Tämä on yksinkertaisesti mikä tahansa käyttöliittymän osoite, joka on valmis käsittelemään pääsykoodin asianmukaisesti.
Käytössä olevasta OAuth 2 -kirjastosta riippuen käyttöliittymä voi tosiasiallisesti suorittaa palvelimen, joka pystyy hyväksymään HTTP-pyyntöjä käyttäjän laitteella. siinä tapauksessa uudelleenohjauksen URL-osoite on muodossa http://localhost:7862/callback/?token=TOKEN
.
Koska OAuth 2 -palvelin palauttaa HTTP-uudelleenohjauksen, kun käyttäjä on hyväksynyt, ja käyttäjän laitteessa oleva selain käsittelee tämän uudelleenohjauksen, tämä osoite tulkitaan oikein, mikä antaa käyttöliittymälle pääsyn tunnukseen.
Vaihtoehtoisesti käyttöliittymä voi suoraan toteuttaa sopivan sivun. Kummassakin tapauksessa käyttöliittymä on tässä vaiheessa vastuussa kyselyparametrien jäsentämisestä ja käyttöoikeustunnuksen käsittelystä.
Tästä eteenpäin käyttöliittymä voi soittaa suoraan OAuth 2 -palveluntarjoajan sovellusliittymään tunnuksen avulla. Mutta käyttäjät eivät todellakaan halua sitä; he haluavat todennetun käyttöoikeuden sovellusliittymään. Kaikki käyttöliittymän on tarjottava vain päätepiste, jossa käyttöliittymä voi vaihtaa sosiaalisen palvelun tarjoajan käyttöoikeustunnuksen tunnukseksi, joka myöntää pääsyn sovellusliittymään.
Miksi tämä sallitaan ollenkaan, koska käyttöoikeustunnuksen toimittaminen käyttöliittymään on luonnostaan vähemmän turvallista kuin palvelinpuolen virta?
Asiakaspuolen virtaus mahdollistaa tiukemman eron REST-käyttöliittymän ja käyttäjäkohtaisen käyttöliittymän välillä. Mikään ei tiukasti estä sinua määrittelemästä taustapalvelinta uudelleenohjauksen URI: ksi. loppuvaikutus olisi jonkinlainen hybridivirta.
Asia on, että palvelimen on sitten luotava sopiva käyttäjälle osoittava sivu ja sitten käsiohjaus jollakin tavalla takaisin käyttöliittymään.
Nykyaikaisissa projekteissa on yleistä, että huolenaiheet erotetaan tiukasti käyttöliittymän ja kaiken liiketoimintalogiikkaa käsittelevän taustan välillä. He kommunikoivat tyypillisesti hyvin määritellyn JSON-sovellusliittymän kautta. Edellä kuvattu hybridivirta heikentää huolenaiheiden erottamista, pakottaen taustapuolen palvelemaan molempia käyttäjään päin olevaa sivua ja suunnittelemaan sitten jonkin verran virtausta jotenkin käsin ohjaamaan takaisin käyttöliittymään.
Käyttöliittymän antaminen käyttöliittymälle on tarkoituksenmukainen tekniikka, joka säilyttää huolenaiheet. Se lisää jonkin verran vaarantuneen asiakkaan riskiä, mutta se toimii yleensä hyvin.
Tämä virtaus saattaa tuntua monimutkaiselta käyttöliittymälle, ja se on, jos vaadit käyttöliittymän tiimiä kehittämään kaiken itse. Kuitenkin molemmat Facebook ja Google tarjota kirjastoja, jotka mahdollistavat käyttöliittymän sisällyttämään kirjautumispainikkeita, jotka käsittelevät koko prosessia minimaalisella kokoonpanolla.
Asiakasvirran alla tausta on melko eristetty OAuth 2 -prosessista. Älä johda harhaan: Tämä ei ole yksinkertainen työ. Haluat, että se tukee ainakin seuraavia toimintoja.
User
malli heille ja täytä se asianmukaisesti.User
malli on jo olemassa, sovita heidät sähköpostiosoitteensa mukaan, jotta he pääsevät käyttämään oikeaa olemassa olevaa tiliä sen sijaan, että luovat uuden sosiaalista kirjautumista varten.Hyvä uutinen on, että kaiken tämän toiminnon toteuttaminen taustapuolella on paljon yksinkertaisempaa kuin voit odottaa.
Tässä on taika, kuinka saada tämä kaikki toimimaan taustalla vain kahdella kymmenellä koodirivillä. Tämä riippuu Python Social Auth kirjasto ('PSA' tästä lähtien), joten sinun on sisällytettävä molemmat social-auth-core
ja social-auth-app-django
omassa requirements.txt
Sinun on myös määritettävä kirjasto dokumentoituna tässä . Huomaa, että tämä sulkee pois joitain poikkeusten käsittelyä selkeyden vuoksi.
Tämän esimerkin täydellinen koodi löytyy tässä .
@api_view(http_method_names=['POST']) @permission_classes([AllowAny]) @psa() def exchange_token(request, backend): serializer = SocialSerializer(data=request.data) if serializer.is_valid(raise_exception=True): # This is the key line of code: with the @psa() decorator above, # it engages the PSA machinery to perform whatever social authentication # steps are configured in your SOCIAL_AUTH_PIPELINE. At the end, it either # hands you a populated User model of whatever type you've configured in # your project, or None. user = request.backend.do_auth(serializer.validated_data['access_token']) if user: # if using some other token back-end than DRF's built-in TokenAuthentication, # you'll need to customize this to get an appropriate token object token, _ = Token.objects.get_or_create(user=user) return Response({'token': token.key}) else: return Response( {'errors': {'token': 'Invalid token'}}, status=status.HTTP_400_BAD_REQUEST, )
Asetuksissa on vain vähän enemmän ( koko koodi ), ja sitten olet valmis:
AUTHENTICATION_BACKENDS = ( 'social_core.backends.google.GoogleOAuth2', 'social_core.backends.facebook.FacebookOAuth2', 'django.contrib.auth.backends.ModelBackend', ) for key in ['GOOGLE_OAUTH2_KEY', 'GOOGLE_OAUTH2_SECRET', 'FACEBOOK_KEY', 'FACEBOOK_SECRET']: # Use exec instead of eval here because we're not just trying to evaluate a dynamic value here; # we're setting a module attribute whose name varies. exec('SOCIAL_AUTH_{key} = os.environ.get('{key}')'.format(key=key)) SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.user.get_username', 'social_core.pipeline.social_auth.associate_by_email', 'social_core.pipeline.user.create_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', )
Lisää kartoitus tähän toimintoon urls.py
-kansiossa, ja olet valmistautunut!
Python Social Auth on erittäin hieno, erittäin monimutkainen kone. On täysin ilo käsitellä todennusta ja pääsyä mihin tahansa useita kymmeniä sosiaalisen todennuksen tarjoajia , ja se toimii suosituimmissa Python-verkkokehyksissä, mukaan lukien Django , Pullo , Pyramidi , KirsikkaPy ja WebPy .
Suurimmaksi osaksi yllä oleva koodi on hyvin tavallinen Django REST Framework (DRF) -toimintopohjainen näkymä: Se kuuntelee POST-pyyntöjä mihin polkuun kartoit sen urls.py
ja olettaen, että lähetät sille pyynnön odotetussa muodossa, se saa sitten User
esine tai None
.
Jos saat User
objekti, se on mallityyppi, jonka olet määrittänyt muualla projektissasi, jota on ehkä jo ollut tai ei. PSA on jo huolehtinut tunnuksen vahvistamisesta, tunnistamisesta, onko käyttäjän vastaavuus olemassa, luomalla käyttäjän tarvittaessa ja päivittämällä sosiaalisen palveluntarjoajan käyttäjän tiedot.
Tarkat yksityiskohdat siitä, miten käyttäjä kartoitetaan sosiaalisen palvelun tarjoajan käyttäjältä sinun ja yhdistetään nykyisiin käyttäjiin, on määritetty SOCIAL_AUTH_PIPELINE
määritelty edellä. Siitä on paljon enemmän tietoa siitä, miten tämä kaikki toimii, mutta se ei kuulu tämän viestin piiriin. Voit lukea lisää siitä tässä .
Taikuuden avain on @psa()
sisustaja näkymässä, joka lisää jäseniä request
objekti, joka siirtyy näkymään. Mielenkiintoisin niistä on request.backend
(PSA: lle backend on mikä tahansa sosiaalisen todennuksen tarjoaja).
Sopiva taustakuva valittiin meille ja liitettiin request
-sivuun backend
-pohjainen objekti argumentti näkymälle, jonka itse URL täyttää.
Kun sinulla on backend
esine kädessä, on täysin onnellista todentaa sinut palveluntarjoajaa vastaan antamalla pääsykoodisi; se on do_auth
menetelmä. Tämä puolestaan harjoittaa SOCIAL_AUTH_PIPELINE
: n kokonaisuutta asetustiedostostasi.
Putkilinja voi tehdä melko voimakkaita asioita, jos laajennat sitä, vaikka se tekee jo kaiken, mitä tarvitset, vain oletusarvoisella, sisäänrakennetulla toiminnolla.
Sen jälkeen on palattu normaaliin DRF-koodiin: jos sinulla on kelvollinen User
objekti, voit helposti palauttaa sopivan API-tunnuksen. Jos et saanut kelvollista User
esine takaisin, virheen luominen on helppoa.
Yksi tämän tekniikan haittapuolista on, että vaikka virheiden palauttaminen niiden esiintyessä on suhteellisen helppoa, on vaikea saada paljon oivalluksia siitä, mikä erityisesti meni pieleen. PSA nielaisee kaikki yksityiskohdat, jotka palvelin on saattanut palauttaa ongelmasta.
Jälleen kerran on hyvin suunniteltujen todennusjärjestelmien luonteeltaan melko läpinäkymätön virhelähteisiin. Jos sovellus kertoo käyttäjälle koskaan virheellisen salasanan sisäänkirjautumisyrityksen jälkeen, se merkitsee sanoa 'Onnittelut! Olet arvannut kelvollisen käyttäjänimen. '
Lyhyesti sanottuna: laajennettavuus. Hyvin harvat sosiaaliset OAuth 2 -palveluntarjoajat vaativat tai palauttavat täsmälleen samat tiedot API-puheluissaan samalla tavalla. On kuitenkin kaikenlaisia erikoistapauksia ja poikkeuksia.
Uuden sosiaalisen palveluntarjoajan lisääminen, kun olet jo määrittänyt PSA: n, on asetustiedostoissa muutaman rivin määritys. Sinun ei tarvitse säätää mitään koodia lainkaan. PSA tiivistää kaiken tämän, jotta voit keskittyä omaan sovellukseesi.
Hyvä kysymys! unittest.mock
ei sovellu hyvin pilkkaamaan API-kutsuja, jotka on haudattu abstraktikerroksen alle syvälle kirjastoon; pelkästään tarkan polun löytäminen pilkkaamiseen vaatii huomattavia ponnisteluja.
Sen sijaan, koska PSA on rakennettu Requests-kirjaston päälle, käytät erinomaista Vastaukset kirjasto pilkkaamaan palveluntarjoajia HTTP-tasolla.
Täydellinen keskustelu testauksesta on tämän artikkelin ulkopuolella, mutta näyte testeistämme on mukana tässä . Erityisiä toimintoja on huomioitava mocked
kontekstipäällikkö ja SocialAuthTests
luokassa.
OAuth2-prosessi on yksityiskohtainen ja monimutkainen ja monimutkainen. Onneksi on mahdollista ohittaa suuri osa tästä monimutkaisuudesta tuomalla kirjasto, joka on omistettu käsittelemään sitä mahdollisimman kivuttomalla tavalla.
Python Social Auth tekee siinä hienoa työtä. Olemme osoittaneet Django / DRF-näkymän, joka käyttää asiakaspuolen, implisiittistä, OAuth2-kulkua saumattomien käyttäjien luomiseen ja vastaavuuteen vain 25 koodirivillä. Se ei ole liian nuhjuinen.