Beruflich Dokumente
Kultur Dokumente
Documentation
SearchforStrategies
G ENERAL
PRO VIDERS
APIS
O PERAT IO NS
Overview
PassportisauthenticationmiddlewareforNode.Itisdesignedtoserveasingularpurpose:authenticate
requests.Whenwritingmodules,encapsulationisavirtue,soPassportdelegatesallotherfunctionalitytothe
application.Thisseparationofconcernskeepscodecleanandmaintainable,andmakesPassportextremely
easytointegrateintoanapplication.
Inmodernwebapplications,authenticationcantakeavarietyofforms.Traditionally,usersloginbyprovidinga
usernameandpassword.Withtheriseofsocialnetworking,singlesignonusinganOAuthprovidersuchas
FacebookorTwitterhasbecomeapopularauthenticationmethod.ServicesthatexposeanAPIoftenrequire
tokenbasedcredentialstoprotectaccess.
Passportrecognizesthateachapplicationhasuniqueauthenticationrequirements.Authenticationmechanisms,
knownasstrategies,arepackagedasindividualmodules.Applicationscanchoosewhichstrategiestoemploy,
withoutcreatingunnecessarydependencies.
Despitethecomplexitiesinvolvedinauthentication,codedoesnothavetobecomplicated.
http://passportjs.org/docs
1/40
3/14/2016
Documentation
app.post('/login',passport.authenticate('local',{successRedirect:'/',
failureRedirect:'/login'}))
Install
$npminstallpassport
Authenticate
Authenticatingrequestsisassimpleascalling passport.authenticate() andspecifyingwhichstrategytoemploy.
authenticate()
'sfunctionsignatureisstandardConnectmiddleware,whichmakesitconvenienttouseasroute
middlewareinExpressapplications.
app.post('/login',
passport.authenticate('local'),
function(req,res){
//Ifthisfunctiongetscalled,authenticationwassuccessful.
//`req.user`containstheauthenticateduser.
res.redirect('/users/'+req.user.username)
})
Note:Strategiesmustbeconfiguredpriortousingtheminaroute.Continuereadingthechapteronconfiguration
fordetails.
http://passportjs.org/docs
2/40
3/14/2016
Documentation
Redirects
Aredirectiscommonlyissuedafterauthenticatingarequest.
app.post('/login',
passport.authenticate('local',{successRedirect:'/',
failureRedirect:'/login'}))
Inthiscase,theredirectoptionsoverridethedefaultbehavior.Uponsuccessfulauthentication,theuserwillbe
redirectedtothehomepage.Ifauthenticationfails,theuserwillberedirectedbacktotheloginpageforanother
attempt.
FlashMessages
Redirectsareoftencombinedwithflashmessagesinordertodisplaystatusinformationtotheuser.
app.post('/login',
passport.authenticate('local',{successRedirect:'/',
failureRedirect:'/login',
failureFlash:true})
)
Alternatively,theflashmessagecanbesetspecifically.
passport.authenticate('local',{failureFlash:'Invalidusernameorpassword.'})
http://passportjs.org/docs
3/40
3/14/2016
Documentation
passport.authenticate('local',{successFlash:'Welcome!'})
DisableSessions
Aftersuccessfulauthentication,Passportwillestablishapersistentloginsession.Thisisusefulforthecommon
scenarioofusersaccessingawebapplicationviaabrowser.However,insomecases,sessionsupportisnot
necessary.Forexample,APIserverstypicallyrequirecredentialstobesuppliedwitheachrequest.Whenthisis
thecase,sessionsupportcanbesafelydisabledbysettingthe session optionto false .
app.get('/api/users/me',
passport.authenticate('basic',{session:false}),
function(req,res){
res.json({id:req.user.id,username:req.user.username})
})
CustomCallback
Ifthebuiltinoptionsarenotsufficientforhandlinganauthenticationrequest,acustomcallbackcanbeprovided
toallowtheapplicationtohandlesuccessorfailure.
app.get('/login',function(req,res,next){
passport.authenticate('local',function(err,user,info){
if(err){returnnext(err)}
if(!user){returnres.redirect('/login')}
http://passportjs.org/docs
4/40
3/14/2016
Documentation
req.logIn(user,function(err){
if(err){returnnext(err)}
returnres.redirect('/users/'+user.username)
})
})(req,res,next)
})
Thecallbackcanusetheargumentssuppliedtohandletheauthenticationresultasdesired.Notethatwhen
usingacustomcallback,itbecomestheapplication'sresponsibilitytoestablishasession(bycalling req.login() )
andsendaresponse.
Configure
ThreepiecesneedtobeconfiguredtousePassportforauthentication:
1.Authenticationstrategies
2.Applicationmiddleware
3.Sessions(optional)
Strategies
Passportuseswhataretermedstrategiestoauthenticaterequests.Strategiesrangefromverifyingausername
andpassword,delegatedauthenticationusingOAuthorfederatedauthenticationusingOpenID.
BeforeaskingPassporttoauthenticatearequest,thestrategy(orstrategies)usedbyanapplicationmustbe
configured.
http://passportjs.org/docs
5/40
3/14/2016
Documentation
forusername/passwordauthentication.
varpassport=require('passport')
,LocalStrategy=require('passportlocal').Strategy
passport.use(newLocalStrategy(
function(username,password,done){
User.findOne({username:username},function(err,user){
if(err){returndone(err)}
if(!user){
returndone(null,false,{message:'Incorrectusername.'})
}
if(!user.validPassword(password)){
returndone(null,false,{message:'Incorrectpassword.'})
}
returndone(null,user)
})
}
))
VerifyCallback
Thisexampleintroducesanimportantconcept.Strategiesrequirewhatisknownasaverifycallback.The
purposeofaverifycallbackistofindtheuserthatpossessesasetofcredentials.
WhenPassportauthenticatesarequest,itparsesthecredentialscontainedintherequest.Ittheninvokesthe
verifycallbackwiththosecredentialsasarguments,inthiscase username and password .Ifthecredentialsarevalid,
theverifycallbackinvokes done tosupplyPassportwiththeuserthatauthenticated.
returndone(null,user)
http://passportjs.org/docs
6/40
3/14/2016
Documentation
returndone(null,false)
Anadditionalinfomessagecanbesuppliedtoindicatethereasonforthefailure.Thisisusefulfordisplayinga
flashmessagepromptingtheusertotryagain.
returndone(null,false,{message:'Incorrectpassword.'})
Finally,ifanexceptionoccurredwhileverifyingthecredentials(forexample,ifthedatabaseisnotavailable),
done
shouldbeinvokedwithanerror,inconventionalNodestyle.
returndone(err)
Notethatitisimportanttodistinguishthetwofailurecasesthatcanoccur.Thelatterisaserverexception,in
which err issettoanon null value.Authenticationfailuresarenaturalconditions,inwhichtheserverisoperating
normally.Ensurethat err remains null ,andusethefinalargumenttopassadditionaldetails.
Bydelegatinginthismanner,theverifycallbackkeepsPassportdatabaseagnostic.Applicationsarefreeto
choosehowuserinformationisstored,withoutanyassumptionsimposedbytheauthenticationlayer.
Middleware
InaConnectorExpressbasedapplication, passport.initialize() middlewareisrequiredtoinitializePassport.Ifyour
applicationusespersistentloginsessions, passport.session() middlewaremustalsobeused.
app.configure(function(){
http://passportjs.org/docs
7/40
3/14/2016
Documentation
app.use(express.static('public'))
app.use(express.cookieParser())
app.use(express.bodyParser())
app.use(express.session({secret:'keyboardcat'}))
app.use(passport.initialize())
app.use(passport.session())
app.use(app.router)
})
Notethatenablingsessionsupportisentirelyoptional,thoughitisrecommendedformostapplications.If
enabled,besuretouse express.session() before passport.session() toensurethattheloginsessionisrestoredinthe
correctorder.
Sessions
Inatypicalwebapplication,thecredentialsusedtoauthenticateauserwillonlybetransmittedduringthelogin
request.Ifauthenticationsucceeds,asessionwillbeestablishedandmaintainedviaacookiesetintheuser's
browser.
Eachsubsequentrequestwillnotcontaincredentials,butrathertheuniquecookiethatidentifiesthesession.In
ordertosupportloginsessions,Passportwillserializeanddeserialize user instancestoandfromthesession.
passport.serializeUser(function(user,done){
done(null,user.id)
})
passport.deserializeUser(function(id,done){
User.findById(id,function(err,user){
done(err,user)
})
})
http://passportjs.org/docs
8/40
3/14/2016
Documentation
Inthisexample,onlytheuserIDisserializedtothesession,keepingtheamountofdatastoredwithinthe
sessionsmall.Whensubsequentrequestsarereceived,thisIDisusedtofindtheuser,whichwillberestoredto
req.user
Theserializationanddeserializationlogicissuppliedbytheapplication,allowingtheapplicationtochoosean
appropriatedatabaseand/orobjectmapper,withoutimpositionbytheauthenticationlayer.
Username&Password
Themostwidelyusedwayforwebsitestoauthenticateusersisviaausernameandpassword.Supportforthis
mechanismisprovidedbythepassportlocalmodule.
Install
$npminstallpassportlocal
Configuration
varpassport=require('passport')
,LocalStrategy=require('passportlocal').Strategy
passport.use(newLocalStrategy(
function(username,password,done){
User.findOne({username:username},function(err,user){
if(err){returndone(err)}
if(!user){
returndone(null,false,{message:'Incorrectusername.'})
}
if(!user.validPassword(password)){
returndone(null,false,{message:'Incorrectpassword.'})
http://passportjs.org/docs
9/40
3/14/2016
Documentation
}
returndone(null,user)
})
}
))
Form
Aformisplacedonawebpage,allowingtheusertoentertheircredentialsandlogin.
<formaction="/login"method="post">
<div>
<label>Username:</label>
<inputtype="text"name="username"/>
</div>
<div>
<label>Password:</label>
<inputtype="password"name="password"/>
</div>
<div>
<inputtype="submit"value="LogIn"/>
</div>
</form>
Route
Theloginformissubmittedtotheserverviathe POST method.Using authenticate() withthe local strategywillhandle
theloginrequest.
http://passportjs.org/docs
10/40
3/14/2016
Documentation
app.post('/login',
passport.authenticate('local',{successRedirect:'/',
failureRedirect:'/login',
failureFlash:true})
)
Parameters
Bydefault, LocalStrategy expectstofindcredentialsinparametersnamed username and password .Ifyoursiteprefersto
namethesefieldsdifferently,optionsareavailabletochangethedefaults.
passport.use(newLocalStrategy({
usernameField:'email',
passwordField:'passwd'
},
function(username,password,done){
//...
}
))
OpenID
OpenIDisanopenstandardforfederatedauthentication.Whenvisitingawebsite,userspresenttheirOpenIDto
signin.TheuserthenauthenticateswiththeirchosenOpenIDprovider,whichissuesanassertiontoconfirmthe
user'sidentity.Thewebsiteverifiesthisassertioninordertosigntheuserin.
http://passportjs.org/docs
11/40
3/14/2016
Documentation
SupportforOpenIDisprovidedbythepassportopenidmodule.
Install
$npminstallpassportopenid
Configuration
WhenusingOpenID,areturnURLandrealmmustbespecified.The returnURL istheURLtowhichtheuserwill
beredirectedafterauthenticatingwiththeirOpenIDprovider. realm indicatesthepartofURLspaceforwhich
authenticationisvalid.TypicallythiswillbetherootURLofthewebsite.
varpassport=require('passport')
,OpenIDStrategy=require('passportopenid').Strategy
passport.use(newOpenIDStrategy({
returnURL:'http://www.example.com/auth/openid/return',
realm:'http://www.example.com/'
},
function(identifier,done){
User.findOrCreate({openId:identifier},function(err,user){
done(err,user)
})
}
))
Form
http://passportjs.org/docs
12/40
3/14/2016
Documentation
Aformisplacedonawebpage,allowingtheusertoentertheirOpenIDandsignin.
<formaction="/auth/openid"method="post">
<div>
<label>OpenID:</label>
<inputtype="text"name="openid_identifier"/><br/>
</div>
<div>
<inputtype="submit"value="SignIn"/>
</div>
</form>
Routes
TworoutesarerequiredforOpenIDauthentication.Thefirstrouteacceptstheformsubmissioncontainingan
OpenIDidentifier.Duringauthentication,theuserwillberedirectedtotheirOpenIDprovider.Thesecondrouteis
theURLtowhichtheuserwillbereturnedafterauthenticatingwiththeirOpenIDprovider.
//AccepttheOpenIDidentifierandredirecttheusertotheirOpenID
//providerforauthentication.Whencomplete,theproviderwillredirect
//theuserbacktotheapplicationat:
///auth/openid/return
app.post('/auth/openid',passport.authenticate('openid'))
//TheOpenIDproviderhasredirectedtheuserbacktotheapplication.
//Finishtheauthenticationprocessbyverifyingtheassertion.Ifvalid,
//theuserwillbeloggedin.Otherwise,authenticationhasfailed.
app.get('/auth/openid/return',
passport.authenticate('openid',{successRedirect:'/',
failureRedirect:'/login'}))
http://passportjs.org/docs
13/40
3/14/2016
Documentation
ProfileExchange
OpenIDcanoptionallybeconfiguredtoretrieveprofileinformationabouttheuserbeingauthenticated.Profile
exchangeisenabledbysettingthe profile optionto true .
passport.use(newOpenIDStrategy({
returnURL:'http://www.example.com/auth/openid/return',
realm:'http://www.example.com/',
profile:true
},
function(identifier,profile,done){
//...
}
))
Whenprofileexchangeisenabled,thefunctionsignatureoftheverifycallbackacceptsanadditional profile
argumentcontaininguserprofileinformationprovidedbytheOpenIDproviderrefertoUserProfileforfurther
information.
OAuth
OAuthisastandardprotocolthatallowsuserstoauthorizeAPIaccesstowebanddesktopormobile
applications.Onceaccesshasbeengranted,theauthorizedapplicationcanutilizetheAPIonbehalfoftheuser.
OAuthhasalsoemergedasapopularmechanismfordelegatedauthentication.
OAuthcomesintwoprimaryflavors,bothofwhicharewidelydeployed.
TheinitialversionofOAuthwasdevelopedasanopenstandardbyalooselyorganizedcollectiveofweb
developers.TheirworkresultedinOAuth1.0,whichwassupersededbyOAuth1.0a.Thisworkhasnowbeen
standardizedbytheIETFasRFC5849.
http://passportjs.org/docs
14/40
3/14/2016
Documentation
RecenteffortsundertakenbytheWebAuthorizationProtocolWorkingGrouphavefocusedondefiningOAuth
2.0.Duetothelengthystandardizationeffort,providershaveproceededtodeployimplementationsconforming
tovariousdrafts,eachwithslightlydifferentsemantics.
Thankfully,PassportshieldsanapplicationfromthecomplexitiesofdealingwithOAuthvariants.Inmanycases,
aproviderspecificstrategycanbeusedinsteadofthegenericOAuthstrategiesdescribedbelow.Thiscutsdown
onthenecessaryconfiguration,andaccommodatesanyproviderspecificquirks.SeeFacebook,Twitterorthe
listofprovidersforpreferredusage.
SupportforOAuthisprovidedbythepassportoauthmodule.
Install
$npminstallpassportoauth
OAuth1.0
OAuth1.0isadelegatedauthenticationstrategythatinvolvesmultiplesteps.First,arequesttokenmustbe
obtained.Next,theuserisredirectedtotheserviceprovidertoauthorizeaccess.Finally,afterauthorizationhas
beengranted,theuserisredirectedbacktotheapplicationandtherequesttokencanbeexchangedforan
accesstoken.Theapplicationrequestingaccess,knownasaconsumer,isidentifiedbyaconsumerkeyand
consumersecret.
Configuration
WhenusingthegenericOAuthstrategy,thekey,secret,andendpointsarespecifiedasoptions.
varpassport=require('passport')
,OAuthStrategy=require('passportoauth').OAuthStrategy
passport.use('provider',newOAuthStrategy({
requestTokenURL:'https://www.provider.com/oauth/request_token',
http://passportjs.org/docs
15/40
3/14/2016
Documentation
accessTokenURL:'https://www.provider.com/oauth/access_token',
userAuthorizationURL:'https://www.provider.com/oauth/authorize',
consumerKey:'123456789',
consumerSecret:'shhhitsasecret'
callbackURL:'https://www.example.com/auth/provider/callback'
},
function(token,tokenSecret,profile,done){
User.findOrCreate(...,function(err,user){
done(err,user)
})
}
))
Routes
TworoutesarerequiredforOAuthauthentication.ThefirstrouteinitiatesanOAuthtransactionandredirectsthe
usertotheserviceprovider.ThesecondrouteistheURLtowhichtheuserwillberedirectedafterauthenticating
withtheprovider.
//RedirecttheusertotheOAuthproviderforauthentication.When
//complete,theproviderwillredirecttheuserbacktotheapplicationat
///auth/provider/callback
app.get('/auth/provider',passport.authenticate('provider'))
//TheOAuthproviderhasredirectedtheuserbacktotheapplication.
//Finishtheauthenticationprocessbyattemptingtoobtainanaccess
//token.Ifauthorizationwasgranted,theuserwillbeloggedin.
//Otherwise,authenticationhasfailed.
http://passportjs.org/docs
16/40
3/14/2016
Documentation
app.get('/auth/provider/callback',
passport.authenticate('provider',{successRedirect:'/',
failureRedirect:'/login'}))
Link
Alinkorbuttoncanbeplacedonawebpage,whichwillstarttheauthenticationprocesswhenclicked.
<ahref="/auth/provider">LogInwithOAuthProvider</a>
OAuth2.0
OAuth2.0isthesuccessortoOAuth1.0,andisdesignedtoovercomeperceivedshortcomingsintheearlier
version.Theauthenticationflowisessentiallythesame.Theuserisfirstredirectedtotheserviceproviderto
authorizeaccess.Afterauthorizationhasbeengranted,theuserisredirectedbacktotheapplicationwithacode
thatcanbeexchangedforanaccesstoken.Theapplicationrequestingaccess,knownasaclient,isidentifiedby
anIDandsecret.
Configuration
WhenusingthegenericOAuth2.0strategy,theclientID,clientsecret,andendpointsarespecifiedasoptions.
varpassport=require('passport')
,OAuth2Strategy=require('passportoauth').OAuth2Strategy
passport.use('provider',newOAuth2Strategy({
authorizationURL:'https://www.provider.com/oauth2/authorize',
tokenURL:'https://www.provider.com/oauth2/token',
clientID:'123456789',
clientSecret:'shhhitsasecret'
callbackURL:'https://www.example.com/auth/provider/callback'
http://passportjs.org/docs
17/40
3/14/2016
Documentation
},
function(accessToken,refreshToken,profile,done){
User.findOrCreate(...,function(err,user){
done(err,user)
})
}
))
Routes
TworoutesarerequiredforOAuth2.0authentication.Thefirstrouteredirectstheusertotheserviceprovider.
ThesecondrouteistheURLtowhichtheuserwillberedirectedafterauthenticatingwiththeprovider.
//RedirecttheusertotheOAuth2.0providerforauthentication.When
//complete,theproviderwillredirecttheuserbacktotheapplicationat
///auth/provider/callback
app.get('/auth/provider',passport.authenticate('provider'))
//TheOAuth2.0providerhasredirectedtheuserbacktotheapplication.
//Finishtheauthenticationprocessbyattemptingtoobtainanaccess
//token.Ifauthorizationwasgranted,theuserwillbeloggedin.
//Otherwise,authenticationhasfailed.
app.get('/auth/provider/callback',
passport.authenticate('provider',{successRedirect:'/',
failureRedirect:'/login'}))
Scope
http://passportjs.org/docs
18/40
3/14/2016
Documentation
WhenrequestingaccessusingOAuth2.0,thescopeofaccessiscontrolledbythescopeoption.
app.get('/auth/provider',
passport.authenticate('provider',{scope:'email'})
)
Multiplescopescanbespecifiedasanarray.
app.get('/auth/provider',
passport.authenticate('provider',{scope:['email','sms']})
)
Link
Alinkorbuttoncanbeplacedonawebpage,whichwillstarttheauthenticationprocesswhenclicked.
<ahref="/auth/provider">LogInwithOAuth2.0Provider</a>
UserProfile
WhenauthenticatingusingathirdpartyservicesuchasFacebookorTwitter,userprofileinformationwilloftenbe
available.Eachservicetendstohaveadifferentwayofencodingthisinformation.Tomakeintegrationeasier,
Passportnormalizesprofileinformationtotheextentpossible.
NormalizedprofileinformationconformstothecontactschemaestablishedbyPortableContacts.Thecommon
http://passportjs.org/docs
19/40
3/14/2016
Documentation
fieldsavailableareoutlinedinthefollowingtable.
provider
{String}
{String}
Auniqueidentifierfortheuser,asgeneratedbytheserviceprovider.
displayName
{String}
Thenameofthisuser,suitablefordisplay.
name
{Object}
familyName
{String}
Thefamilynameofthisuser,or"lastname"inmostWesternlanguages.
givenName
{String}
Thegivennameofthisuser,or"firstname"inmostWesternlanguages.
middleName
{String}
Themiddlenameofthisuser.
emails
value
{Array}[n]
{String}
Theactualemailaddress.
type
{String}
Thetypeofemailaddress(home,work,etc.).
photos
value
{Array}[n]
{String}
TheURLoftheimage.
Notethatnotalloftheabovefieldsareavailablefromeveryserviceprovider.Someprovidersmaycontain
additionalinformationnotdescribedhere.Consulttheproviderspecificdocumentationforfurtherdetails.
Facebook
TheFacebookstrategyallowsuserstologintoawebapplicationusingtheirFacebookaccount.Internally,
FacebookauthenticationworksusingOAuth2.0.
http://passportjs.org/docs
20/40
3/14/2016
Documentation
SupportforFacebookisimplementedbythepassportfacebookmodule.
Install
$npminstallpassportfacebook
Configuration
InordertouseFacebookauthentication,youmustfirstcreateanappatFacebookDevelopers.Whencreated,
anappisassignedanAppIDandAppSecret.YourapplicationmustalsoimplementaredirectURL,towhich
Facebookwillredirectusersaftertheyhaveapprovedaccessforyourapplication.
varpassport=require('passport')
,FacebookStrategy=require('passportfacebook').Strategy
passport.use(newFacebookStrategy({
clientID:FACEBOOK_APP_ID,
clientSecret:FACEBOOK_APP_SECRET,
callbackURL:"http://www.example.com/auth/facebook/callback"
},
function(accessToken,refreshToken,profile,done){
User.findOrCreate(...,function(err,user){
if(err){returndone(err)}
done(null,user)
})
}
))
http://passportjs.org/docs
21/40
3/14/2016
Documentation
Note:Forsecurityreasons,theredirectionURLmustresideonthesamehostthatisregisteredwithFacebook.
Routes
TworoutesarerequiredforFacebookauthentication.ThefirstrouteredirectstheusertoFacebook.Thesecond
routeistheURLtowhichFacebookwillredirecttheuseraftertheyhaveloggedin.
//RedirecttheusertoFacebookforauthentication.Whencomplete,
//Facebookwillredirecttheuserbacktotheapplicationat
///auth/facebook/callback
app.get('/auth/facebook',passport.authenticate('facebook'))
//FacebookwillredirecttheusertothisURLafterapproval.Finishthe
//authenticationprocessbyattemptingtoobtainanaccesstoken.If
//accesswasgranted,theuserwillbeloggedin.Otherwise,
//authenticationhasfailed.
app.get('/auth/facebook/callback',
passport.authenticate('facebook',{successRedirect:'/',
failureRedirect:'/login'}))
Permissions
Ifyourapplicationneedsextendedpermissions,theycanberequestedbysettingthe scope option.
app.get('/auth/facebook',
passport.authenticate('facebook',{scope:'read_stream'})
)
http://passportjs.org/docs
22/40
3/14/2016
Documentation
Multiplepermissionscanbespecifiedasanarray.
app.get('/auth/facebook',
passport.authenticate('facebook',{scope:['read_stream','publish_actions']})
)
Link
Alinkorbuttoncanbeplacedonawebpage,allowingoneclickloginwithFacebook.
<ahref="/auth/facebook">LoginwithFacebook</a>
Twitter
TheTwitterstrategyallowsuserstosignintoawebapplicationusingtheirTwitteraccount.Internally,Twitter
authenticationworksusingOAuth1.0a.
SupportforTwitterisimplementedbythepassporttwittermodule.
Install
$npminstallpassporttwitter
Configuration
InordertouseTwitterauthentication,youmustfirstcreateanapplicationatTwitterDevelopers.Whencreated,
anapplicationisassignedaconsumerkeyandconsumersecret.Yourapplicationmustalsoimplementa
callbackURL,towhichTwitterwillredirectusersaftertheyhaveapprovedaccessforyourapplication.
http://passportjs.org/docs
23/40
3/14/2016
Documentation
varpassport=require('passport')
,TwitterStrategy=require('passporttwitter').Strategy
passport.use(newTwitterStrategy({
consumerKey:TWITTER_CONSUMER_KEY,
consumerSecret:TWITTER_CONSUMER_SECRET,
callbackURL:"http://www.example.com/auth/twitter/callback"
},
function(token,tokenSecret,profile,done){
User.findOrCreate(...,function(err,user){
if(err){returndone(err)}
done(null,user)
})
}
))
Routes
TworoutesarerequiredforTwitterauthentication.ThefirstrouteinitiatesanOAuthtransactionandredirectsthe
usertoTwitter.ThesecondrouteistheURLtowhichTwitterwillredirecttheuseraftertheyhavesignedin.
//RedirecttheusertoTwitterforauthentication.Whencomplete,Twitter
//willredirecttheuserbacktotheapplicationat
///auth/twitter/callback
app.get('/auth/twitter',passport.authenticate('twitter'))
//TwitterwillredirecttheusertothisURLafterapproval.Finishthe
//authenticationprocessbyattemptingtoobtainanaccesstoken.If
http://passportjs.org/docs
24/40
3/14/2016
Documentation
//accesswasgranted,theuserwillbeloggedin.Otherwise,
//authenticationhasfailed.
app.get('/auth/twitter/callback',
passport.authenticate('twitter',{successRedirect:'/',
failureRedirect:'/login'}))
Link
Alinkorbuttoncanbeplacedonawebpage,allowingoneclicksigninwithTwitter.
<ahref="/auth/twitter">SigninwithTwitter</a>
Google
TheGooglestrategyallowsuserstosignintoawebapplicationusingtheirGoogleaccount.Internally,Google
authenticationworksusingOpenID.
Usingthisstrategydirectly,asopposedtothegeneralpurposeOpenIDstrategy,allowsasitetoofferoneclick
signin.Theuserdoesnothavetoenteranidentifier,whichimprovesusability,albeitattheexpenseoflimiting
choiceofprovider.
SupportforGoogleisimplementedbythepassportgooglemodule.
Install
$npminstallpassportgoogle
http://passportjs.org/docs
25/40
3/14/2016
Documentation
Configuration
WhenusingGoogleforsignin,yourapplicationmustimplementareturnURL,towhichGooglewillredirect
usersaftertheyhaveauthenticated.The realm indicatesthepartofURLspaceforwhichauthenticationisvalid.
TypicallythiswillbetherootURLofyourwebsite.
varpassport=require('passport')
,GoogleStrategy=require('passportgoogle').Strategy
passport.use(newGoogleStrategy({
returnURL:'http://www.example.com/auth/google/return',
realm:'http://www.example.com/'
},
function(identifier,profile,done){
User.findOrCreate({openId:identifier},function(err,user){
done(err,user)
})
}
))
Routes
TworoutesarerequiredforGoogleauthentication.ThefirstrouteredirectstheusertoGoogle.Thesecondroute
istheURLtowhichGooglewillreturntheuseraftertheyhavesignedin.
//RedirecttheusertoGoogleforauthentication.Whencomplete,Google
//willredirecttheuserbacktotheapplicationat
///auth/google/return
http://passportjs.org/docs
26/40
3/14/2016
Documentation
app.get('/auth/google',passport.authenticate('google'))
//GooglewillredirecttheusertothisURLafterauthentication.Finish
//theprocessbyverifyingtheassertion.Ifvalid,theuserwillbe
//loggedin.Otherwise,authenticationhasfailed.
app.get('/auth/google/return',
passport.authenticate('google',{successRedirect:'/',
failureRedirect:'/login'}))
Link
Alinkorbuttoncanbeplacedonawebpage,allowingoneclicksigninwithGoogle.
<ahref="/auth/google">SignInwithGoogle</a>
Basic&Digest
AlongwithdefiningHTTP'sauthenticationframework,RFC2617alsodefinedtheBasicandDigest
authenticationsschemes.Thesetwoschemesbothuseusernamesandpasswordsascredentialsto
authenticateusers,andareoftenusedtoprotectAPIendpoints.
Itshouldbenotedthatrelyingonusernameandpasswordcreditialscanhaveadversesecurityimpacts,
especiallyinscenarioswherethereisnotahighdegreeoftrustbetweentheserverandclient.Inthese
situations,itisrecommendedtouseanauthorizationframeworksuchasOAuth2.0.
SupportforBasicandDigestschemesisprovidedbythepassporthttpmodule.
Install
http://passportjs.org/docs
27/40
3/14/2016
Documentation
$npminstallpassporthttp
Basic
TheBasicschemeusesausernameandpasswordtoauthenticateauser.Thesecredentialsaretransportedin
plaintext,soitisadvisedtouseHTTPSwhenimplementingthisscheme.
Configuration
passport.use(newBasicStrategy(
function(username,password,done){
User.findOne({username:username},function(err,user){
if(err){returndone(err)}
if(!user){returndone(null,false)}
if(!user.validPassword(password)){returndone(null,false)}
returndone(null,user)
})
}
))
ProtectEndpoints
app.get('/api/me',
passport.authenticate('basic',{session:false}),
function(req,res){
res.json(req.user)
})
http://passportjs.org/docs
28/40
3/14/2016
Documentation
Digest
TheDigestschemeusesausernameandpasswordtoauthenticateauser.ItsprimarybenefitoverBasicisthat
itusesachallengeresponseparadigmtoavoidsendingthepasswordintheclear.
Configuration
passport.use(newDigestStrategy({qop:'auth'},
function(username,done){
User.findOne({username:username},function(err,user){
if(err){returndone(err)}
if(!user){returndone(null,false)}
returndone(null,user,user.password)
})
},
function(params,done){
//validatenoncesasnecessary
done(null,true)
}
))
TheDigeststrategyutilizestwocallbacks,thesecondofwhichisoptional.
Thesecond"validatecallback"acceptsnoncerelatedparams,whichcanbecheckedtoavoidreplayattacks.
http://passportjs.org/docs
29/40
3/14/2016
Documentation
ProtectEndpoints
app.get('/api/me',
passport.authenticate('digest',{session:false}),
function(req,res){
res.json(req.user)
})
OAuth
OAuth(formallyspecifiedbyRFC5849)providesameansforuserstograntthirdpartyapplicationsaccessto
theirdatawithoutexposingtheirpasswordtothoseapplications.
Theprotocolgreatlyimprovesthesecurityofwebapplications,inparticular,andOAuthhasbeenimportantin
bringingattentiontothepotentialdangersofexposingpasswordstoexternalservices.
WhileOAuth1.0isstillwidelyused,ithasbeensupersededbyOAuth2.0.Itisrecommendedtobasenew
implementationsonOAuth2.0.
WhenusingOAuthtoprotectAPIendpoints,therearethreedistinctstepsthatthatmustbeperformed:
1.Theapplicationrequestspermissionfromtheuserforaccesstoprotectedresources.
2.Atokenisissuedtotheapplication,ifpermissionisgrantedbytheuser.
3.Theapplicationauthenticatesusingthetokentoaccessprotectedresources.
IssuingTokens
OAuthorize,asiblingprojecttoPassport,providesatoolkitforimplementingOAuthserviceproviders.
http://passportjs.org/docs
30/40
3/14/2016
Documentation
Theauthorizationprocessisacomplexsequencethatinvolvesauthenticatingboththerequestingapplication
andtheuser,aswellaspromptingtheuserforpermission,ensuringthatenoughdetailisprovidedfortheuserto
makeaninformeddecision.
Additionally,itisuptotheimplementortodeterminewhatlimitscanbeplacedontheapplicationregardingscope
ofaccess,aswellassubsequentlyenforcingthoselimits.
Asatoolkit,OAuthorizedoesnotattempttomakeimplementationdecisions.Thisguidedoesnotcoverthese
issues,butdoeshighlyrecommendthatservicesdeployingOAuthhaveacompleteunderstandingofthesecurity
considerationsinvolved.
AuthenticatingTokens
Onceissued,OAuthtokenscanbeauthenticatedusingthepassporthttpoauthmodule.
Install
$npminstallpassporthttpoauth
Configuration
passport.use('token',newTokenStrategy(
function(consumerKey,done){
Consumer.findOne({key:consumerKey},function(err,consumer){
if(err){returndone(err)}
if(!consumer){returndone(null,false)}
returndone(null,consumer,consumer.secret)
})
},
function(accessToken,done){
AccessToken.findOne({token:accessToken},function(err,token){
http://passportjs.org/docs
31/40
3/14/2016
Documentation
if(err){returndone(err)}
if(!token){returndone(null,false)}
Users.findById(token.userId,function(err,user){
if(err){returndone(err)}
if(!user){returndone(null,false)}
//fourthargumentisoptionalinfo.typicallyusedtopass
//detailsneededtoauthorizetherequest(ex:`scope`)
returndone(null,user,token.secret,{scope:token.scope})
})
})
},
function(timestamp,nonce,done){
//validatethetimestampandnonceasnecessary
done(null,true)
}
))
Incontrasttootherstrategies,therearetwocallbacksrequiredbyOAuth.InOAuth,bothanidentifierforthe
requestingapplicationandtheuserspecifictokenareencodedascredentials.
Thefirstcallbackisknownasthe"consumercallback",andisusedtofindtheapplicationmakingtherequest,
includingthesecretassignedtoit.Thesecondcallbackisthe"tokencallback",whichisusedtoindentifythe
useraswellasthetoken'scorrespondingsecret.Thesecretssuppliedbytheconsumerandtokencallbacksare
usedtocomputeasignature,andauthenticationfailsifitdoesnotmatchtherequestsignature.
Afinal"validatecallback"isoptional,whichcanbeusedtopreventreplayattacksbycheckingthetimestampand
nonceusedintherequest.
ProtectEndpoints
app.get('/api/me',
passport.authenticate('token',{session:false}),
http://passportjs.org/docs
32/40
3/14/2016
Documentation
function(req,res){
res.json(req.user)
})
OAuth2.0
OAuth2.0(formallyspecifiedbyRFC6749)providesanauthorizationframeworkwhichallowsuserstoauthorize
accesstothirdpartyapplications.Whenauthorized,theapplicationisissuedatokentouseasanauthentication
credential.Thishastwoprimarysecuritybenefits:
1.Theapplicationdoesnotneedtostoretheuser'susernameandpassword.
2.Thetokencanhavearestrictedscope(forexample:readonlyaccess).
Thesebenefitsareparticularlyimportantforensuringthesecurityofwebapplications,makingOAuth2.0the
predominantstandardforAPIauthentication.
WhenusingOAuth2.0toprotectAPIendpoints,therearethreedistinctstepsthatmustbeperformed:
1.Theapplicationrequestspermissionfromtheuserforaccesstoprotectedresources.
2.Atokenisissuedtotheapplication,ifpermissionisgrantedbytheuser.
3.Theapplicationauthenticatesusingthetokentoaccessprotectedresources.
IssuingTokens
OAuth2orize,asiblingprojecttoPassport,providesatoolkitforimplementingOAuth2.0authorizationservers.
Theauthorizationprocessisacomplexsequencethatinvolvesauthenticatingboththerequestingapplication
andtheuser,aswellaspromptingtheuserforpermission,ensuringthatenoughdetailisprovidedfortheuserto
makeaninformeddecision.
http://passportjs.org/docs
33/40
3/14/2016
Documentation
Additionally,itisuptotheimplementortodeterminewhatlimitscanbeplacedontheapplicationregardingscope
ofaccess,aswellassubsequentlyenforcingthoselimits.
Asatoolkit,OAuth2orizedoesnotattempttomakeimplementationdecisions.Thisguidedoesnotcoverthese
issues,butdoeshighlyrecommendthatservicesdeployingOAuth2.0haveacompleteunderstandingofthe
securityconsiderationsinvolved.
AuthenticatingTokens
OAuth2.0providesaframework,inwhichanarbitrarilyextensiblesetoftokentypescanbeissued.Inpractice,
onlyspecifictokentypeshavegainedwidespreaduse.
BearerTokens
BearertokensarethemostwidelyissuedtypeoftokeninOAuth2.0.Somuchso,infact,thatmany
implementationsassumethatbearertokensaretheonlytypeoftokenissued.
Bearertokenscanbeauthenticatedusingthepassporthttpbearermodule.
Install
$npminstallpassporthttpbearer
Configuration
passport.use(newBearerStrategy(
function(token,done){
User.findOne({token:token},function(err,user){
if(err){returndone(err)}
if(!user){returndone(null,false)}
returndone(null,user,{scope:'read'})
http://passportjs.org/docs
34/40
3/14/2016
Documentation
})
}
))
ProtectEndpoints
app.get('/api/me',
passport.authenticate('bearer',{session:false}),
function(req,res){
res.json(req.user)
})
APISchemes
ThefollowingisalistofstrategiesthatimplementauthenticationschemesusedwhenprotectingAPIendpoints.
http://passportjs.org/docs
Scheme
Specification
Developer
Anonymous
N/A
JaredHanson
Bearer
RFC6750
JaredHanson
Basic
RFC2617
JaredHanson
Digest
RFC2617
JaredHanson
Hash
N/A
YuriKaradzhov
Hawk
hueniverse/hawk
JosF.Romaniello
LocalAPIKey
N/A
SudhakarMani
35/40
3/14/2016
Documentation
OAuth
RFC5849
JaredHanson
OAuth2.0ClientPassword
RFC6749
JaredHanson
OAuth2.0JWTClientAssertion
draftjonesoauthjwtbearer
xTuple
OAuth2.0PublicClient
RFC6749
TimShadel
LogIn
Passportexposesa login() functionon req (alsoaliasedas logIn() )thatcanbeusedtoestablishaloginsession.
req.login(user,function(err){
if(err){returnnext(err)}
returnres.redirect('/users/'+req.user.username)
})
LogOut
Passportexposesa logout() functionon req (alsoaliasedas logOut() )thatcanbecalledfromanyroutehandler
whichneedstoterminatealoginsession.Invoking logout() willremovethe req.user propertyandclearthelogin
session(ifany).
app.get('/logout',function(req,res){
req.logout()
res.redirect('/')
})
http://passportjs.org/docs
36/40
3/14/2016
Documentation
Authorize
Anapplicationmayneedtoincorporateinformationfrommultiplethirdpartyservices.Inthiscase,theapplication
willrequesttheuserto"connect",forexample,boththeirFacebookandTwitteraccounts.
Whenthisoccurs,auserwillalreadybeauthenticatedwiththeapplication,andanysubsequentthirdparty
accountsmerelyneedtobeauthorizedandassociatedwiththeuser.Becauseauthenticationandauthorization
inthissituationaresimilar,Passportprovidesameanstoaccommodateboth.
app.get('/connect/twitter',
passport.authorize('twitterauthz',{failureRedirect:'/account'})
)
app.get('/connect/twitter/callback',
passport.authorize('twitterauthz',{failureRedirect:'/account'}),
function(req,res){
varuser=req.user
varaccount=req.account
//AssociatetheTwitteraccountwiththeloggedinuser.
account.userId=user.id
account.save(function(err){
if(err){returnself.error(err)}
self.redirect('/')
})
}
http://passportjs.org/docs
37/40
3/14/2016
Documentation
)
Configuration
Strategiesusedforauthorizationarethesameasthoseusedforauthentication.However,anapplicationmay
wanttoofferbothauthenticationandauthorizationwiththesamethirdpartyservice.Inthiscase,anamed
strategycanbeused,byoverridingthestrategy'sdefaultnameinthecallto use() .
passport.use('twitterauthz',newTwitterStrategy({
consumerKey:TWITTER_CONSUMER_KEY,
consumerSecret:TWITTER_CONSUMER_SECRET,
callbackURL:"http://www.example.com/connect/twitter/callback"
},
function(token,tokenSecret,profile,done){
Account.findOne({domain:'twitter.com',uid:profile.id},function(err,account){
if(err){returndone(err)}
if(account){returndone(null,account)}
varaccount=newAccount()
account.domain='twitter.com'
account.uid=profile.id
vart={kind:'oauth',token:token,attributes:{tokenSecret:tokenSecret}}
account.tokens.push(t)
returndone(null,account)
})
}
))
http://passportjs.org/docs
38/40
3/14/2016
Documentation
AssociationinVerifyCallback
Onedownsidetotheapproachdescribedaboveisthatitrequirestwoinstancesofthesamestrategyand
supportingroutes.
passport.use(newTwitterStrategy({
consumerKey:TWITTER_CONSUMER_KEY,
consumerSecret:TWITTER_CONSUMER_SECRET,
callbackURL:"http://www.example.com/auth/twitter/callback",
passReqToCallback:true
},
function(req,token,tokenSecret,profile,done){
if(!req.user){
//Notloggedin.AuthenticatebasedonTwitteraccount.
}else{
//Loggedin.AssociateTwitteraccountwithuser.Preservethelogin
//statebysupplyingtheexistinguserafterassociation.
//returndone(null,req.user)
}
}
))
39/40
3/14/2016
Documentation
Supportedby
http://passportjs.org/docs
40/40