96

Getting started with_o_auth_2_0

Embed Size (px)

Citation preview

Page 1: Getting started with_o_auth_2_0
Page 2: Getting started with_o_auth_2_0

GettingStartedwithOAuth2.0RyanBoyd

EditorShawnWallace

EditorMikeLoukides

Copyright©2012RyanBoyd

O’Reillybooksmaybepurchasedforeducational,business,orsalespromotionaluse.Onlineeditionsarealsoavailableformosttitles(http://my.safaribooksonline.com).Formoreinformation,contactourcorporate/institutionalsalesdepartment:(800)[email protected],theNutshellHandbooklogo,andtheO’ReillylogoareregisteredtrademarksofO’ReillyMedia,Inc.GettingStartedwithOAuth2.0,theimageofahornedtrunkfish,andrelatedtradedressaretrademarksofO’ReillyMedia,Inc.Manyofthedesignationsusedbymanufacturersandsellerstodistinguishtheirproductsareclaimedastrademarks.Wherethosedesignationsappearinthisbook,andO’ReillyMedia,Inc.,wasawareofatrademarkclaim,thedesignationshavebeenprintedincapsorinitialcaps.Whileeveryprecautionhasbeentakeninthepreparationofthisbook,thepublisherandauthorsassumenoresponsibilityforerrorsoromissions,orfordamagesresultingfromtheuseoftheinformationcontainedherein.

O'ReillyMedia

Page 3: Getting started with_o_auth_2_0

SPECIALOFFER:UpgradethisebookwithO’ReillyClickhereformoreinformationonthisoffer!Pleasenotethatupgradeoffersarenotavailablefromsamplecontent.

Page 4: Getting started with_o_auth_2_0

ANoteRegardingSupplementalFilesSupplementalfilesandexamplesforthisbookcanbefoundathttp://examples.oreilly.com/0636920021810/.Pleaseuseastandarddesktopwebbrowsertoaccessthesefiles,astheymaynotbeaccessiblefromallereaderdevices.

Allcodefilesorexamplesreferencedinthebookwillbeavailableonline.Forphysicalbooksthatshipwithanaccompanyingdisc,wheneverpossible,we’vepostedallCD/DVDcontent.Notethatwhileweprovideasmuchofthemediacontentasweareableviafreedownload,wearesometimeslimitedbylicensingrestrictions.Pleasedirectanyquestionsorconcernstobooktech@oreilly.com.

Page 5: Getting started with_o_auth_2_0

PrefaceI’vebeenworkingwithweb-basedAPIssince1999,buildingSOAP-basedwebservicesforinternalITapplicationsandhelpingthousandsofdevelopersusingGoogle’sREST-basedAPIsforGoogleCalendar,PicasaWebAlbums,YouTube,andmore.EachoftheseAPIshasrequiredauthorizationfromuserstoactontheirbehalf.DevelopersusingtheseGoogleAPIswereinitiallyrequiredtouseproprietarytechnologieslikeClientLoginandAuthSub.IfthesesamedeveloperswantedtointegratewithAPIsprovidedbyYahoo!,theyneededtouseYahoo!’sBBAuth.TheuseoftheseproprietaryauthorizationtechnologiesmadeitchallengingtobuildapplicationsusingAPIsfrommultipleproviders.

ThedevelopmentofOAuth1.0reducedmanyoftheheadachesfordevelopersandallowedthemtouseasingleauthorizationtechnologyacrosshundredsofAPIsontheWeb.However,OAuth1.0camewithsomechallengesaswell—cryptographicsignaturesandlimiteddefinitionofhowtouseitforauthorizingapplicationsnotusingaserver-to-serverwebapplicationflow.I’mdelightedthatthestandardizationofOAuth2.0isnearlycomplete,asitprovidesanauthorizationprotocolthat’seasytousebothforthesetypesofapplicationsandforavarietyofotherusecases.

PerhapsmostexcitingistheupcomingstandardizationofOpenIDConnect—aprotocolbuiltontopofOAuth2.0toenableusingthesameidentitytologin(authenticate)tomultipleapplications.WhileI’veworkedwithhundredsofdeveloperswhohavesuccessfullybuiltearlierversionsofOpenIDauthenticationintotheirwebapplications,it’srarelybeenaverysmoothprocess.JustasOAuth2.0makesauthorizationeasierfordevelopers,OpenIDConnectdoesthesameforauthentication.

IhopethisbookgivesyouthefoundationknowledgeyouneedtoworkwithOAuth2.0andOpenIDConnectasthenext-generationauthorizationandauthenticationtechnologiesfortheWeb.

ConventionsUsedinThisBookThefollowingtypographicalconventionsareusedinthisbook:

Italic

Indicatesnewterms,URLs,emailaddresses,filenames,andfileextensions.

Constant width

Usedforprogramlistings,aswellaswithinparagraphstorefertoprogramelementssuchasvariableorfunctionnames,databases,datatypes,environmentvariables,statements,andkeywords.

Constant width bold

Showscommandsorothertextthatshouldbetypedliterallybytheuser.

Constant width italic

Showstextthatshouldbereplacedwithuser-suppliedvaluesorbyvaluesdeterminedbycontext.

TIP

Thisiconsignifiesatip,suggestion,orgeneralnote.

Page 6: Getting started with_o_auth_2_0

CAUTION

Thisiconindicatesawarningorcaution.

Page 7: Getting started with_o_auth_2_0

UsingCodeExamplesThisbookisheretohelpyougetyourjobdone.Ingeneral,youmayusethecodeinthisbookinyourprogramsanddocumentation.Youdonotneedtocontactusforpermissionunlessyou’rereproducingasignificantportionofthecode.Forexample,writingaprogramthatusesseveralchunksofcodefromthisbookdoesnotrequirepermission.SellingordistributingaCD-ROMofexamplesfromO’Reillybooksdoesrequirepermission.Answeringaquestionbycitingthisbookandquotingexamplecodedoesnotrequirepermission.Incorporatingasignificantamountofexamplecodefromthisbookintoyourproduct’sdocumentationdoesrequirepermission.

Weappreciate,butdonotrequire,attribution.Anattributionusuallyincludesthetitle,author,publisher,andISBN.Forexample:“GettingStartedwithOAuth2.0byRyanBoyd(O’Reilly).Copyright2012RyanBoyd,978-1-449-31160-5.”

Ifyoufeelyouruseofcodeexamplesfallsoutsidefairuseorthepermissiongivenabove,[email protected].

Page 8: Getting started with_o_auth_2_0

Safari®BooksOnlineNOTE

SafariBooksOnlineisanon-demanddigitallibrarythatletsyoueasilysearchover7,500technologyandcreativereferencebooksandvideostofindtheanswersyouneedquickly.

Withasubscription,youcanreadanypageandwatchanyvideofromourlibraryonline.Readbooksonyourcellphoneandmobiledevices.Accessnewtitlesbeforetheyareavailableforprint,andgetexclusiveaccesstomanuscriptsindevelopmentandpostfeedbackfortheauthors.Copyandpastecodesamples,organizeyourfavorites,downloadchapters,bookmarkkeysections,createnotes,printoutpages,andbenefitfromtonsofothertime-savingfeatures.

O’ReillyMediahasuploadedthisbooktotheSafariBooksOnlineservice.TohavefulldigitalaccesstothisbookandothersonsimilartopicsfromO’Reillyandotherpublishers,signupforfreeathttp://my.safaribooksonline.com.

Page 9: Getting started with_o_auth_2_0

HowtoContactUsPleaseaddresscommentsandquestionsconcerningthisbooktothepublisher:

O’ReillyMedia,Inc.

1005GravensteinHighwayNorth

Sebastopol,CA95472

800-998-9938(intheUnitedStatesorCanada)

707-829-0515(internationalorlocal)

707-829-0104(fax)

Wehaveawebpageforthisbook,wherewelisterrata,examples,andanyadditionalinformation.Youcanaccessthispageat:

http://shop.oreilly.com/product/0636920021810.do

Tocommentorasktechnicalquestionsaboutthisbook,sendemailto:

[email protected]

Formoreinformationaboutourbooks,courses,conferences,andnews,seeourwebsiteathttp://www.oreilly.com.

FindusonFacebook:http://facebook.com/oreilly

FollowusonTwitter:http://twitter.com/oreillymedia

WatchusonYouTube:http://www.youtube.com/oreillymedia

Page 10: Getting started with_o_auth_2_0

AcknowledgmentsI’dliketothanktheidentityandauthteamsatGoogleforprovidingyearsofguidanceandexpertise,andmostimportantlyEricSachs,MariusScurtescu,andBrenodeMedeirosfortheirreviewandfeedbackonthisbook.Ialsowouldliketothankmyfamily,friends,andcolleaguesinGoogle’sDeveloperRelationsgroupfortheirconstantsupport.

Ofcourse,withoutthefantasticworkoftheOAuthspecauthorsandworkinggroups,nobodywouldhaveachancetouseorwriteaboutOAuth.

Page 11: Getting started with_o_auth_2_0

Chapter1.IntroductionHowOAuthWasBornInthemovieFerrisBueller’sDayOff,avaletattendanttakesafullyrestored1961Ferrarioutforajoyride.Howdoyoupreventthesamethingfromhappeningtoyourbrand-newMustang?Somecarsnowcomewithspecialkeysthatallowtheownertoprovidelimitedauthorizationtovaletattendants(orkids!)andpreventactivitiessuchasopeningthetrunkanddrivingatexcessivespeeds.

OAuthwascreatedtosolvethesamecoreissueonline.

WhenGooglefirstreleasedtheGoogleCalendarAPI,itprovidedtheabilityforapplicationdeveloperstoreadandmanipulateauser’sGoogleCalendar.However,theonlywayforausertoprovidedelegatedaccesswastogivetheapplicationhisorheraccountusernameandpassword,whichtheapplicationwouldthenusewithGoogle’sproprietaryClientLoginprotocol.

ProprietaryprotocolslikeClientLoginandstandardprotocolslikeHTTPBasicauthenticationresultedinbothsmallandbigapplicationsrequestingpasswordsfromuserstogetaccesstotheirdata.Thiswasn’taffectingjustdesktopapps—applicationsallovertheWebwerepromptingforcredentials.Flickr,anonlinephoto-sharingsite,wasonesuchapplication.Originallyanindependentcompany,FlickrwasacquiredbyYahoo!afewyearsafterGoogleboughtBlogger.TheideaofYahoo!askingforGoogleuserpasswordsscaredbothfirms,leadingtothedevelopmentofnewproprietaryprotocolsthattackledthisproblemontheWeb.

Withthesenewprotocols,suchasGoogle’sAuthSub(seeFigure1-1)andYahoo!’sBBAuth,anapplicationwouldredirectuserstoanauthorizationpageontheprovider’ssiteiftheappneededaccesstouserdata.Userswouldlogintotheiraccountsandgrantaccess,andthentheapplicationwouldgetatokentouseforaccessingtheusers’data.

Figure1-1.Google’sAuthSubapprovalscreen,askingusersforpermissionfortheirGoogleCalendar

Whilethissolvedsomesecurityissues,italsocreatedcostsfordevelopers.Developersintegratingwith

Page 12: Getting started with_o_auth_2_0

multiplemajorAPIprovidershadtolearnandimplementseveralweb-basedauthorizationprotocolsintheirapplications.StartupsbuildingnewAPIswerenotcomfortableimplementingtheproprietaryauthschemes,nordevelopingtheirowncustomschemes,whichmightintroducesecurityvulnerabilities.Instead,thesestartupsandmajorAPIprovidersdecidedthattheyneededtocreateastandardprotocoltoimproveconsistencyfortheseweb-basedauthorizationflows.

Page 13: Getting started with_o_auth_2_0

WhyDevelopersShouldCareAboutOAuthWithwideadoptionofcollaborationplatformsandsocialnetworks,applicationdevelopershavetheopportunitytoconnectuserswiththeirdatawherevertheyareontheWeb.Connectinguserswiththeirdataresultsinimprovedday-to-dayefficiencybyeliminatingdatasilosandalsoallowsdeveloperstodifferentiatetheirapplicationsfromthecompetition.

OAuthprovidestheabilityfortheseapplicationstoaccessauser’sdatasecurely,withoutrequiringtheusertotakethescarystepofhandingoveranaccountpassword.

TypesoffunctionalityprovidedbyOAuth-enabledAPIsincludethefollowing:

Gettingaccesstoauser’ssocialgraph—theirFacebookfriends,peoplethey’refollowingonTwitter,ortheirGoogleContacts

Sharinginformationaboutauser’sactivitiesonyoursitebypostingtotheirFacebookwallorTwitterstream

Accessingauser’sGoogleDocsorDropboxaccounttostoredataintheironlinefilesystemofchoice

IntegratingbusinessapplicationswithoneanothertodrivesmarterdecisionsbymashingupmultipledatasourcessuchasaSalesforceCRMandTripIttravelplan

InordertoaccessorupdateprivatedataviaeachoftheseAPIs,anapplicationneedstobedelegatedaccessbytheownerofthedata.EachoftheseAPIs,andover300morearoundtheWeb(accordingtoProgrammableWebinFebruary2012),supportOAuthforgettingaccess.

HavingacommonprotocolforhandlingAPIauthorizationgreatlyimprovesthedeveloperexperiencebecauseitlessensthelearningcurverequiredtointegratewithanewAPI.Atthesametime,anauthorizationstandardcreatesmoreconfidenceinthesecurityofAPIsbecausethestandardhasbeenvettedbyalargecommunity.

Page 14: Getting started with_o_auth_2_0

WhyDon’tTheseAPIsJustUsePasswordsforAuthorization?UsernamesandpasswordsaretypicallythelowestcommondenominatorforauthenticationandauthorizationontheWeb.TheyareusedforHTTPBasicandHTTPDigestauthenticationandoncountlessloginpages.However,askingauserfortheirpasswordhasanumberofsideeffects:

Trust

Ausermaynottrustprovidingtheirpasswordtoyourapplication.

Decreasedusersensitivitytophishing

Eveniftheuseriscomfortableprovidingtheirpasswordtoyourapplication,makingtheusercomfortabledoingthisaroundtheWebcanhavenegativelong-termeffects,suchasmakingphishingscamsmoreeffective.

Expandedaccessandrisk

Whentheuserprovidestheirpasswordtoyourapplication,yougetaccesstonotonlythedatayourapplicationneeds,butallotherdataintheuser’saccount.Theapplicationhasanobligationtoitsuserstosecurelystorethesepasswordsandpreventthemfromleaking.Manydevelopersdonotwanttheriskexposureofhavingthisadditionalresponsibility.

Limitedreliability

Whenauserchangestheirpassword,yourapplicationnolongerhasaccesstotheirdata.

Revocationchallenges

Theonlywayausercanrevokeaccesstoyourapplicationisbychangingtheirpassword,whichalsorevokesaccesstoallotherapps.

Passwordsbecomerequired

WhenanAPIprovidersupportsfederatedauthenticationmechanismssuchasOpenIDorSAML(seeFederatedAuthentication),usersmaynothavepasswordsontheiraccounts.ThismakesitimpossibleforthoseuserstouseapplicationspoweredbytheAPI.

Difficultyimplementingstrongerauthentication

IfanAPIproviderrequirespasswordsforAPIauthentication,itbecomeschallengingtoimproveaccountsecuritywithtechnologieslikeCAPTCHAsormultifactorauthentication(suchasone-timepasswordtokens).

Page 15: Getting started with_o_auth_2_0

TerminologyInordertounderstandOAuth,it’simportanttofirstunderstandtherelevantterminology.We’llintroducesomekeytermsupfront,andthendiscussadditionaltermsthroughoutthebook.

AuthenticationAuthenticationistheprocessofverifyingtheidentityofauser—knowingthattheuseriswhotheyclaimtobe.

Intherealworld,whenapoliceofficerasksforyouridentification,she’sverifyingyouridentitybyensuringthatthepictureonyouridentificationmatchesyourlikeness.

OndesktopcomputersandontheWeb,authenticationisaboutknowingthattheuseratthekeyboardistheowneroftheaccount.Authenticationistypicallyperformedbyaskingauserforausernameandpassword.Theusernamerepresentstheuser’sclaimedidentity,andthesoftwareapplicationassumesthatiftheuserprovidesthecorrectpasswordthattheyareindeedthatuser.

FederatedAuthenticationAlthoughmanyapplicationshavetheirownsystemofaccounts(includingusernamesandpasswords),someapplicationsrelyonotherservicestoverifytheidentityofusers.Thisiscalledfederatedauthentication.

InacorporateITenvironment,applicationsmaytrustanActiveDirectoryserver,aLDAPserver,oraSAMLprovidertoauthenticateusers.

OntheWeb,applicationsoftentrustOpenIDproviders(suchasGoogleorYahoo!)tohandletheauthenticationofusers.Therearemanybenefitstofederationforbothapplicationdevelopersandusers.OpenIDisthemostcommonopenwebprotocolforhandlingfederatedauthentication.

AlthoughOpenIDhasbeenusedontheWebformanyyears,we’lldiscussonlyOpenIDConnect,whichisthenext-generationversionofOpenIDbasedonOAuth2.0.

AuthorizationAuthorizationistheprocessofverifyingthatauserhastherighttoperformsomeaction,suchasreadingadocumentoraccessinganemailaccount.Thistypicallyfirstrequiresvalididentificationoftheuser(authentication)inordertocheckwhethertheactualuserisauthorized.

Whenapoliceofficerpullsoveryourcarforspeeding,shefirstauthenticatesyouusingyourdriver’slicense(toverifyyouridentity)andthenchecksthelicense(expirationdate,restrictions,etc.)toensureyou’reauthorizedtodrive.

Thesameprocesshappensonline—awebapplicationfirstverifiesyouridentitybyloggingyouin,andthenitensuresthatyouaccessonlythedataandservicesyou’reallowedto,typicallybycheckinganaccesscontrollistforeachoperation.

Page 16: Getting started with_o_auth_2_0

DelegatedAuthorizationDelegatedauthorizationisgrantingaccesstoanotherpersonorapplicationtoperformactionsonyourbehalf.

Whenyoudriveyourcartoaclassyhotel,theymayoffervaletparking.Youthenauthorizethevaletattendanttodriveyourcarbyhandinghimthekeyinordertolethimperformactionsonyourbehalf.

OAuthworkssimilarly—ausergrantsaccesstoanapplicationtoperformactionsontheuser’sbehalfandtheapplicationcanonlyperformtheauthorizedactions.

RolesThereareseveralkeyactorsintheOAuthprotocolflows:

Resourceserver

Theserverhostinguser-ownedresourcesthatareprotectedbyOAuth.ThisistypicallyanAPIproviderthatholdsandprotectsdatasuchasphotos,videos,calendars,orcontacts.

Resourceowner

Typicallytheuserofanapplication,theresourceownerhastheabilitytograntaccesstotheirowndatahostedontheresourceserver.

Client

AnapplicationmakingAPIrequeststoperformactionsonprotectedresourcesonbehalfoftheresourceownerandwithitsauthorization.

Authorizationserver

Theauthorizationservergetsconsentfromtheresourceownerandissuesaccesstokenstoclientsforaccessingprotectedresourceshostedbyaresourceserver.SmallerAPIprovidersmayusethesameapplicationandURLspaceforboththeauthorizationserverandresourceserver.

Page 17: Getting started with_o_auth_2_0

TheGreatDebateoverSignaturesOAuth1.0requiredcryptographicsignaturesbesentwitheachAPIrequesttoverifytheidentityandauthorizationoftheclient.Cryptographyischallengingforthecasualdevelopertograspandalsochallengingforevenhighlyskilledengineerstomaster.Thisledtoplentyofdeveloperfrustrationand,presumably,lessadoptionofAPIsthancouldhavebeenachievedwithaneasierauthorizationprotocol.

WhenOAuth1.0wasdevelopedin2007,itwasdecidedthatcryptographicsignatureswerenecessarytosupportthesecurityofAPIs.Atthetime,manytopAPIprovidershostedtheirAPIsatvanillaHTTPendpoints,withoutSSL/TLSprotection.Overtheyears,SSL/TLSbecameamorecommonwayofprotectingAPIsandtheneedforsignaturesdecreasedintheeyesofsomemembersofthesecuritycommunity.

CombiningtheperceptionoflowAPIadoptionduetothecomplexityofcryptographyinOAuth1.0andthegreaterprevalenceofSSL/TLSsupportforAPIsledtothedevelopmentoftheOAuthWebResourceAuthorizationProfiles(WRAP)specification.OAuthWRAPisthepredecessortoOAuth2.0—iteliminatedthecomplexsignaturerequirementsandintroducedtheuseofbearertokens.

EvenasOAuth2.0nearsfinalizationinthestandardscommunity,thereremainssomestrongindividualoppositiontonotrequiringtheuseofsignatures,includingbyEranHammer-Lahav,theeditorofthespecification.EranhaswrittenablogposttitledOAuth2.0(withoutSignatures)IsBadfortheWeb,inwhichheacknowledgesthecomplexityofsignaturesforsomedevelopersbutdefendstheirvalue.HemainlypointsoutthatremovingsignaturesfromOAuth2.0makesiteasyfordeveloperstomakemistakesandaccidentallysendtheircredentialstoamaliciousAPIendpoint,whichcanthenabusethesecredentialstomakeadditionalrequestsbecausethey’renotprotectedbyasignature.Whilehearguesthatthisisn’tlikelytoday,hedoesbelieveitwillbecomemorecriticalasautomateddiscoveryisaddedforAPIandOAuthendpoints.OthersidentifycryptographicsignaturesasafeaturethatallowsforgreaterconfidenceintheoriginofAPIrequestsastherequestspassthroughmultitieredarchitectures.

Engineersoftenhavetostrikeadelicatebalancebetweensecurityandusability,andthiscaseisnodifferent.

MitigatingConcernswithBearerTokensOneoftheprimaryconcernswiththeeliminationofsignaturesisthatdeveloperswillnotproperlyverifySSL/TLScertificatechainswhenmakingrequeststotheauthorizationandresourceservers.ThisisrequiredbythespecificationandaddressedintheOAuth2.0threatmodeldocument,buttheeaseofdisablingpropercertificateandcertificateauthorityvalidationinpopularlibraries,combinedwiththedifficultyoffixingissuesassociatedwithit,hasresultedinmanydeveloperstakingshortcutsthatthreatenthesecurityoftheirapplications.

WhenimplementingOAuth2.0,callinganyAPIs,orusingalibrary,youshouldverifythatitproperlyhandlesSSL/TLScertificatechainvalidationbydoingthefollowingthings:

CheckingthatthehostnameonthecertificatereturnedbytheservermatchesthehostnameintheURLbeingaccessed

Page 18: Getting started with_o_auth_2_0

Verifyingeachcertificateinthechainproperlychainsuptoavalidandtrustedcertificateauthority(CA)

Ensuringthatthecertificateauthoritybundleonyourserverissecureandnotabletobemodifiedbypotentialattackers

SigningYourOAuth2.0RequestsTheMACAccessAuthenticationspecificationdefineshowclientscansigntheirOAuth2.0requestswhensignaturesaresupportedorrequiredbytheAPIprovider.

Author’sNote:Ifyou’rethinkingMAConlyreferstoatypeofcomputer,youcanunderstandwhysignaturesarehardformanydevelopers!Youmightwanttofindagoodbookoncryptography.

GettingthekeyInordertosignrequestsusingMACauthentication,theclientmustfirstgetaMACkey.ThiscanbeissuedbytheOAuthauthorizationserver.Inthiscase,thekeyisreturnedeachtimeanaccess_tokenisreturnedbytheauthorizationserver.ThisMACkeymustbeforuseineitherthehmac-sha-1orhmac-sha-256algorithms.Alternatively,theMACkeycanbeissuedinanout-of-bandprocess,suchaswhenthedeveloperregisterstheirapplicationwiththeAPIprovider.Regardlessofhowthekeyisissued,itmustalwaysbeissuedoverasecureSSL/TLSchannelandmustbekeptconfidential.

MakingAPIrequestsWhenconnectingtoOAuth-enabledAPIsthatrequiresignatures,eachAPIrequestmustincludeaMACsignatureintheAuthorizationheaderoftherequest.Theprocessofgeneratingthissignatureinvolvescreatinganormalizedrequeststring(nonce,HTTPmethod,requestURI,host,port,optionalbodyhash,etc.)andperformingacryptographicsignature.ItishighlyrecommendedthatdevelopersuseaprebuiltlibrarytohandleOAuthMACsigningifneeded.Ifyouneedtobuildyourownimplementation,pleaseseethespecification,asthedetailsareoutofscopeforthisbook.

Page 19: Getting started with_o_auth_2_0

DeveloperandApplicationRegistrationOAuthrequiresthatapplicationsregisterwiththeauthorizationserversothatAPIrequestsareabletobeproperlyidentified.Whiletheprotocolallowsforregistrationusingautomatedmeans,mostAPIprovidersrequiremanualregistrationviafillingoutaformontheirdeveloperwebsites.

Atthetimeofthiswriting

GooglerequiresyoutoregisteryourclientbyvisitingitsAPIsConsole,asshowninFigure1-2.

MicrosoftWindowsLiverequiresyoutoregisteryourclientusingitsapplicationmanagementsite.

FacebookrequiresyoutoregisteryourclientontheFacebookDeveloperssite.

Figure1-2.Google’sAPIsConsoleforOAuthappregistration

Asanexample,thefollowinginformationisrequiredtoregisteranOAuthclientwithGoogleviatheirAPIsConsole:

GoogleAccount

ProductName

ProductLogo(optional)

WebsiteURLusedforRedirectURIs(forwebapplicationsonly)

Afterregistrationiscomplete,thedeveloperisissuedclientcredentials:

ClientID

Specifiedasclient_idwheninteractingwiththeresourceserver

ClientSecret

Specifiedasclient_secretwhenexchanginganauthorizationcodeforanaccesstokenandrefreshingaccesstokensusingtheserver-sideWebApplicationFlow(seeFigure7-1).

WhyIsRegistrationNecessary?

Page 20: Getting started with_o_auth_2_0

Registrationenablestheapplicationdevelopertoobtainclientcredentials,whichareusedtoauthenticaterequestsmadetotheauthorizationserver.Thesecredentialsarecriticalinprotectingtheauthenticityofrequestswhenperformingoperationssuchasexchangingauthorizationcodesforaccesstokensandrefreshingaccesstokens(asdescribedinChapter2).

RegistrationalsogivestheAPIproviderinformationtoimprovetheuserexperienceduringtheauthorizationprocess.Whenpresentinganapplication’srequestfordataaccesstotheuser,theAPIproviderwilloftendisplaythenameandlogooftheapplication.

SeeFigure2-3foranexampleofhowGoogleusestheregistrationinformationontheapprovalscreen.

Page 21: Getting started with_o_auth_2_0

ClientProfiles,AccessTokens,andAuthorizationFlowsThefirstversionofOAuthwasdesignedprimarilytohandleAPIauthorizationforclassicclient-serverwebapplications.Thespecificationdidnotdefinehowtohandleauthorizationinmobileapplications,desktopapplications,JavaScriptapplications,browserextensions,orothersituations.WhileeachofthesetypesofappshavebeenwrittenusingOAuth1.0,themethodofimplementationisinconsistentandoftensuboptimal,astheprotocolwasn’tdesignedforthesecases.

OAuth2.0wasarchitectedwiththisvarietyofusecasesinmind.

ClientProfilesOAuth2.0definesseveralimportantclientprofiles:

Server-sidewebapplication

AnOAuthclientrunningonawebserver.Thewebapplicationisaccessedbyaresourceowner(user)andtheapplicationmakestheappropriateAPIcallsusingaserver-sideprogramminglanguage.TheuserhasnoaccesstotheOAuthclientsecretoranyaccesstokensissuedbytheauthorizationserver.

Client-sideapplicationrunninginawebbrowser

AnOAuthclientrunninginauser’swebbrowser,wheretheclienthasaccesstotheapplicationcodeand/orAPIrequests.TheapplicationcouldbedistributedasJavaScriptincludedinawebpage,asabrowserextension,orusingaplug-intechnologysuchasFlash.TheOAuthcredentialsarenottrustedtobekeptconfidentialfromtheresourceowner,sosomeAPIproviderswon’tissueclientsecretsforapplicationsusingthisprofile.

Nativeapplication

AnOAuthclientwhichisverysimilartotheclient-sideapplication,asthecredentialsarenottrustedtobekeptconfidential.However,sinceit’saninstalledapplication,itmaynothaveaccesstothefullcapabilitiesofawebbrowser.

AccessTokensAlthoughsignature-basedMACAccessAuthenticationwasmentionedearlier,mostOAuth2.0authorizedAPIsrequireonlybearertokenstomakeauthorizedrequests.Bearertokensareatypeofaccesstokenwherebysimplepossessionofthetokenvaluesprovidesaccesstoprotectedresources.Noadditionalinformation,suchasacryptographickey,isneededtomakeAPIcalls.

Whetheryou'rebuildingaserver-sidewebapplication,client-sidewebapplication,oranativeapplication,theendgoalofusingOAuthisthesame:you’retryingtoobtainanOAuthaccesstokenthatyourapplicationcanusetoperformAPIrequestsonbehalfofauserortheapplicationitself.

Afterobtaininganaccesstoken,thetokencanbesentalongwithyourrequestsinoneofseveralways.ThepreferredmethodofauthorizingrequestsisbysendingtheaccesstokeninaHTTPAuthorizationheader:

GET /tasks/v1/lists/@default/tasks HTTP/1.1

Page 22: Getting started with_o_auth_2_0

Host: www.googleapis.comAuthorization: Bearer ya29.AHES6ZSzX

TheAuthorizationheaderisthepreferredmechanismbecause

Theheaderisrarelyloggedbyproxyserversandwebserveraccesslogs.

Theheaderisalmostnevercached.

Theheaderdoesn’tgetstoredinthebrowsercachewhenmakingrequestsfromtheclient.

Whiletheothermechanismsaredefinedinthespecification,APIprovidersarenotrequiredtoimplementanyoftheseadditionalmethods,soyourmileagewillvary:

Queryparameter

Includingtheaccess_tokenasaURLqueryparameterisusefulfordebuggingandwhenlibrariesmakeitdifficulttomodifytheAuthorizationheader.Thismechanismisalsovaluablewhenusingtheclient-sideflowandsendingatokeninaJSONPrequest.Forexample,

https://www.googleapis.com/tasks/v1/lists/@default/tasks?callback=outputTasks&access_token=ya29.AHES6ZTh00gsAn4

Form-encodedbodyparameter

ThisisafallbackmechanismforwhenanapplicationcannotmodifytheAuthorizationheaderonrequests.ItisonlytobeusedwhenaHTTPbodywouldnormallybesentandcanthenbeaddedasanadditionalformparameterinanapplication/ x-www-form-urlencodedbody.ThismechanismisnotsupportedbytheGoogleTasksAPI.

AuthorizationFlowsEachoftheclientprofilesneedstobeaccommodatedwithanappropriateprotocolflowforobtainingauthorizationfromtheresourceownerforaccesstotheirdata.ThecoreOAuth2.0protocoldefinesfourprimary“granttypes”usedforobtainingauthorizationandalsodefinesanextensionmechanismforenablingadditionalgranttypes.

Authorizationcode

Thisgranttypeismostappropriateforserver-sidewebapplications.Aftertheresourceownerhasauthorizedaccesstotheirdata,theyareredirectedbacktothewebapplicationwithanauthorizationcodeasaqueryparameterintheURL.Thiscodemustbeexchangedforanaccesstokenbytheclientapplication.Thisexchangeisdoneserver-to-serverandrequiresboththeclient_idandclient_secret,preventingeventheresourceownerfromobtainingtheaccesstoken.Thisgranttypealsoallowsforlong-livedaccesstoanAPIbyusingrefreshtokens.

Implicitgrantforbrowser-basedclient-sideapplications

Theimplicitgrantisthemostsimplisticofallflows,andisoptimizedforclient-sidewebapplicationsrunninginabrowser.Theresourceownergrantsaccesstotheapplication,andanewaccesstokenisimmediatelymintedandpassedbacktotheapplicationusinga#hashfragmentintheURL.Theapplicationcanimmediatelyextracttheaccesstokenfromthehashfragment(usingJavaScript)andmakeAPIrequests.Thisgranttypedoesnotrequiretheintermediary“authorizationcode,”butitalso

Page 23: Getting started with_o_auth_2_0

doesn’tmakeavailablerefreshtokensforlong-livedaccess.

Resourceownerpassword-basedgrant

Thisgranttypeenablesaresourceowner’susernameandpasswordtobeexchangedforanOAuthaccesstoken.Itisusedforonlyhighly-trustedclients,suchasamobileapplicationwrittenbytheAPIprovider.Whiletheuser’spasswordisstillexposedtotheclient,itdoesnotneedtobestoredonthedevice.Aftertheinitialauthentication,onlytheOAuthtokenneedstobestored.Becausethepasswordisnotstored,theusercanrevokeaccesstotheappwithoutchangingthepassword,andthetokenisscopedtoalimitedsetofdata,sothisgranttypestillprovidesenhancedsecurityovertraditionalusername/passwordauthentication.

Clientcredentials

Theclientcredentialsgranttypeallowsanapplicationtoobtainanaccesstokenforresourcesownedbytheclientorwhenauthorizationhasbeen“previouslyarrangedwithanauthorizationserver.”ThisgranttypeisappropriateforapplicationsthatneedtoaccessAPIs,suchasstorageservicesordatabases,onbehalfofthemselvesratherthanonbehalfofaspecificuser.

Theseadditionalflowsaredefinedoutsideofthecorespec:

Deviceprofile

ThedeviceprofilewascreatedtoenableOAuthtobeusedondevicesthatdonothavebuilt-inwebbrowsersorhavelimitedinputoptions—suchasagameconsoleorelectronicphotoframe.Theusertypicallyinitiatestheflowonthedeviceandisthentoldtouseacomputertoaccessawebsiteandapproveaccessforthedevicebytypinginanauthorizationcodedisplayedinthedevice.Facebookhasagreatexampleofthisflowreferencedinitsdocumentation.

SAMLbearerassertionprofile

ThisprofileenablesexchangingSAML2.0assertionforanOAuthaccesstoken.ThisisusefulinenterpriseenvironmentsthatalreadyhaveSAMLauthorizationserverssetuptocontrolapplicationanddataaccess.

Page 24: Getting started with_o_auth_2_0

Chapter2.Server-SideWebApplicationFlowIntheWebApplicationflow(alsoknownastheAuthorizationCodeflow),theresourceownerisfirstredirectedbytheapplicationtotheOAuthauthorizationserverattheAPIprovider.Theauthorizationservercheckstoseeiftheuserhasanactivesession.Ifshedoes,theauthorizationserverpromptsherforaccesstotherequesteddata.Aftershegrantsaccess,sheisredirectedbacktothewebapplicationandanauthorizationcodeisincludedintheURLasthecodequeryparameter:

http://www.example.com/oauth_callback?code=ABC1234

Becausethecodeispassedasaqueryparameter,thewebbrowsersendsitalongtothewebserverthatisactingastheOAuthclient.Thisauthorizationcodeisthenexchangedforanaccesstokenusingaserver-to-servercallfromtheapplicationtotheauthorizationserver.ThisaccesstokenisusedbytheclienttomakeAPIcalls.

Soundconfusing?Figure2-1showstheflowstep-by-step,basedonadiagramfromthespecification.

Page 25: Getting started with_o_auth_2_0

Figure2-1.Server-sideWebApplicationflow:Step-by-step

WhenShouldtheAuthorizationCodeFlowBeUsed?TheAuthorizationCodeflowshouldbeusedwhen

Long-livedaccessisrequired.

TheOAuthclientisawebapplicationserver.

AccountabilityforAPIcallsisveryimportantandtheOAuthtokenshouldn’tbeleakedtothebrowser,

Page 26: Getting started with_o_auth_2_0

wheretheusermayhaveaccesstoit.

Page 27: Getting started with_o_auth_2_0

SecurityPropertiesTheAuthorizationCodeflowdoesnotexposetheaccesstokentotheresourceowner’sbrowser.Instead,authorizationisaccomplishedusinganintermediary“authorizationcode”thatispassedthroughthebrowser.ThiscodemustbeexchangedforanaccesstokenbeforecallscanbemadetoprotectedAPIs.Theexchangeprocessonlysucceedsifacorrectclient_secretispassedwiththerequest,ensuringconfidentialityoftheaccesstokenaslongasclientsecurityismaintained.UnlikewiththeImplicitflowdescribedinChapter3,thisconfidentialityalsoextendstotheresourceowner,meaningAPIrequestsmadewiththeaccesstokenaredirectlyattributabletotheclientanditsdevelopers.Perhapsmostimportantly—becausetheaccesstokenisneversentthroughthebrowser—thereislessriskthattheaccesstokenwillbeleakedtomaliciouscodethroughbrowserhistory,refererheaders,JavaScript,andthelike.

Althoughthereislesschanceoftheaccesstokenleakingbecauseit’snotexposedtothebrowser,manyapplicationsusingthisflowwillstorelong-livedrefreshtokensintheapplication’sdatabaseorkeystoretoenable“offline”accesstodata.Thereisadditionalriskwhenanapplicationrequireslong-livedofflineaccesstodata,asthiscreatesasinglepointofcompromiseforaccessingdatabelongingtomanyusers.Thisdoesn’texistwithotherflows,suchastheflowforclient-sidewebapplications(seeChapter3).Evenwiththisadditionalrisk,manywebsiteswillchoosetouse“offline”dataaccessbecausetheirapplicationarchitecturemakesitdifficulttointeractwiththeuser’sbrowsertoobtainnewaccesstokens.

Page 28: Getting started with_o_auth_2_0

UserExperienceLet’stakeanexampleofapayrollapplication.Thepayrollapplicationwantsaccesstoupdateamanager’stasklisttoremindthemanagertoapprovetimesheets.Byplacingtheseremindersinthemanager’stasklist,whichthemanageruseseveryday,it’smuchmorelikelythatemployeeswillgetpaidontime,reducingthenumberofangryemployeesandtime-consumingcallstotheHRdepartment.

Theuserexperienceinthemostcommoncaseisverysimple:

1. Payrollapplicationletsthemanagerknowthatit’saskingforaccesstomodifyhertasks,andredirectsherovertothetasklistapp’sOAuthauthorizationserver(seeFigure2-2).

2. TheOAuthauthorizationserverusedbythetasklistapp’sAPIpromptstheusertograntpermissionforthepayrollapplicationtoupdatehertasks(seeFigure2-3).

3. Aftertheuserhasapproved,sheisredirectedbacktothepayrollapplication,whichnowhasaccesstothetasks(seeFigure2-4).

Page 29: Getting started with_o_auth_2_0

Step-by-StepAfterregisteringyourapp(seeDeveloperandApplicationRegistration)withtheAPIproviderandobtaininganOAuthclientIDandclientsecret,it’stimetostartwritingcode!Let’sgothrougheachstepoftheflowandshowhowtheprotocolworks.We’llusePHPastheexampleprogramminglanguageandtheGoogleTasksAPIalongwithGoogle’sOAuth2.0authorizationserver.

Althoughwe’llwritethePHPcodeusingtherawOAuthprotocol,manyAPIprovidersdistributeclientlibrariesforaccessingtheirservices.TheselibrariesabstractawaysomeofthedetailsofimplementingOAuth2.0andmakeiteasierfordevelopers.YoucanfindinformationonGoogle’sPHPlibrary,whichworkswithGoogleTasks,Google+,andmanyotherGoogleAPIs,atcode.google.com.

Step1:Lettheuserknowwhatyou’redoingandrequestauthorizationSincetheOAuthflowinvolvesdirectingyouruserstothewebsiteoftheAPIprovidertoobtainauthorization,it’sabestpracticetoletthemknowinadvancewhatwillhappen.Youcandothisbydisplayingamessage,alongwithalink(the“AddtaskstoyourGoogleTasks”linkinFigure2-2).

Aftertheuserinitiatestheflow,yourapplicationwillneedtosendtheuser’sbrowsertotheOAuthauthorizationpage(asseeninFigure2-3).Thiscanbedoneeitherbysendingthemainbrowserwindowdirectlytotheauthorizationendpointorbycreatingapopup.Onthispage,theAPIproviderwillpresenttheuserwitharequesttoapprovetheapplication’sabilitytoaccesstheuser’sdata.Ofcourse,theuserneedstoalreadybesignedintotheAPIprovider,ortheywillbepromptedtoauthenticatebeforebeingaskedtograntaccesstotheirdata.

Figure2-2.Payrollapplicationlettinguserknowthey’llsoonbedirectedovertothetasklistapp’sapprovalscreen.

Page 30: Getting started with_o_auth_2_0

Figure2-3.OAuthauthorizationserveraskinguserifit’sOKtoletthepayrollapplicationaccesshisorhertasks.

Figure2-4.Payrollappthankingtheuserforaccess,andremindingthemwhatthey’llusetheaccesstoenable.

YoucanfindtheURLfortheOAuthauthorizationendpointintheAPIprovider’sdocumentation.ForGoogleTasks(andallotherGoogleAPIsusingOAuth2.0),theauthorizationendpointisat

https://accounts.google.com/o/oauth2/auth

Youwillneedtospecifyafewqueryparameterswiththislink:

client_id

Thevalueprovidedtoyouwhenyouregisteredyourapplication.

redirect_uri

Thelocationtheusershouldbereturnedtoaftertheyapproveaccessforyourapp.Forthisexample,theapplicationwillusehttps://payroll.saasyapp.com/oauth_response.php.Thevalueusedfortheredirect_uritypicallyneedstoberegisteredinadvancewiththeprovider.

scope

Thedatayourapplicationisrequestingaccessto.Thisistypicallyspecifiedasalistofspace-delimited

Page 31: Getting started with_o_auth_2_0

strings,thoughFacebookusescomma-delimitedstrings.ValidvaluesforthescopeshouldbeincludedintheAPIproviderdocumentation.ForGoogleTasks,thescopeishttps://www.googleapis.com/auth/tasks.IfanapplicationalsoneededaccesstoGoogleDocs,itwouldspecifyascopevalueofhttps://www.googleapis.com/auth/taskshttps://docs.google.com/feeds.

response_type

codefortheserver-sideWebApplicationflow,indicatingthatanauthorizationcodewillbereturnedtotheapplicationaftertheuserapprovestheauthorizationrequest.

state

Auniquevalueusedbyyourapplicationinordertopreventcross-siterequestforgery(CSRF)attacksonyourimplementation.Thevalueshouldbearandomuniquestringforthisparticularrequest,unguessableandkeptsecretintheclient(perhapsinaserver-sidesession).

Here’swhatthePHPcodemaylooklike:<?phpsession_start();

// Generate random value for use as the 'state'. Mitigates// risk of CSRF attacks when this value is verified against the// value returned from the OAuth provider with the authorization// code.$_SESSION['state'] = rand(0,999999999);

$authorizationUrlBase = 'https://accounts.google.com/o/oauth2/auth';$redirectUriPath = '/oauth2callback.php';

// For example only. A valid value for client_id needs to be obtained// for your environment from the Google APIs Console at// http://code.google.com/apis/console.$queryParams = array( 'client_id' => '240195362.apps.googleusercontent.com', 'redirect_uri' => (isset($_SERVER['HTTPS'])?'https://':'http://') . $_SERVER['HTTP_HOST'] . $redirectUriPath, 'scope' => 'https://www.googleapis.com/auth/tasks', 'response_type' => 'code', 'state' => $_SESSION['state'], 'approval_prompt' => 'force', // always request user consent 'access_type' => 'offline' // obtain a refresh token);

$goToUrl = $authorizationUrlBase . '?' . http_build_query($queryParams);

// Output a webpage directing users to the $goToUrl after// they click a "Let's Go" buttoninclude 'access_request_template.php';?>

InadditiontothestandardOAuthqueryparameters,you’llnoticewe’veincludedafewwhicharespecifictoGoogle’simplementation:

approval_prompt

Useforcetoindicatethatwewanttheuserpromptedforapprovaleachtimetheuservisitstheapplication.Youcanalsouseautotoindicatethattheuserwillonlyseetheapprovalrequestthefirsttimethisapplicationrequiresit.

access_type

Page 32: Getting started with_o_auth_2_0

Useofflinetoindicatethattheapplicationneedsaccesstouserdatawhiletheuserisnotatthekeyboard.Thisresultsinarefreshtokenbeingissuedwhentheuserexplicitlyapprovesgrantingaccesstothisapp.Ifonlineisused,norefreshtokenwillbeissued.

SomeenterpriseAPIprovidershavespecialprovisionstohandleauto-approvalofOAuth2.0grantsforanindividualuserifanITadministratoroftheuser’sorganizationhaspreviouslyapprovedaccessforanapplication.Inthisscenario,theapplicationwillredirecttheuser’sbrowsertotheauthorizationserver,buttheuserwillneverbepromptedtoapproveaccess.Instead,theuserwillbeimmediatelyredirectedbacktotheapplicationwithanauthorizationcode,asdescribedbelowinStep2:Exchangeauthorizationcodeforanaccesstoken.Salesforceprovidesthisoptionas“nouserapprovalrequired”ontheircontrolpanelpagetodefineRemoteAccessApplications.

ErrorhandlingIfallrequestparametersarevalidandtheuserapprovesthedataaccessrequest,theuserwillberedirectedbacktotheapplicationattheURLspecifiedastheredirect_uri.

However,ifoneoftherequestparametersisinvalid,anerrorconditionexists.Ifthereisanissuewiththeredirect_uri,client_id,orotherrequestinformation,theauthorizationservershouldpresentanerrormessagetotheuserandnotredirecttheuserbacktotheapplication.

Inthecasethattheuser(orauthorizationserver)deniestheaccessrequest,anerrorresponsewillbegenerated,andtheuserwillberedirectedtotheredirect_uriwithaqueryparametercallederrorindicatingthetypeoferrorasaccess_denied.Additionally,theservercanincludeanerror_descriptionmessageand/oranerror_uriindicatingtheURLofawebpagecontainingmoreinformationabouttheerror.

Whileaccess_deniedisthemostlikelyerrorresponseyourapplicationwillneedtohandle,thereareothererrortypesdefinedintheOAuth2.0specificationaswell:

invalid_request

Therequestismissingarequiredparameter,includesanunsupportedparametervalue,orisotherwisemalformed.

unauthorized_client

Theclientisnotauthorizedtorequestanauthorizationcodeusingthismethod.

unsupported_response_type

Theauthorizationserverdoesnotsupportobtaininganauthorizationcodeusingthismethod.

invalid_scope

Therequestedscopeisinvalid,unknown,ormalformed.

server_error

Theauthorizationserverencounteredanunexpectedconditionthatpreventeditfromfulfillingtherequest.

temporarily_unavailable

Theauthorizationserveriscurrentlyunabletohandletherequestbecauseofatemporaryoverloading

Page 33: Getting started with_o_auth_2_0

ormaintenanceoftheserver.

Step2:ExchangeauthorizationcodeforanaccesstokenInthecasethatnoerroroccursduringtheapprovalprocess,theauthorizationserverwillredirecttheuserbacktotheapplicationattheURLspecifiedastheredirect_uri.Inthisexample,theuserwillberedirectedbacktohttps://payroll.saasyapp.com/oauth2callback.

Whentheuserhasgrantedaccess,twoqueryparameterswillbeincludedbytheauthorizationserverintheredirectbacktothewebapplication:

code

Theauthorizationcode,indicatingthattheuserhasapprovedtherequestforaccess

state

Thevalueofthestateparameterpassedintheinitialrequesttotheauthorizationserver

ThestatevalueshouldbecomparedagainstthevaluegeneratedinStep1above.Ifthevaluesdonotmatch,it’spossibleamalicioususerisattemptingtoperformacross-siterequestforgeryattackontheapplication,sotheOAuthflowshouldnotbecontinued.

Take,forexample,https://payroll.saasyapp.com/oauth2callback?code=AB231DEF2134123kj89&state=987d43e51a262f

TheapplicationneedstoexchangethecodeforanOAuthaccesstokentomakeAPIrequests.Ifyou’reusingaclientlibraryforOAuth,thisexchangewilltypicallyhappenbehindthescenesbythelibrary.However,ifyou’renotusingalibrary,you’llneedtomakeaHTTPPOSTrequesttothetokenendpoint.Thefollowingparametersneedtobepassedintherequest:

code

Theauthorizationcodepassedtotheapplication

redirect_uri

Thelocationregisteredandusedintheinitialrequesttotheauthorizationendpoint

grant_type

Thevalueauthorization_code,indicatingthatyou’reexchanginganauthorizationcodeforanaccesstoken

ThisHTTPPOSTneedstobeauthenticatedusingtheclient_idandclient_secretobtainedduringapplicationregistration.Therearetwoprimarywaystohandletheauthenticationoftherequestdefinedinthespecification:includeaHTTPBasicAuthorizationheader(withtheclient_idastheusername,andtheclient_secretasthepassword)orincludetheclient_idandclient_secretasadditionalHTTPPOSTparameters.

AtypicalAuthorizationheaderlookslikethis:Authorization: Basic MDAwMDAwMDA0NzU1REU0MzpVRWhrTDRzTmVOOFlhbG50UHhnUjhaTWtpVU1nWWlJNg==

BecauseusingHTTPBasicaccessauthenticationwasalateradditiontotheOAuth2.0specifications,itisnotyetsupportedbymanyproviders.Instead,theHTTPPOSTparametermechanismmustbeused.The

Page 34: Getting started with_o_auth_2_0

followingadditionalPOSTparametersmustbepassedalongsidethecodeandstate:

client_id

Thevalueprovidedtoyouwhenyouregisteredyourapplication

client_secret

Theconfidentialsecretprovidedtoyouwhenyouregisteredyourapplication

Iftherequestisproperlyauthenticatedandtheotherparametersarevalid,theauthorizationserverwillissueandreturnanOAuthaccesstokeninaJSON-encodedresponse:

access_token

AtokenthatcanbeusedtoauthorizeAPIrequests

token_type

Thetypeofaccesstokenissued,often“bearer,”butthesetofpotentialvaluesisextensible

Theaccesstokenmaybetime-limited,inwhichcasesomeadditionalinformationmaybereturned:

expires_in

Theremaininglifetimeoftheaccesstoken,inseconds

refresh_token

Atokenthatcanbeusedtoacquireanewaccesstokenafterthecurrentoneexpires

TheJSON-encodedresponselookslikethis:{ "access_token" : "ya29.AHES6ZSzX", "token_type" : "Bearer", "expires_in" : 3600, "refresh_token" : "1/iQI98wWFfJNFWIzs5EDDrSiYewe3dFqt5vIV-9ibT9k"}

NOTE

BecausetheOAuthspecificationisstillindevelopment,someAPIproviderswhohaven’tcaughtupwiththelatestspecificationmayformattheirresponsesdifferently.Facebook,forinstance,returnsaform-encoded(&delimited)response.

Here’sexamplecodeforexchangingtheauthorizationcodeforanaccesstokeninPHP:<?phpsession_start();include 'http_client.inc';

$code = $_GET['code'];$state = $_GET['state'];

// Verify the 'state' value is the same random value we created// when initiating the authorization request.if ((! is_numeric($state)) || ($state != $_SESSION['state'])) { throw new Exception('Error validating state. Possible CSRF.');}

$accessTokenExchangeUrl = 'https://accounts.google.com/o/oauth2/token';$redirectUriPath = '/oauth2callback.php';

// For example only. Valid values for client_id and client_secret// need to be obtained for your environment from the Google APIs// Console at http://code.google.com/apis/console.

Page 35: Getting started with_o_auth_2_0

// Also, these values should not be hard-coded in a production application.// Instead, they should be loaded in from a configuration file or secure keystore.$accessTokenExchangeParams = array( 'client_id' => '240195362.apps.googleusercontent.com', 'client_secret' => 'hBMLD98Zi4wiqmiwmqDq', 'grant_type' => 'authorization_code', 'code' => $code, 'redirect_uri' => (isset($_SERVER['HTTPS'])?'https://':'http://') . $_SERVER['HTTP_HOST'] . $redirectUriPath);

$httpClient = new HttpClient();$responseJson = $httpClient->postData( $accessTokenExchangeUrl, $accessTokenExchangeParams);$responseArray = json_decode($responseJson, TRUE);

$accessToken = $responseArray['access_token'];$expiresIn = $responseArray['expires_in'];$refreshToken = $responseArray['refresh_token'];

$_SESSION['access_token'] = $accessToken;// Storing refresh token in the session, and using approval_prompt=force for // simplicity. Typically the fresh token would be stored in a server-side database// and associated with the user's account. This would eliminate the need for// prompting the user for approval each time.$_SESSION['refresh_token'] = $refreshToken;

header('Location: /get_data.php');?>

Nowthattheapphasanaccesstoken,theapplicationcanrespondtotheusertothankthemforgrantingauthorization,andremindthemwhatfeaturestheaccesswillenable.TheapplicationcannowaccesstheAPIsdirectlythroughthelifetimeoftheaccesstokenoruntiltheaccessisrevoked.Inthecasearefreshtokenisprovided,theapplicationcancontinuetoaccesstheAPIsofflinewithoutuserinteraction.

Theaccesstokenandtherefreshtokenshouldbekeptsecretatalltimesandtheyshouldnotbeexposedtoanyuser,includingtheresourceowner.Typicallytherefreshtokenisstoredsecurelyinaserver-sidedatabase,associatedwiththeuseraccount.Accesstokenscanalsobestoredinadatabase,buttheymayalsobecachedinaserver-sidesessiontoimproveperformance.

Whybothaccesstokensandrefreshtokens?Somedevelopersdon’tunderstandtheneedforbothshort-livedaccesstokensandlong-livedrefreshtokens.Havingbothtokentypesimprovessecurityandperformance,especiallyforlarge-scaleAPIproviderswithmanyAPIsandacentralOAuthauthorizationservice.

OAuth2.0typicallyusesbearertokens(withoutsignaturesinAPIrequests),sothecompromiseofaprotectedAPIservicecouldallowanattackertoseetheaccesstokensreceivedfromclients.AnOAuthgrantmayprovideanapplicationaccesstomultipledifferentAPIs(scopes)forauser,suchastheuser’scontactsandtheuser’scalendars.Thiscouldallowanattackeraccesstonotonlythecompromisedservice,butotherservicesaswell.Havingonlytime-limitedaccesstokensaccessibletoAPIservices(andnotlong-livedrefreshtokens)reducesthepotentialimpactofanattack.

WhenanAPIservicereceivesanaccesstokenfromaclient,itneedstoensurethatit’svalidforaccessingtherequesteddata.Ifthetokenisanopaquestring,itdeterminesthevaliditybymakinganinternalrequesttotheAPIservice’sOAuthauthorizationserviceoradatabaselookup.ThiscanintroducelatencytoAPIrequests,sosomeAPIprovidersinsteadofOAuthuseaccesstokens,whicharesignedorencryptedstrings

Page 36: Getting started with_o_auth_2_0

andareabletobeverifiedlessexpensively.

OneofthekeybenefitsofanauthorizationprotocollikeOAuthistheabilityforuserstorevokeaccesstheypreviouslygrantedtoapplications.Atlarge-scaleproviders,thisrevocationtypicallyishandledbyacentralOAuthauthorizationservicethathandlesrequestsformanyAPIs.IftheAPIservicesareindependentlyverifyingtheaccesstokensusingcryptographywithoutdatabaselookupsorcallstothecentralservice,theserviceswon’tknowwhenaccessforaclienthasbeenrevoked.Thusitisimportanttokeepthelifespanoftheaccesstokensshortsotheydonotremainvalidfortoolongaftertheclient’saccessisrevoked.

Step3:CalltheAPIThenextstepisretrievingandupdatingtheuser’stasks.ManyAPIprovidersimplementingOAuth2.0usebearertokens.ThismeansthattheapplicationcanauthorizeAPIrequestssimplybyincludingtheOAuthaccesstokenintherequests,withouttheneedforcryptographicsignatures.

ThepreferredwayofauthorizingrequestsisbysendingtheaccesstokeninaHTTPAuthorizationheader,asdiscussedinChapter1.

Here’sanexampleofusingtheAuthorizationheadermethodofmakinganauthorizedAPIcalltoretrieveauser’stasksinGoogleTasks.NotethatthiscodeisagainusingacustomHttpClientclasstoimplementtheunderlyingcallstothecurllibrary:

<?phpsession_start();require_once 'http_client.inc';

$tasksUrl = 'https://www.googleapis.com/tasks/v1/lists/@default/tasks';

// The value for $accessToken would typically be stored in a// server-side PHP session bound to the active user. The value of the// access token can be any string. Google uses values similar to:// 'ya29.AHES6ZS_2G4-VuL041L0GpFJqH0wGfGSR'.$accessToken = $_SESSION['access_token'];

// Recommended approach for an OAuth 2 authorized request is to// use a HTTP Authorization header$httpClient = new HttpClient();$headers = array( 'Authorization: Bearer ' . $accessToken);

// Alternative to using the Authorization header would be appending// the OAuth token to the URL as a query parameter// $tasksUrl .= '?access_token=' . urlencode($accessToken);

$response = $httpClient->getData($tasksUrl, $headers);$responseArray = json_decode($response, TRUE);

foreach ($responseArray["items"] as $item) { echo '<li>' . $item['title'] . "</li>\n";}?>

WhilethissamplecodespecificallydemonstratescallingtheGoogleTasksAPI,similarcodecouldbeusedtoauthorizerequestsofanyAPIsupportingrecentversionsofthedraftspecification.Simplyreplacethevaluesof$tasksUrland$accessToken.

Errorhandling

Page 37: Getting started with_o_auth_2_0

WhenmakingAPIcallsusingtheOAuth2.0accesstoken,youmayencountererrorsiftheaccesstokenisnolongervalidbecausethetokenexpiredorwasrevoked.Inthiscase,youshouldgetaHTTP4xxerror.DependingontheindividualAPI,thedetailederrordescriptionwillbecommunicateddifferently.

Inadditiontothe4xxerrorcode,thelatestversionoftheOAuthbearertokenspecificationalsorequiresthattheHTTPWWW-AuthenticateresponseheaderbeincludedwhencredentialsarenotincludedintherequestortheaccesstokenprovideddoesnotenableaccesstotherequestedAPIresource.Thisheadermayincludeadditionaldetailsontheerrorencountered.

Here’sanexampleresponsefromthespecification,indicatingthatanexpiredOAuthaccesstokenwaspassedtotheapp:

HTTP/1.1 401 UnauthorizedWWW-Authenticate: Bearer realm="example", error="invalid_token", error_description="The access token expired"

Validerrorcodesinclude:invalid_request,invalid_token,andinsufficient_scope.

BecausetheuseoftheWWW-Authenticateheaderwasalateadditiontothespec,itmaynotbeimplementedbyallofyourfavoriteAPIproviders.

WhenFacebookencountersanerrorwiththetoken,itreturnsaHTTP400statuscodeandincludesthefollowingJSONobjectinthebodyoftheresponse:

{ "error": { "type": "OAuthException", "message": "Error validating access token." }}

Here’sanexampleresponseresultingfromtheuseofanexpiredaccesstokenwithoneofGoogle’snewerAPIs:

{ "error": { "errors": [ { "domain": "global", "reason": "authError", "message": "Invalid Credentials", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Invalid Credentials" }}

Step4a:RefreshtheaccesstokenWhenanauthorizationcodeisexchangedforanaccesstoken,manyAPIproviderswillissueshort-livedaccesstokenseveniftheysupportlong-lived“offline”accesstotheirAPIs.Althoughtheseaccesstokenshavealimitedlifespan,twoadditionalparametersmaybeincludedintheresponsetoenablelong-livedaccess:expires_inandrefresh_token.

Ifincludedintheresponse,expires_inindicatestheremaininglifetimeoftheaccess_token,specified

Page 38: Getting started with_o_auth_2_0

inseconds.Whentheaccesstokenexpires,therefresh_tokenparametercanbeusedtoobtainanewaccesstoken.

Iftryingtooptimizeforlatencyinyourapplication,it’sbesttostoretheaccesstokenalongwiththetimewhentheaccesstokenexpires.WhenmakinganAPIcall,firstchecktoseeifthecurrenttimeisgreaterthantheexpirationtime.Ifso,refreshtheaccesstokenfirst,insteadofwaitingfortheAPIservertorejectyourrequestbecauseofaninvalidaccesstoken.ThiswillresultinreducedlatencybecauseoffewerHTTPrequestsbeingmadewhenthetokenexpires.

RefreshingtheaccesstokenisaccomplishedbymakingaHTTPPOSTtothetokenendpoint,specifyingthegrant_typeasrefresh_tokenandincludingtherefresh_token.Therequestmustalsobeauthenticated.

Here’sanexampleinPHP:<?phpinclude 'http_client.inc';

function getNewAccessToken($refreshToken) { $refreshTokenUrl = 'https://accounts.google.com/o/oauth2/token';

// For example only. Valid values for client_id and client_secret // need to be obtained for your environment from the Google APIs // Console at http://code.google.com/apis/console. $refreshTokenParams = array( 'client_id' => '240195362.apps.googleusercontent.com', 'client_secret' => 'hBMLD98Zi4wiqmiwmqDq', 'grant_type' => 'refresh_token', 'refresh_token' => $refreshToken );

$httpClient = new HttpClient(); $responseJson = $httpClient->postData( $refreshTokenUrl, $refreshTokenParams); $responseArray = json_decode($responseJson, TRUE); return $responseArray;}

$responseArray = getNewAccessToken('adbadsfa12345');$accessToken = $responseArray['access_token'];$refreshToken = $responseArray['refresh_token'];$expiresIn = $responseArray['expires_in'];?>

Thisexampleauthenticatestherequestbyincludingtheclient_idandclient_secretasHTTPPOSTparameters.SomeOAuthprovidersmayalsosupportauthenticatingtherequestusingtheHTTPBasicaccessauthenticationmethoddescribedinStep2.

Whenrequestinganewaccesstoken,anewrefreshtokenmaybeissuedaswell.Inthiscase,storethenewrefreshtokenanddiscardthepreviousone.

Step4b:ObtaininganewaccesstokenRegardlessofwhetherAPIcallsarebeingmadedirectfromauser’sbrowserorserver-to-server,someapplicationsonlyneedaccesstoauser’sdatawhiletheuseris“atthekeyboard.”Inthiscase,theapplicationmaybeabletorequest“online”accessthatresultsinnorefreshtokenbeingissuedandtheaccesstokenhavingalimitedlifespan.Inthiscase,obtaininganewaccesstokenisdonebysendingthe

Page 39: Getting started with_o_auth_2_0

userthroughtheauthorizationflow,startingatStep1again.SomeAPIproviderswillnotreprompttheuserforaccessiftheapplicationhaspreviouslybeengrantedaccesstothesamesetofdatabytheuserandwillinsteadredirectimmediatelybacktotheapplicationwithanauthorizationcode.

Herearesomespecificimplementations:

Googledefaultsto“online”accessanddoesnothandoutrefreshtokensunlessexplicitlyrequestedbypassingaccess_type=offlinetotheauthorizationendpointatthetimeanauthorizationcodeisrequested(seeStep1).Inthiscase,theuseriswarnedthattheyaregrantingpermissionfortheapplicationto“PerformtheseoperationswhenI’mnotusingtheapplication.”Ifanapplicationwithonly“online”accessneedsanewauthorizationcode,itisautomaticallyissuedtotheclientwithoutuserinteraction,andthenexchangedbytheapplicationinaserver-to-servercall(seeStep2).

Facebookdefaultsto“online”access:itissuesaccesstokenswithlimitedlifespananddoesnotissuerefreshtokens.Ifanapplicationneedsofflineaccess,itcanrequestoffline_accessbyspecifyingthispermissionasoneofthevaluesinthescopestring.Thiswillresultinanaccesstokenbeingissuedwithaninfiniteexpirationtime,thoughthetokenwillstillbesubjecttopotentialrevocationbytheuser.

Page 40: Getting started with_o_auth_2_0

HowCanAccessBeRevoked?Differentauthorizationservershavedifferentpoliciesastowhenaccesstokensarerevoked.Mosttypicallyenabletheusertoexplicitlyrevokeaccessthroughanaccountmanagementinterface,thoughtheseinterfacescanbedifficultforuserstofind.Additionally,someAPIproviders(suchasFacebook)revokeoutstandingaccesstokenswhenauserchangestheirpassword.

Applicationsarenotusuallyinformedwhenauserrevokesaccess,andthespecificationdoesnotdefineanywaytoimplementanotification—theappwillsimplyseeanerrorthenexttimeitattemptstouseanaccesstokenorrefreshthetokenstoredforthatuser.

Facebook,however,doeshaveadefinable“DeauthorizecallbackURL”whichperformsaHTTPPOSTtoyourapplicationwhenauserrevokesaccessinthestyleofaWebHook.MoreinformationisavailableinFacebook’sdeveloperdocumentation.

Whileuserscanrevoketheiraccessmanually,someOAuth2.0authorizationserversalsoallowtokenstoberevokedprogrammatically.Thisenablesanapplicationtocleanupafteritselfandremoveaccessitnolongerneedsif,forinstance,theuseruninstallstheapp.

ProgrammaticrevocationisdefinedinadraftextensiontotheOAuth2.0specificationandisimplementedbypopularOAuthproviderssuchasSalesforceandGoogle.Salesforceallowsforrevocationofbothrefreshtokensandaccesstokens,whileGoogleonlyenablesrevocationofrefreshtokens.Here’sanexamplerevocationrequest:

curl "https://accounts.google.com/o/oauth2/revoke?token=ya29.AHES6ZSzF"

TheextensionalsodefinesaJSONP“callback”queryparameterthatOAuthproviderscanoptionallysupport.BothSalesforceandGooglesupportthisparameter.

A200responsecodeindicatessuccessfulrevocation.

Page 41: Getting started with_o_auth_2_0

Chapter3.Client-SideWebApplicationsFlowTheImplicitGrantflowforbrowser-basedclient-sidewebapplicationsisverysimple.Inthisflow,anaccesstokenisimmediatelyreturnedtotheapplicationafterausergrantstherequestedauthorization.Anintermediateauthorizationcodeisnotrequiredasitisintheserver-sideWebApplicationflow(seeChapter2).

Figure3-1showsastep-by-stepflowdiagram,basedonadiagramfromthespecification.

Page 42: Getting started with_o_auth_2_0

Figure3-1.Client-SideWebApplicationsflow:Step-by-step

WhenShouldtheImplicitGrantFlowBeUsed?TheImplicitGrantflowshouldbeusedwhen

Page 43: Getting started with_o_auth_2_0

Onlytemporaryaccesstodataisrequired.

TheuserisregularlyloggedintotheAPIprovider.

TheOAuthclientisrunninginthebrowser(usingJavaScript,Flash,etc.).

Thebrowserisstronglytrustedandthereislimitedconcernthattheaccesstokenwillleaktountrustedusersorapplications.

Page 44: Getting started with_o_auth_2_0

LimitationsoftheImplicitGrantFlowTheImplicitGrantflowdoesnotaccommodaterefreshtokens.IftheAuthorizationserverexpiresaccesstokensregularly,yourapplicationwillneedtorunthroughtheauthorizationflowwheneveritneedsaccess.

SomeAPIproviders,suchasGoogle,willnotreprompttheuserforaccessiftheuserremainsloggedinandhasapprovedtherequiredscopespreviously.Theapplicationcandothis“refresh”processinthebackgroundasaniframewithoutanyimpactontheuserexperience.

Page 45: Getting started with_o_auth_2_0

SecurityPropertiesIntheImplicitGrantflow,theapplicationdoesnotstorelong-livedrefreshtokensonaserver,limitingtheexposureiftheserveriscompromised.ItalsorequiresthattheuserbeauthenticatedtotheAPIprovider’sauthorizationserverinorderto“refresh”accesstokensontheclient,ensuringthataleakedaccesstoken’svalueistime-limited,dependingontheOAuthimplementation.

Becausetheaccesstokenissenttotheuser’swebbrowser,thisflowofferslessaccountabilitythantheAuthorizationCodeflow.APIcallsthatappeartohaveoriginatedfromathird-partyappmayhaveinfactbeenmadedirectlybytheresourceownerthemselves.

Page 46: Getting started with_o_auth_2_0

UserExperienceAJavaScript-basedContactspickerforselectinguserstoinvitetoaPhotoViewerapplicationisagreatexampleusecasefortheImplicitGrantflow.Itisavaluableactivityforboththeuserandtheapplicationdeveloper,itdoesn’thappenregularly,andtheuserisalwaysresponsibleforchoosingwhichuserstoinvitefromhisorhercontacts.

TheuserexperienceisidenticaltotheServer-SideWebApplicationflowdescribedinChapter2:

1. PhotoViewerapplicationletstheuserknowthatitneedsaccesstoherContacts.

2. TheOAuthauthorizationserverusedbytheContactapp’sAPIpromptstheusertograntpermissionforthePhotoViewerapplicationtoreadhercontacts.

3. Aftertheuserhasapproved,sheisredirectedbacktothePhotoViewerapplication,whichnowhasaccesstohercontacts.

Page 47: Getting started with_o_auth_2_0

Step-by-StepLikeinthecaseoftheflowforServer-sideWebApplicationsdescribedinChapter2,you’llfirstneedtoregisteryourapplicationwiththeAPIprovider(seeDeveloperandApplicationRegistration).

Afterregistrationiscomplete,it’stimetowritesomecode!We’llusesimpleHTMLandJavaScriptforthisexample.

Step1:Lettheuserknowwhatyou’redoingandrequestauthorizationThisstepisverysimilartotheAuthorizationCodeflow.Sincerequestingdataaccessrequiresredirectingyouruserstotheauthorizationserver,it’sabestpracticetoletthemknowinadvancewhatwillhappen.Youcandothisbydisplayingamessage,alongwithalinkthatdirectstheusertotheOAuthauthorizationendpoint.

YoucanfindtheURLfortheOAuthauthorizationendpointintheAPIprovider’sdocumentation.ForGoogleTasks(andallotherGoogleAPIsusingOAuth2.0),theauthorizationendpointisat

https://accounts.google.com/o/oauth2/auth

Youwillneedtospecifyafewqueryparameterswiththislink:

client_id

Thevalueprovidedtoyouwhenyouregisteredyourapplication.

redirect_uri

Thelocationtheusershouldbereturnedtoaftertheyapproveaccessforyourapp.Forthisexample,theapplicationwillusehttps://photoviewer.saasyapp.com/oauth_response.html.

scope

Thedatayourapplicationisrequestingaccessto.Thisisspecifiedasalistofspace-delimitedstrings.ValidvaluesforthescopeshouldbeincludedintheAPIproviderdocumentation.ForGoogleContacts,thescopeishttps://www.google.com/m8/feeds/.

response_type

Thetokenfortheclient-sideWebApplicationflow,indicatingthatanaccesstokenwillbereturnedtotheapplicationaftertheuserapprovestheauthorizationrequest.

Thecompletecodeforhandlingthisflow(inindex.html)islong,solet’sexploreitinsnippets.

ThisinitialsnippetopensapopupwindowtotheauthorizationURL.Theclient_id,scope,andresponse_typearesettotheappropriatevalues.Apseudo-randomstatevalueisgeneratedinordertomitigatetheriskofCSRFattacks.We’vealsosettheredirect_uritoapagethatcontainsJavaScriptforparsingtheaccesstokenfromtheURLandpassingitbacktotheparentwindow:

<script type="text/javascript"> var clientId = '1032068783357.apps.googleusercontent.com'; var authorizationUrlBase = 'https://accounts.google.com/o/oauth2/auth'; var redirectUri = 'http://photoviewer.saasyapp.com/pv/oauth2callback.html'; var scope = 'https://www.google.com/m8/feeds/';

Page 48: Getting started with_o_auth_2_0

var state;

function startOauth() { // generate a pseudo-random number for state var rand = Math.random(); var dateTime = new Date().getTime(); state = rand * dateTime; var url = authorizationUrlBase; url += '?response_type=token' + '&redirect_uri=' + encodeURIComponent(redirectUri) + '&client_id=' + encodeURIComponent(clientId) + '&scope=' + encodeURIComponent(scope) + '&state=' + encodeURIComponent(state); var w = window.open(url, '_blank', 'width=500,height=400'); }</script>

ErrorhandlingSeethedescriptionforerrorhandlinginStep1oftheServer-sideWebApplicationsflow(Chapter2).Thesameerrorhandlingprocessappliestothisflow.

Step2:ParsingtheaccesstokenfromtheURLAftertheuserapprovesaccess,thepopupwindowisredirectedbacktothespecifiedredirect_uriandanaccess_tokenisincludedinthe#hashfragment.Here’sanexampleURLforthisapplication:

http://photoviewer.saasyapp.com/pv/oauth2callback.html#access_token=ya29.AHES6ZSzX&token_type=Bearer&expires_in=3600

JavaScriptdoesn’ttraditionallytreatelementsofthehashfragmentasname/valuepairs,soweneedtoparseoutthevalueoftheaccess_tokenandotherelementsoftheOAuthresponse:

var oauthParams = {};

// parse the query string// from http://oauthssodemo.appspot.com/step/2var params = {}, queryString = location.hash.substring(1), regex = /([^&=]+)=([^&]*)/g, m;while (m = regex.exec(queryString)) { oauthParams[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);}

...

Next,weneedtopasstheaccesstokentotheparentwindow:window.opener.setOauthParams(oauthParams);

Thispassestheaccesstokenbacktothemainbrowserwindow.ToprotectagainstCSRFattacks,thesetOAuthParamsmethodshouldcheckthatoauthParams['state']matchestheglobalstatevariablesetinstartOAuthabove.

Thismechanismofcommunicatingwiththeparentwindowworksinmodernbrowsers.However,thesame-originpolicyisenforced,sothepopupwindowneedstomatchthehost/port/protocolofthemainwindow.

GooglehasimplementedamoreelegantwayforOAuth2.0popupwindowstocommunicateusingtheHTML5window.postMessagefeature.Thisisnotwidelydeployedyet,butyoucanseeasampleimplementationonGoogleProjectHosting.

Step3:CalltheAPI

Page 49: Getting started with_o_auth_2_0

WeusejQueryforcallingtheAPItomakeitabiteasier.Instead,youcouldcreatea<script>elementpointingtotheJSONPURLfortheContactsAPIanddynamicallyappendittothe<head>elementofyourwebpage.

ThecallApi()functionbelowwillretrievetheuser’scontactsasJSONandcallthesetResponsefunctionwiththedata:

function callApi() { var contactsUrl = 'https://www.google.com/m8/feeds/contacts/default/full?v=3.0&alt=json-in-script'; document.getElementById('access_request').style.display = 'none'; var oauthParams = this.getOAuthParams(); contactsUrl += "&access_token=" + encodeURIComponent(oauthParams['access_token']); $.ajax({ 'url': contactsUrl, 'dataType': 'jsonp', 'success': function(data) { setResponse(data); } });}

Noticethatweappendedtheaccess_tokentotheURLinsteadofusingthepreferredAuthorizationheadermechanism.ThisisbecausejQuerydoesnotallowmanuallysettingtheAuthorizationheaderusedontheserequests.

Step4:RefreshingtheaccesstokenUnlikewiththeAuthorizationCodeflowforserver-sidewebapplications,thereisnospecialprotocolforrefreshingtokenswhenusingtheImplicitGrantflow.Yourapplicationwillsimplyneedtorequestanewaccesstokenusingthesameprocessasyouusedtofetchtheinitialtoken(Steps1to3above).

Someproviders,likeGoogle,willnotpresentanauthorizationrequesttotheuseriftheyhavepreviouslyapprovedaccessforyourapplication.However,theuserwillneedtobeloggedintotheirGoogleaccountforanewtokentobeissuedwithouttheauthorizationserverpromptingtheuserfortheirGoogleaccountpassword.

Althoughnotstandardizedyet,supportforan“immediate”modealsoexistsinsomeOAuth2.0providers.Thisallowsthisrefreshprocesstooccurinahiddeniframe,enablinganewaccesstokentobetransparentlysentbacktotheapplicationwithouttheriskofpromptingtheuser.Iftheuserwouldotherwisebepromptedtoauthenticateorgrantaccess,immediatemodewillinsteadcausethewindowtoberedirectedbacktotheappwithanerrormessageindicatingthefailure.Thisallowstheapptogracefullyprompttheuserasneededforrenewedauthorization.

FortheGoogleandSalesforceOAuthauthorizationendpoints,youcanprovideanadditionalqueryparametervalueimmediate=truetoenableimmediatemode.

Page 50: Getting started with_o_auth_2_0

HowCanAccessBeRevoked?SeethedescriptionfortokenrevocationintheServer-sideWebApplicationsflow(Chapter2)section.Thesametokenrevocationprocessappliestothisflow.

Page 51: Getting started with_o_auth_2_0

Chapter4.ResourceOwnerPasswordFlowTheResourceOwnerPasswordCredentialsflowallowsexchangingtheusernameandpasswordofauserforanaccesstokenand,optionally,arefreshtoken.ThisflowhassignificantlydifferentsecuritypropertiesthantheotherOAuthflows.Theprimarydifferenceisthattheuser’spasswordisaccessibletotheapplication.Thisrequiresstrongtrustoftheapplicationbytheuser.

Figure4-1showsastep-by-stepflowdiagram,basedonadiagramfromthespecification.

Figure4-1.ResourceOwnerPasswordflow:Step-by-step

WhenShouldtheResourceOwnerPasswordFlowBeUsed?Becausetheresourceowner’spasswordisexposedtotheapplication,thisflowshouldbeusedsparingly.Itisrecommendedonlyforfirst-party“official”applicationsreleasedbytheAPIprovider,andnotopeneduptowiderthird-partydevelopercommunities.

Ifauserisaskedtotypetheirpasswordinto“official”applications,theymaybecomeaccustomedtodoing

Page 52: Getting started with_o_auth_2_0

soandbecomevulnerabletophishingattemptsbyotherapps.Inordertomitigatethisconcern,developersandITadministratorsshouldclearlyeducatetheirusershowtheyshoulddeterminewhichappsare“official”andwhicharenot.

Page 53: Getting started with_o_auth_2_0

SecurityPropertiesAlthoughtheapplicationhasaccesstotheresourceowner’spassword,therearestillsomesecuritybenefitstousingthisflowversusauthenticatingAPIcallswithausernameandpassword(viaHTTPBasicaccessauthenticationorsimilar).WithBasicauthentication,anapplicationneedstohavecontinuousaccesstotheuser’spasswordinordertomakeAPIcalls.Italsorequirestheuserchangetheirpasswordandreenterthenewpasswordinallapplicationswhichrequireit,shouldtheusernolongerwantanapplicationtohaveaccesstotheirdata.

However,iftheOAuthResourceOwnerPasswordflowisused,theapplicationonlyneedsaccesstotheuser’scredentialsonce:onfirstusewhenthecredentialsareexchangedforanaccesstoken.Thismeansthere’snorequirementfortheapptostorethesecredentialswithintheapplicationoronthedevice,andrevokingaccessiseasyaswell.

Page 54: Getting started with_o_auth_2_0

UserExperienceTheuserexperienceforthisflowisidenticaltotypicalpassword-basedaccessrequests.Theapplicationaskstheuserfortheirusernameandpasswordandtheuserprovidestheinformation.Theapplicationthenmakeseitheraserver-sideorclient-siderequesttotheAPIprovider’sauthorizationserver,withoutanyuser-facinginterfacechanges.

IftheAPIproviderdoesnotissuearefresh_tokenandtheissuedaccess_tokenisshort-lived,theapplicationwilllikelystoretheusernameandpasswordforfutureauthenticationattempts.Unfortunately,thisdefeatssomeofthebenefitofthisflow.

Page 55: Getting started with_o_auth_2_0

Step-by-StepTodemonstratethisflow,we’lluseanexamplebuiltontopofSalesforce’sREST-basedAPIs.OurexamplewillretrieveandoutputallcontactsaccessibletotheresourceownerintheSalesforceCRMsystem.

We’llassumetheexampleapplicationisanativemobileapplicationwrittenbyAcmeCorporationanddistributedtoitsemployeesthroughacorporateapplicationdirectory.Thismethodofdistributionindicatestotheemployeesthatitisa“trusted”applicationandit’sOKtoentertheircredentialsintheapp.

Step1:AsktheuserfortheircredentialsThefirststepisaskingtheusertoprovidetheircredentialstotheapplication.Inadditiontoausernameandpassword,Salesforcerequiresthatauserentertheirsecuritytokenwhenloggingintoanappfromanuntrustednetwork,suchasthenetworksusedbypopularmobilephoneserviceproviders.Anapplicationwouldtypicallydisplaythisasathirdfieldforuserinput,inadditiontotheusernameandpassword.

Step2:ExchangethecredentialsforanaccesstokenTheprocessofexchangingcredentialsforanaccesstokenisverysimilartoexchanginganauthorizationcodeforanaccesstokenintheAuthorizationCodeflow.WesimplyneedtomakeaHTTP POSTtotheauthorizationserver,providingthecredentialsandclientinformation.

YoucanfindtheauthorizationserverURLintheAPIprovider’sdocumentation.ForSalesforce,theURLis

https://login.salesforce.com/services/oauth2/token

HerearetherequiredPOSTparameters:

grant_type

Specifiedas“password”forthisflow.

scope

Thedatayourapplicationisrequestingaccessto.ItisnotrequiredforSalesforceandisoptionalforotherAPIs.TheWinter’12versionofSalesforceintroducesoptionalvaluesforthisparameter.

client_id

Thevalueprovidedtoyouwhenyouregisteredyourapplication.Althoughoptionalinthespec,thisvalueisrequiredbySalesforce.RegistrationoftheappisachievedusingtheAppSetup→Develop→RemoteAccessmenu.

client_secret

Thevalueprovidedtoyouwhenyouregisteredyourapplication.Whilethenameofthisparameterimpliesthatthevalueissecret,itissometimesrequiredbyAPIprovidersfornonconfidentialclientssuchasnativemobileapplications.Inthesecases,thevalueisnotactuallyasecret,asitcouldbediscoveredbyusersoftheapplication.

username

Page 56: Getting started with_o_auth_2_0

Theusernameprovidedbytheresourceowner,encodedasUTF-8.

password

Thepasswordprovidedbytheresourceowner,encodedasUTF-8.ForSalesforce,youneedtoconcatenatethesecuritytokenenteredbytheuserattheendoftheenteredpasswordandpassthecombinedvalueasthevalueofthisparameter.

Here’sanexamplerequestviathecurlcommand-lineHTTPclient:curl -d "grant_type=password" \-d "client_id=3MVG9QDx8IKCsXTFM0o9aE3KfEwsZLvRt" \-d "client_secret=4826278391389087694" \-d "username=ryan%40ryguy.com" \-d "password=_userspassword__userssecuritytoken_" \https://login.salesforce.com/services/oauth2/token

Iftheuser-providedcredentialsaresuccessfullyauthenticated,theSalesforceOAuthauthorizationserverwillreturnanapplication/jsonresponsecontaininganaccess_token:

{ "id":"https://login.salesforce.com/id/00DU0000000Io8rMAC/005U0000000hMDCIA2", "issued_at":"1316990706988", "instance_url":"https://na12.salesforce.com", "signature":"Q2KTt8Ez5dwJ4Adu6QttAhCxbEP3HyfaTUXoNI=", "access_token":"00DU0000000Io8r!AQcKbNiJPt0OCSAvxU2SBjVGP6hW0mfmKH07QiPEGIX"}

Whatdoeachoftheseresponseparametersmean?

access_token

TheaccesstokenusedtoaccesstheAPIonbehalfoftheuserwhoprovidedtheircredentials.Thisistheonlyrequireditemintheresponse.

id(Salesforce-specificvalue)

Theuniqueidentityoftheuser.ThisURLcanalsobeaccessedasanyotherOAuth-protectedresourcetoobtainmoreinformationabouttheuser.TheusermetadataisreturnedasJSONorXML,dependingonthevalueoftheHTTPAcceptheadersentintherequest.

instance_url

TheURLprefixtheclientapplicationshouldusetoaccesstheAPI.ThisresponseparameterisspecifictoSalesforce’simplementation.

signature

AsignatureusedtovalidatethattheidentityURLhasn’tbeenmodifiedsincebeingsentfromtheserver.AlthoughSalesforceissuessignaturesthatcanbeverified,itisn’tstrictlynecessary;instead,theapplicationcanusethebuilt-inprotectionsofHTTPStoensurecommunicationwithSalesforce’sservers.ThisresponseparameterisspecifictoSalesforce’simplementation.

issued_at(Salesforce-specificvalue)

Thetimethesignaturewasgenerated,usedforvalidatingit.

Step3:CalltheAPISincetheOAuthaccesstokenissuedbytheauthorizationflowisasimplebearertokenliketheaccess

Page 57: Getting started with_o_auth_2_0

tokensprovidedintheotherflows(asdescribedinStep3:CalltheAPI),itcanbeusedsimilarly.YousimplyneedtoprovidetheaccesstokenviaaHTTPAuthorizationheaderorqueryparametervalue,dependingonwhichtheAPIprovidersupports.

Here’sanexamplecurlrequest:curl -d "q=SELECT+name+FROM+Account"\-H 'Authorization: Bearer 00DU0000000Io8r!AQcAQKJ.Cg1dCBCVHmx2.Iu3lroPQBV2P65_jXk'"https://na12.salesforce.com/services/data/v20query"

Step4:RefreshtheaccesstokenAlthoughSalesforcedoesnotsupportrefreshingtheaccesstokenwhenusingthisflow,thespecdoesaccommodateitusingthemethoddescribedinStep4a:Refreshtheaccesstoken.

Itisimportantthatclientshaveawayofrefreshingtheaccesstokenifitisissuedwithonlyashort-termlifespan.Thispreventsdevelopersfromneedingtostoretheprovidedusercredentialswithintheirapplications—oneofthemajorbenefitsofthisflowversustraditionalHTTPBasicaccessauthenticationmechanisms.

Page 58: Getting started with_o_auth_2_0

Chapter5.ClientCredentialsFlowMostoftheOAuthflowsareforhandlingdelegatedauthorization,whenaresourceownergrantsaccesstoanapplicationtoaccessherdata.However,therearecaseswhentheclientitselfownsthedataanddoesnotneeddelegatedaccessfromaresourceowner,ordelegatedaccesshasalreadybeengrantedtotheapplicationoutsideofatypicalOAuthflow.

Thisflow(showninFigure5-1)workswellforsimilarusecasesasthe“2-legged”flowinOAuth1.0.

Figure5-1.ClientCredentialsflow:Step-by-step

WhenShouldtheClientCredentialsFlowBeUsed?ImagineastorageAPI,suchasGoogleStorageorAmazonS3.You’rebuildinganapplicationthathasresources(datafiles,images,etc.)storedexternallytoyourappusingoneoftheseAPIs.Theapplicationneedstoreadandupdatetheseresources,butactingonbehalfoftheappitselfratherthanonbehalfofanyindividualuser.ThisisaperfectusecasefortheClientCredentialsflow.TheapplicationcanasktheOAuthauthorizationserverforanaccesstokendirectly,withouttheinvolvementofanyenduser.

ThereisanotherrepresentativecasefortheClientCredentialsflow—whenaresourceownerhasgrantedanapplicationaccesstotheirresourcesoutofband,withoutusingatypicalOAuthflow.GoogleprovidesaconcreteusecaseintheGoogleAppsMarketplace.WhenanapplicationislistedontheMarketplace,vendorsgetcredentialsthatrepresenttheirapplicationandalsoregisterthescopesofdatatheyneedaccessto.Whentheapplicationislaterinstalledbyanorganization’sITadministrator,Googleaskstheadministratorwhetherit’sOKtogranttheapplicationaccesstohisorganization’sdata.Whenaccessisapproved,Googlestoresthatorganization“AcmeCorp”hasgrantedaccessto“GoogleCalendarandGoogleContacts”forapplication“TaskManagerPro.”Googledoesnotissueanytokenstotheapplication.Whentheapplicationtriestoaccessdatainthefuture,Googlesimplylooksupwhethertheapplicationisallowedaccesstodatafortheparticularorganization.

Page 59: Getting started with_o_auth_2_0

WhatAPIsSupporttheClientCredentialsFlow?Whiletheprecedingparagraphsdescribesomepotentialusecasesforthisflow,theseproviders(GoogleandAmazon)havenotyetimplementedtheClientCredentialsflowinOAuth2.0.However,Facebookhasimplementedthisflowforitsapplications,tobeabletoperformAppLogin.AppLoginisrequiredforcertainFacebookAPIcalls,includingtheabilitytogetappstatisticsanduserdemographicsfromtheAppInsightsservice.

Page 60: Getting started with_o_auth_2_0

HowDoestheClientAuthenticate?Thisflowisreliantupontheclientbeingabletoproperlyauthenticatewiththeauthorizationserverandtheclient’sauthenticationcredentialsremainingconfidential.Inordertoauthenticate,theclientcanpasstheclient_idandclient_secrettotheauthorizationserverasPOSTparametersintheaccesstokenrequestorcanuseaHTTPBasicAuthenticationheader.Theauthorizationservercanalsoauthenticatetheclientusingothermechanisms,suchasapublic/privatekeypair,SSL/TLSclientauthentication,andthelike.

Page 61: Getting started with_o_auth_2_0

SecurityPropertiesDependingonthepreciseusecasetheClientCredentialsflowisusedfor,asinglesetofcredentialsforaclientcouldprovideaccesstoalargeamountofdata.Themoredataasinglesetofcredentialshasaccessto,thegreatertheriskifthecredentialsbecomecompromised.Itisextremelycriticalthatthecredentialsusedtoauthenticatetheclientbekepthighlyconfidential.Ideally,thesecredentialswouldalsoberegularlyrotated.

Page 62: Getting started with_o_auth_2_0

Step-by-StepTodemonstratethisflow,we’lluseFacebook’simplementationofAppLoginwiththeAppInsightsservice.

Step1:Exchangetheapplication’scredentialsforanaccesstokenTheapplicationneedstorequestanaccesstokenfromtheauthorizationserver,authenticatingtherequestwithitsclientcredentials.

Youcanfindtheauthorizationserver’stokenURLintheAPIprovider’sdocumentation.ForFacebook,theURLis

https://graph.facebook.com/oauth/access_token

HerearetherequiredPOSTparameters:

grant_type

Specifiedas“client_credentials”forthisflow.

client_id

Thevalueprovidedtoyouwhenyouregisteredyourapplication.

client_secret

Thevalueprovidedtoyouwhenyouregisteredyourapplication.

Here’sanexamplerequestviathecurlcommand-lineHTTPclient:curl -d "grant_type=client_credentials\&client_id=2016271111111117128396\&client_secret=904b98aaaaaaac1c92381d2" \https://graph.facebook.com/oauth/access_token

Iftheclientcredentialsaresuccessfullyauthenticated,anaccesstokenisreturnedtotheclient.AsFacebookhasimplementedanearlierversionoftheOAuth2.0specificationasofthetimeofthiswriting,itreturnstheaccess_tokeninthebodyoftheresponseusingformurl-encoding:

access_token=2016271111111117128396|8VG0riNauEzttXkUXBtUbw

Thelatestdraftofthespec(v22)statesthattheauthorizationservershouldinsteadreturnanapplication/jsonresponsecontainingtheaccess_token:

{ "access_token":"2016271111111117128396|8VG0riNauEzttXkUXBtUbw"}

Theaccess tokenisthenusedtoaccesstheAPIonbehalfoftheapplicationitself.

Step2:CalltheAPISincetheOAuthaccesstokenissuedbytheClientCredentialsflowisabearertokenliketheaccesstokensprovidedintheotherflows,itcanbeusedsimilarly.YousimplyneedtoprovidetheaccesstokenviaaHTTPAuthorizationheaderorqueryparametervalue,dependingonwhichtheAPIprovidersupports.

Page 63: Getting started with_o_auth_2_0

Here’sanexamplecurlrequest,usingaqueryparametertopasstheaccesstoken:curl "https://graph.facebook.com/202627763128396/insights?\access_token=2016271111111117128396|8VG0riNauEzttXkUXBtUbw"

FacebooksupportspassingtheaccesstokenasaHTTPAuthorizationheaderaswell,butusingtheolderAuthorization: OAuth tokenvalueinsteadofAuthorization: Bearer tokenvalue.

Page 64: Getting started with_o_auth_2_0

WhentheAccessTokenExpiresTheClientCredentialsflowtypicallyprovidesalong-livedaccesstoken.Theauthorizationservermayindicateanexpires_intime;however,theprotocoldoesnotsupportissuingarefreshtokeninresponsetotheClientCredentialsflow.Instead,theapplicationsimplyasksforanewaccesstokenifthecurrentoneexpires.

Page 65: Getting started with_o_auth_2_0

Chapter6.GettingAccesstoUserDatafromMobileAppsTherearetwomainclassesofmobileapplications:mobile-optimizedwebappsusingHTML5andotherwebtechnologiesandnativemobileapplications.Whilemobile-optimizedwebappscanusethetraditionalOAuthclient-sideorWebApplicationflowswithsomespecialconsiderationforuserexperience,nativemobileapplicationsrequireadditionalconsiderations.

WhyYouShouldUseOAuthforNativeMobileAppsWhenbuildinganativemobileapp,therearetwoprimaryreasonsyoushouldconsiderusingOAuth:

AccesstoyourownAPIs

Manymobileapplicationshavebackendserversthattheyusetokeeptrackofuserdata.Perhapsyourappisagameandstoreshighscoresandlevelcompletiondatainaserver-sidedatabasetoenablesocialfunctionalityorsupportingplayingthegameonmultipleplatforms.Inthiscase,yourappneedstocommunicatewiththebackendusinganAPI,typicallyaREST-basedHTTPAPI.OAuthisagreatwaytohandleAPIauthorizationforthesetypesofapplications,anditenablesyoutobuildandmaintainonlyoneinterfaceforuserstologintoyourapplication,whetherthey’reontheWeborusingyournativemobilecompanionapp.

AccesstoAPIsfromotherproviders

SomeAPIprovidersmayrequireyoutouseOAuthforAPIauthorization.However,forthosethatdon’t,therearestillseveralgreatreasonsyouwanttouseOAuthfornativemobileapps:youhaveanobligationtohelpusersstaysafeandalsoadesiretomakeyourapplicationeasytousebyallusers.Askingusersfortheirpasswordforthird-partyservicesreinforcesthispatternandmakesusersmorevulnerabletophishingattempts.Thisfurtherrequiresthatyourapphaveaccesstotheuser’sentireaccount(asopposedtoalimitedscopeofdata)andrequiresyourapptostoretheuser’scredentialsonthedeviceforlong-livedaccess,potentiallyleavingthemopentocompromise.AnotherprimaryreasonthatyouwanttoconsiderusingOAuthisthatsomeusersatspecificAPIprovidersmaysimplynotbeabletodelegateaccesstoyourappwithatypicalusernameandpasswordbecausetheyuseasecond-factorauthenticationscheme(suchasaone-timepasswordkeytoken)ortheiraccountisfederatedtoanotheridentityprovider(viaOpenID,SAML,etc.).

Page 66: Getting started with_o_auth_2_0

WhatFlowShouldBeUsedforNativeMobileApps?TheavailableflowsfornativemobileappswilllikelyberestrictedbasedonwhatflowsaresupportedbyyourAPIprovider.However,thereareafewquestionsyoucanconsiderwhendecidingwhatflowtouse.

DoYouHaveaMobileBackendWebServerforYourApplication?Yes:Ifyouhaveamobilebackendwebserverforyournativeapp,youcanuseoneofthetypicalOAuthflowsforwebapplications:theclient-side(implicit)flowortheflowforserver-sidewebapps.Thesameconsiderationsapply:Doyouneedlong-lived“offline”accessfromyourmobileapp’sbackendserver?Usetheserver-sidewebappflow.Ordoyouneedshort-livedone-timeaccessdirectlyfromthenativeapp?Usetheclient-sideimplicitflow.

Whenusingtheserver-sidewebappflowandpassinganauthorizationcodetoyourserver,theuseroftheappwillstillneedtobeauthenticatedtotheappbackend,similartohowauserisauthenticatedtowebapplicationserversusingsessioncookies.

No:Ifyourapplicationdoesnothaveamobilebackendwebserverpoweringit,youneedtousesometypeofnativeapplicationflow.Thiscanbeverysimilartotheserver-sidewebappflowortheclient-sideimplicitflow,buttherearetworestrictions:youdon’thaveawebservertousefortheredirect_uri,andyoushouldmaintaintheconfidentialityofanyclient_secretvalues,whicharesometimesrequiredfortheserver-sideflow.

Dependingonthemobileplatformyou’rebuildingonandtheAPIprovideryou’reusing,youcanuseacustomURIschemesuchasmy-mobile-app://oauth/callbackfortheredirect_uriinordertoreturntheauthorizationcodeoraccess_tokentoyourapplication.However,onsomeplatforms,thesecustomURIschemescanberegisteredbymultipleapplications(andtheiruniquenessisnotguaranteed),sothereisariskthatthetokenscouldbeinterceptedbythewrongapponthedeviceandusedmaliciously.It’salsopossiblethatyourAPIproviderrequirespreregistrationoftheseredirect_urivaluesanddoesnotacceptvaluesusingcustomURIschemes.

TherearealsosomeAPIproviderssupportinganativeclientflow.Withthenativeclientflow,aspecialredirect_urivalueisusedtosendtheauthorizationcodeoraccesstokentoawebpagehostedbytheOAuthauthorizationserver.Theusercanthencopy/pastethisvalueintotheapplicationortheapplicationcanprogrammaticallygrabthevaluefromthebodyorwindowtitleandclosethewebbrowserwindow.

Thecurrentlyproposedspecialredirect_urivalueforthenativeclientflowisurn:ietf:wg:oauth:2.0:oob.Figure6-1showsanexampleresultwebpageaftertheuserapprovesaccesstotheirdata.Inmostcases,theuserwouldneverseethispage,however,becausetheapplicationwouldgrabtheaccesstokenandclosethewindowbeforeitisvisible.

Page 67: Getting started with_o_auth_2_0

Figure6-1.Google’sresponsepagewhenusingtheOOBredirect_urifornativeclients

Page 68: Getting started with_o_auth_2_0

The(Ugly)WebBrowserManymobileapplicationdevelopershaveobjectedtousingOAuthfortheirnativeapplicationsbecauseitrequireseitherembeddingaWebVieworopeningupthesystemwebbrowseronthedevice.Theydon’tvieweitheroftheseasgoodoptions,asawebbrowseroftenfeelsdifferentthananativeUI.

Thisisareasonableconcern,thoughwealwaysneedtobalancesecurityandusability.WeshouldexpectthattheuserexperiencefortheseOAuthbrowser-basedflowswillcontinuetoimprovealongwithincreasedpervasivenessofHTML5technologyandmobilewebUXdesigntechniques.

EmbeddedWebViewTheembeddedWebViewhasbecomeapopularwaytohandleOAuthauthorizationgrantsfornativemobileapplications.Insteadofopeningupthesystemwebbrowser(viaanIntentonAndroidorUIApplicationoniOS),theembeddedWebViewsimplyincludesabrowserwithinthemainapplicationwindow.Thismechanismleadstoasmallercontextswitchfortheuser,whileatthesametimeprovidingthenativeappgreatercontroloverthewebbrowser.

Primaryadvantage

WebViewsareeasilycontrolledbythenativeapplication.ThisenablestheapplicationtoeasilyaccesstheOAuthaccesstokenorauthorizationcodebyexaminingthecookiestoreorthetitleoftheapplicationwindow,withoutworryingabouttheissuesofregisteringacustomURLscheme.

Somedisadvantages

WebViewsdon’tdisplaythetrustindicatorspresentinthesystemwebbrowser(suchastheSSL/TLSlockindicatingcertificatechainvalidationandtheURLofthesite).UsersmaybepromptedtoentertheircredentialstologintotheOAuthauthorizationprovider.Thisresultsinusersbeingmorevulnerabletophishingattacksifevilappsaredeployedontouserdevices.

Withseparatecookieandhistorystores,theuserisnotloggedintoanyaccounts.ThismeansthattheymustlogintotheOAuthAuthorizationServerbeforegrantingaccesstoanapp,andenteringcredentialsonmobiledevicescansometimesbeapainfulexperience.

SystemWebBrowserOpeningupthesystemwebbrowserseemslikethenaturalwaytosendauserthroughanOAuthgrantflow,butaswiththeembeddedWebView,therearebothadvantagesanddisadvantagestothistechnique.

Someadvantages

Thesystemwebbrowserusesthesystemcookiestore.IfyourapplicationintegrateswithapopularAPIprovider,it’slikelythattheuserisalreadyloggedintotheprovider—resultinginasimplesingle-clickgrantprocess.Usersdon’tneedtoretypetheirpassword.

Usershavegreatersecurityassuranceswiththesystemwebbrowser,asthey’reaccustomedtothetypicalsecurityindicators(suchastheSSL/TLSlockandtheURLofthesite).Thismakesuserslessvulnerabletophishing.

Page 69: Getting started with_o_auth_2_0

Somedisadvantages

Usingthesystemwebbrowserrequiresthattheuserbereturnedtothenativeappaftergrantingaccess.Asmentionedabove,thistypicallydoneusingacustomURIschemesuchasmy-mobile-app://oauth/callbackfortheredirect_uri.Becausethereisnocentralregistryofthesecustomschemes,othermaliciousapplicationsinstalledonthedevicemaybeabletointercepttheOAuthaccesstokensorauthorizationcodes.

Thehistorystoreofthesystemwebbrowsercannotbecontrolledbythenativeapp,leadingtopotentialcompromiseofOAuthaccesstokensiftheimplicitflowisused.Whilethisisalsoaproblemondesktopwebbrowsers,it’smoreofaconcernwithmobiledevices,whicharemoreportableandthusmoresusceptibletolossandtheft.ThisriskisusuallymitigatedbytheshortvalidityofOAuthaccesstokens.

Page 70: Getting started with_o_auth_2_0

EnhancedMobileAppAuthorizationforSpecificProvidersSomeOAuthprovidershavebuiltspecialmobilelibrariesorapplicationstomakedoingOAutheasierondevicesandtoimprovetheuserexperience.

ForGoogleOnitsAndroidoperatingsystem,GoogleprovidesaservicecalledtheAccountManager.OriginallythisservicewasdesignedtoallowapplicationstorequestauthtokensforGoogleAPIsusingtheproprietaryClientLoginmechanism.However,thisservicehasbeenupdatedtosupportgettingOAuth2.0accesstokensforGoogleAPIs.

InordertogetanOAuth2.0accesstoken,yousimplyneedtocallAccountManager.getAuthToken()torequestatokenusinganauthTokenTypeofoauth2:<scope>.Forexample,torequestaccesstotheGoogleTasksAPI,specifyanauthTokenTypeofoauth2:https://www.googleapis.com/auth/tasks.Unfortunately,thisliteralstringwillbepresentedtouserswhenthey’reaskedtograntaccess,sousingthistechniqueisnotrecommended.However,forsomeAPIs,suchasGoogleTasks,therearealiasessuchasManageYourTasksthatcanbeusedinplaceoftheoauth2:<scope>valuetoproduceamuchfriendlierrequest.

AfteryoucallgetAuthToken(),theaccountmanagerwillasktheusertoapproveordenytherequestusinganativeapplicationprompt.Iftheuserapprovestherequest,theapplicationwillbeissuedanaccess_tokenvalue,whichcanbeusedinAPIrequests.

TheGoogleTasksAPIteamhascreatedanarticlewithmoredetailsonusingthistechnique.AlthoughotherGoogleAPIsmaynothaveuser-friendlyaliasessuchasManageYourTasks,thegeneraltechniquesdescribedinthearticlewillstillapply.

GoogledoesnothavesimilarfunctionalityavailableforiOSatthetimeofthiswriting.However,GoogledoeshaveaclientlibraryforObjective-CwhichmakescreatinganembeddedWebViewOAuthflowveryeasytoimplementoniOS.

ForFacebookFacebookhasSDKsavailableforbothAndroidandiOSthatautomaticallyprompttheuserforrequestedpermissions.

OnAndroid,youcallFacebook.authorize()andwaitfortheusertoapprovetheauthorizationrequest.Aftertheuserapproves,youcancallFacebook.getAccessToken()togetanaccesstokenforusewiththerequestedAPIs.

Page 71: Getting started with_o_auth_2_0

Chapter7.OpenIDConnectAuthenticationNearlyeverywebapplicationpromptsuserstocreateanaccountandlogin.Inordertocreateanaccount,usersareaskedtoprovidetheirname,theiremailaddress,apassword,andpasswordconfirmation.Notonlydoesthistakealotofeffortfortheuser(50+keystrokes),butitalsocreatessecurityconcerns,asusersoftencreatethesamepasswordonmultiplesitesandsomesitesdonotproperlysecurethesecredentials.

OpenIDexiststoenablefederatedidentity,whereusersareabletoauthenticatewiththesameidentityacrossmultiplewebapplications.Bothusersandwebapplicationstrustidentityproviders,suchasGoogle,Yahoo!,andFacebook,tostoreuserprofileinformationandauthenticateusersonbehalfoftheapplication.Thiseliminatestheneedforeachwebapplicationtobuilditsowncustomauthenticationsystem,anditmakesitmucheasierandfasterforuserstosignupandsignintositesaroundtheWeb.

OpenIDConnectisthenext-generationversionofOpenID.ThedevelopmentofOpenIDConnecthastakenintoaccounttwokeyconcepts:

Passingpermissiontoaccessauthenticationinformation(theuser’sidentity)toasiteisverysimilartopassingalongdelegatedaccesstoauser’sdata(suchastheircalendar).Developersshouldn’thavetouseentirelydifferentprotocolsforthesetwodifferentusecases—especiallybecausemanydevelopersneedtohandlebothintheirapplications.

Thespecificationshouldbemodular—enablingspeccompliancewithoutrequiringimplementationofautomateddiscovery,associations,andothercomplexbitsincludedinthepreviousversionsofOpenID.

ThebasicflowforOpenIDConnectis:

1. TheapplicationrequestsOAuth2.0authorizationforoneormoreoftheOpenIDConnectscopes(openid,profile,email,address)byredirectingtheusertoanidentityprovider.

2. AftertheuserapprovestheOAuthauthorizationrequest,theuser’swebbrowserisredirectedbacktotheapplicationusingatraditionalOAuthflow.TheappmakesarequesttotheCheckIDEndpoint.Thisendpointreturnstheuser’sidentity(user_id)aswellasotherbits,suchastheaudandstate,whichmustbeverifiedbytheclienttoensurevalidauthentication.

3. Iftheclientrequiresadditionalprofileinformationabouttheuser,suchastheuser’sfullname,picture,andemailaddress,theclientcanmakerequeststotheUserInfoEndpoint.

BecauseOpenIDConnectisbuiltontopofOAuth2.0andisdesignedasamodularspecification,it’smucheasierforyoutoimplementfederatedauthenticationforyourwebsiteinacompliantway.SincethisisaGettingStartedbook,thischapterwillprimarilydiscusstheOpenIDConnectBasicClientimplementation.

IDTokenWithOpenIDConnectauthentication,thereisanadditionaltypeofOAuthtoken:anIDtoken.TheIDtoken,orid_token,representstheidentityoftheuserbeingauthenticated.Thisisaseparatetokenfrom

Page 72: Getting started with_o_auth_2_0

theaccesstoken,whichisusedtoretrievetheuser’sprofileinformationorotheruserdatarequestedduringthesameauthorizationflow.

TheIDtokenisaJSONWebToken(JWT),whichisadigitallysignedand/orencryptedrepresentationoftheuser’sidentityassertedbytheidentityprovider.InsteadofusingcryptographicoperationstovalidatetheJSONWebToken,itcanbetreatedasanopaquestringandpassedtotheCheckIDEndpointforinterpretation(seebelow).ThisflexibilitykeepswiththespiritofOAuth2.0andOpenIDConnectbeingsignificantlyeasiertousethantheirpredecessors.

Page 73: Getting started with_o_auth_2_0

SecurityPropertiesAlthoughtheenduserflowisquitesimilar,thesecurityprecautionsnecessaryforauthenticationaremuchdifferentthanthoseforauthorizationbecauseofthepotentialforreplayattacks.Replayattacksoccurwhenlegitimatecredentialsaresentmultipletimesformaliciouspurposes.

Therearetwomaintypesofreplayattackswewishtoprevent:

Anattackercapturingauser’sOAuthcredentialsastheylogintoasiteandusingthemlateronthesamesite.

ArogueapplicationdeveloperusingtheOAuthtokenauserwasissuedtologintotheirmaliciousappinordertoimpersonatetheuseronadifferentlegitimateapp.

TheOAuth2.0specificationrequirestheOAuthendpointandAPIstobeaccessedoverSSL/TLStopreventman-in-the-middleattacks,suchasthefirstcase.

PreventingrogueapplicationdevelopersfromreplayinglegitimateOAuthcredentialstheirappreceivedinordertoimpersonateoneoftheirusersonanotherapprequiresasolutionspecifictoOpenIDConnect.ThissolutionistheCheckIDEndpoint.TheCheckIDEndpointisusedtoverifythatthecredentialsissuedbytheOAuthproviderwereissuedtothecorrectapplication.

ItisrecommendedthatalldevelopersusetheCheckIDEndpointordecodetheJSONWebTokentoverifytheassertedidentity,thoughthisisnotstrictlynecessaryinsomecaseswhentheapplicationusestheserver-sideWebApplicationflowandtheUserInfoEndpointprovidesallrequiredinformation.

Theserver-sideWebApplicationflow,whenimplementedasperthespecification,onlyissuesanauthorizationcodethroughtheuser’swebbrowser.Thewebapplicationshouldnoteveracceptanaccesstokenoridentitytokendirectlyfromthebrowser.Theaccesstokenandidentitytokenareretrievedbyexchangingtheauthorizationcodeinaserver-to-serverrequest.Sincethisexchangerequirestheserver-to-servercalltobeauthenticatedwiththeclientIDandclientsecretoftheappwhichtheauthorizationcodewasissuedfor,theOAuthtokenservicewillnaturallypreventanappfromaccidentallyusinganauthorizationcodeissuedtoanotherapp.

Alternatively,theclient-sideWebApplicationflowissuesanaccesstokenandidentitytokendirectlytotheappthroughthebrowserusingahashfragment.TheaccesstokenandidentitytokenareoftensenttothebackendwebserverusingJavaScriptinordertoauthenticatetheuser.Inthiscase,thewebservermusteithercryptographicallyverifytheIDTokenorcalltheCheckIDendpointtoverifyitwasissuedtothecorrectapplication.Thisiscalled“verifyingtheaudience”ofthetoken.SeeCheckIDEndpointformoreinformation.

Page 74: Getting started with_o_auth_2_0

ObtainingUserAuthorizationTheprocessofobtaininguserauthorizationforOpenIDConnectisnearlyidenticaltotheprocessofobtainingauthorizationforanyOAuth2.0enabledAPI.Youcanuseeithertheclient-sideimplicitflow(asdescribedinChapter3)ortheserver-sidewebappflow(asdescribedinChapter2).

Aswithanyusageoftheseflows,theclientgeneratesaURLpointingattheOAuthAuthorizationEndpointandredirectstheusertothatURL.Thefollowingparametersarepassed:

client_id

Thevalueprovidedtoyouwhenyouregisteredyourapplication.

redirect_uri

Thelocationtheusershouldbereturnedtoaftertheyapprovetheauthenticationrequest.

scope

openidforabasicOpenIDConnectrequest.Ifyourclientneedsaccesstoadditionalprofileinformationfortheuser,additionalscopescanbeprofiledinthisspace-delimitedstring:profile,email,address.

response_type

id_tokentoindicatethatanid_tokenisrequiredfortheapplication.Additionally,aresponsetypeoftokenorcodemustbeincluded,separatingthetworesponsetypesbyaspace.tokenindicatestheclient-sideWebApplicationflow,whilecodeindicatestheserver-sideWebApplicationflow.

nonce

Auniquevalueusedbyyourapplicationtoprotectagainstreplayandcross-siterequestforgery(CSRF)attacksonyourimplementation.Thevalueshouldbearandomuniquestringforthisparticularrequest,unguessableandkeptsecretintheclient(perhapsinaserver-sidesession).ThisidenticalvaluewillbeincludedintheIDtokenresponse(seebelow).

ThefollowingisanexampleofacompleteAuthorizationEndpointURL,usingtheclient-sideimplicitflow:

https://accounts.example.com/oauth2/auth? scope=openid+email& nonce=53f2495d7b435ac571& redirect_uri=https%3A%2F%2Foauth2demo.appspot.com%2Foauthcallback& response_type=id_token+token& client_id=753560681145-2ik2j3snsvbs80ijdi8.apps.googleusercontent.com

Aftertheuserapprovestheauthenticationrequest,theywillberedirectedbacktotheredirect_uri.Sincethisrequestusestheimplicitflow,theredirectwillincludeanaccesstokenthatcanbeusedwiththeUserInfoEndpointtoobtainprofileinformationabouttheuser.Additionally,andspecifictoOpenIDConnect,theredirectwillalsoincludeanid_token,whichcanbesenttotheCheckIDEndpointtogettheuser’sidentity.

Here’sanexampleredirect:https://oauth2demo.appspot.com/oauthcallback# access_token=ya29.AHES6ZSzX

Page 75: Getting started with_o_auth_2_0

token_type=Bearer& expires_in=3600& id_token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiY...

TheclientthenneedstoparsetheappropriateparametersfromthehashfragmentintheURLandcalltheCheckIDEndpointtovalidatetheresponse.

Page 76: Getting started with_o_auth_2_0

CheckIDEndpointTheCheckIDEndpointexiststovalidatetheid_tokenreturnedalongwiththeOAuth2.0access_tokenbyensuringthatitwasintendedforthecorrectclientandisusedbytheclienttobeginanauthenticatedsession.Asdescribedabove,thischeckisrequiredfortheimplicitflowforclient-sideapplications(describedinChapter3).Ifthischeckisn’tdonecorrectly,theclientbecomesvulnerabletoreplayattacks.

Here’sanexampleCheckIDendpointrequest:https://accounts.example.com/oauth2/tokeninfo? id_token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiY...

Andtheresponse:{ "iss" : "https://accounts.example.com", "user_id" : "113487456102835830811", "aud" : "753560681145-2ik2j3snsvbs80ijdi8.apps.googleusercontent.com", "exp" : 1311281970 "nonce" : 53f2495d7b435ac571}

IftheresponseisreturnedwithoutastandardOAuth2.0error,thefollowingchecksneedtobeperformed:

Verifytheaudvalueintheresponseisidenticaltotheclient_idusedintheAuthorizationrequest.

VerifythatthenoncevalueintheresponsematchesthevalueusedintheAuthorizationrequest.

Ifthisverificationiscompletedsuccessfully,theuser_idisknowntorepresenttheuniqueidentifierfortheauthenticateduser,withinthescopeoftheissuer(iss).Ifstoringtheidentifierinauserdatabasetableandmultipleidentityprovidersaresupportedbyyourapplication,itisrecommendedthatbothvaluesbestoreduponaccountcreationandquerieduponeachsubsequentauthenticationrequest.

Page 77: Getting started with_o_auth_2_0

UserInfoEndpointWhiletheCheckIDEndpointwillreturnauniqueidentifierfortheuserauthenticatingtoyourapplication,manyapplicationsrequireadditionalinformation,suchastheuser’sname,emailaddress,profilephoto,orbirthdate.ThisprofileinformationcanbereturnedbytheUserInfoEndpoint.

TheUserInfoEndpointisastandardOAuth-authorizedRESTAPI,withJSONresponses.AswhenaccessinganyotherAPIusingOAuth,theaccess_tokencanbepassedeitherasanAuthorizationheaderorasaURLqueryparameter.

Here’sanexampleUserInforequest:GET /v1/userinfo HTTP/1.1Host: accounts.example.comAuthorization: Bearer ya29.AHES6ZSzX

Withtheresponse:{ "user_id": "3191142839810811", "name": "Example User", "given_name": "Example", "family_name": "User", "email": "[email protected]", "verified": true, "profile": "http://profiles.example.com/user", "picture": "https://photos.profiles.example.com/user/photo.jpg", "gender": "female", "birthday": "1982-02-11", "locale": "en-US"}

OpenIDConnectdoesnotdefineanyspecificprofilefieldsasrequiredanddoesallowforadditionalprofilefieldstobeincludedintheresponse.

Page 78: Getting started with_o_auth_2_0

PerformanceImprovementsTheobjectiveofthecalltotheCheckIDEndpointistoverifythelegitimacyoftheid_token.However,thisrequiresanadditionalHTTPrequesttotheOpenIDConnectidentityprovider.Thisadditionalrequestcanbeavoidedsincetheid_tokenisreturnedasasignedJSONWebToken(JWT)insteadofasanopaqueblob.TheJWTincludesthesameinformationthatistypicallyreturnedbytheCheckIDEndpoint,butthevalueisalsocryptographicallysignedbytheserverinawaythatcanbevalidatedbytheclient.

ThisgivestheclienttheoptiontoverifythesignatureusingtheJWT(forbestperformance)orsimplycalltheCheckIDEndpointiftheclientwantstoavoidcryptography.

Page 79: Getting started with_o_auth_2_0

PracticalOpenIDConnectSincetheOpenIDConnectspecificationisstillunderactivedevelopment,experimentalimplementationsbyidentityprovidersstilldifferfromthespecification.Herearesomeexamplerequestsandresponsesusingtheseexperimentalimplementations.

ForGoogleGoogle’sOpenIDConnectimplementation(seeFigure7-1)usesthefollowingEndpoints:

CheckID

https://www.googleapis.com/oauth2/v1/tokeninfo

UserInfo

https://www.googleapis.com/oauth2/v1/userinfo

Googledoesnothavethegenericopenidscope,butitsupportsthefollowingmainscopesforitsOpenIDConnectimplementation:

Email

https://www.googleapis.com/auth/userinfo.email

Profile

https://www.googleapis.com/auth/userinfo.profile

Here’sanexampleauthorizationURLforGoogle’sOpenIDConnectimplementation:https://accounts.google.com/o/oauth2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&

state=ABC123456& redirect_uri=https%3A%2F%2Foauthssodemo.appspot.com%2Foauthcallback& response_type=token%20id_token& client_id=8819981768.apps.googleusercontent.com

Figure7-1.Googleaskingifit’sOKtoshareinfowithexampleapp“OAuthSSORelyingParty”

Inthisexample,we’respecifyingaresponse_typeoftoken id_token,indicatingthatwe’relookingfor

Page 80: Getting started with_o_auth_2_0

bothanIDtokenandatraditionalOAuth2.0accesstoken(viatheimplicitflow).Aftertheuserapprovestherequestbyclicking“AllowAccess,”Googleredirectsbacktotheredirect_uriandincludesanid_tokenandanaccess_tokeninthehashfragmentoftheURL.Theid_tokenisaJSONWebToken(JWT)andcontainstheuser’sID.ThisIDtokencanbevalidatedbycomparingacryptographicsignatureortheCheckIDEndpointcanbecalled.Forsimplicity,we’llshowhowtocalltheCheckIDEndpoint.Here’sanexamplerequest:

https://www.googleapis.com/oauth2/v1/tokeninfo? id_token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiY...

Here’stheresponse:{ "issued_to" : "8819981768.apps.googleusercontent.com", "user_id" : "113487456102835830811", "audience" : "8819981768.apps.googleusercontent.com", "expires_in" : 3465}

AftertheCheckIDresponseisproperlyvalidatedbyensuringit’sbeenissuedforthecorrectapplication(bycomparingthevalueoftheissued_toparametertotheapp’sclientID),theappmaywishtoobtainadditionalprofileinformationabouttheuser.Thisinformation,suchastheuser’snameoremailaddress,canbeobtainedasaJSONresponsefromtheUserInfoEndpoint.TheOAuthaccess_tokenmustbesenttoauthorizetherequest.Here’sanexamplerequest:

GET /oauth2/v1/userinfo HTTP/1.1Host: www.googleapis.comAuthorization: Bearer ya29.AHES6ZSzX

Here’stheresponse:{ "id": "110634877589748180443", "email": "[email protected]", "verified_email": true, "name": "Ryan Boyd", "given_name": "Ryan", "family_name": "Boyd", "link": "http://profiles.google.com/110634877589748180443", "picture": "https://lh6.googleusercontent.com/-XC1Cwt4OgfY/AAAAAAAAAAI/AAAAAAAACR8/SU9W99JQFvc/photo.jpg", "gender": "male", "birthday": "0000-10-05", "locale": "en-US"}

You’llnoticethattheresponseindicatesmybirthyearas0000.I’mnotthatold;Googleusesthisspecialvaluetoindicatethatthebirthyearisnotshared.

ForFacebookFacebook’simplementationofidentityusingOAuth2.0isn’tdocumentedasbeingOpenIDConnect.However,itworkssimilarlytothespecification,withafewminordifferencestoaccountforinclientcode.

FacebookusesthefollowingEndpoint:

UserInfo

https://graph.facebook.com/me

Page 81: Getting started with_o_auth_2_0

FacebookdoesnotprovideCheckIDEndpointfunctionality,andforthisreasonIrecommendusingonlytheAuthorizationCodeflowforserver-sideapplications(describedinChapter2)andnottheimplicitflowforclient-sideapplications.Ifyouusetheclient-sideWebApplicationflow,you’llhavenoabilitytoverifytheaccesstokenwasintendedforusebyyourapplication,andthuscanleaveyourappvulnerabletoreplayattacks.

HerewecanseeanexampleauthorizationURLforFacebook’sOpenIDConnectimplementation:https://www.facebook.com/dialog/oauth? client_id=202627763128396& redirect_uri=https%3A%2F%2Foauth2demo.appspot.com%2Foauthcallback& state=ABC123456

Sinceascopeisnotspecified,Facebookdefaultstorequestingauthorizationforpublicprofileinformation.Additionalinformationcanberequestedbyspecifyingscopevaluessuchasemail,read_stream.NoticethatFacebookusescomma-delimitedscopevaluesinsteadofspace-delimitedvaluesasdefinedbythelatestOAuth2.0specification.

Sincearesponse_typeisnotspecified,FacebookdefaultstotheAuthorizationCodeflowforserver-sidewebapplications.Ifyouwishtousetheimplicitflowforclient-sidewebapplications,specifyaresponse_type=token,thoughthisisnotrecommended.

AsistypicalwiththeAuthorizationCodeflowforserver-sidewebapplicationsdescribedinChapter2,theuser’sbrowserwillberedirectedtotheapplication’sredirect_uriaftertheuserapprovesaccess.TheredirectURLwillincludeanauthorizationcodeinthecodequeryparameter.TheapplicationthenneedstoexchangetheauthorizationcodeforanaccesstokenbymakingarequesttotheTokenEndpoint.

WhiletheauthorizationcodeexchangetypicallyusesaHTTPPOST,FacebookalsosupportsusingaHTTPGET:

https://graph.facebook.com/oauth/access_token? client_id=202627763128396& redirect_uri=https%3A%2F%2Foauth2demo.appspot.com%2Foauthcallback& client_secret=YOUR_APP_SECRET&code=123456

Sincewe’reusingtheAuthorizationCodeflowforserver-sidewebapplications,thereisnoneedtodoaCheckIDrequest.ThisisbecausetheAuthorizationCodeflowrequirestheapplication’scredentialstobesentsecurelytotheserverwhenexchanginganauthorizationcodeforanaccesstoken,resultinginanautomaticcheckthattheauthorizationcodewasissuedtothecurrentclient.However,theapplicationmustkeeptheaccesstokenconfidentialontheserverandpreventtrustinganyaccesstokendirectlysentbytheuser,ortheapplicationcouldbevulnerabletothesametypeofreplayattackthattheCheckIDendpointwasdesignedtoprevent.

Atthispoint,theapplicationcanobtainprofileinformationfortheuserviathemeendpointoftheGraphAPI.Here’sanexamplerequest:

https://graph.facebook.com/me? access_token=123456abc123456abc

Here’stheresponse:{ "id":"545296355", "name":"Ryan Boyd", "first_name":"Ryan",

Page 82: Getting started with_o_auth_2_0

"last_name":"Boyd", "link":"http:\/\/www.facebook.com\/rboyd", "username":"rboyd", "hometown":{ "id":"114952118516947", "name":"San Francisco, California" }, "location":{ "id":"114952118516947", "name":"San Francisco, California" }, "gender":"male", "email":"ryan\u0040ryguy.com", "timezone":-8, "locale":"en_US", "verified":true, "updated_time":"2011-06-03T18:37:40+0000"}

Page 83: Getting started with_o_auth_2_0

OpenIDConnectEvolutionTheprotocolislikelytochangeafterreceivingfeedbackfrombothidentityprovidersandrelyingparties.InformationonthecurrentDeveloperPreviewcanbefoundontheOpenIDFoundationsite,includingthedetailedspecificationsandmailingliststofollowdevelopmentofthespecifications.

Page 84: Getting started with_o_auth_2_0

Chapter8.ToolsandLibrariesAlthoughOAuth2.0isrelativelyyoung,therearestillavarietyoftoolsandlibrariesavailablefordeveloperstomakeusingiteasier.

Google’sOAuth2.0PlaygroundGooglehasbuiltanewversionofitsOAuthPlaygroundtoolforOAuth2.0(seeFigure8-1).TheOAuth2.0Playgrounddemonstratesthethree-stepprocessforatypicalserver-sidewebapplicationAuthorizationCodeflow:gettinganauthorizationcode,exchangingitforanaccesstoken,andmakingAPIrequests.ItalsosupportstheImplicitflowforclient-sidewebapplications.

WhilethedefaultconfigurationistouseGoogle’sAPIsandOAuthendpoints,thetooldoesenableyoutospecifyacustomclientID,clientsecret,andcustomendpoints.SalesforcehasbloggedabouthowtousethetoolwiththeirAPIs.

Figure8-1.Google’sOAuthPlayground

NOTE

ThistoolismadeavailablebyGoogleforeducationalandtestingpurposes.WhileitexposestheOAuthaccesstokentothewebbrowser(andresourceowner),thisshouldnotnormallybedonewhenusingtheAuthorizationCodeflowandconfidentialclients.Also,specifyingcustomclientIDandclientsecretvaluesrequiresthosecredentialsbesenttotheOAuthPlaygroundserver.

Page 85: Getting started with_o_auth_2_0

Google’sTokenInfoEndpointGoogle’sendpointfortheCheckIDstepofOpenIDConnectcanbeusedtovalidateanyOAuth2.0tokenissuedbyGoogle.Theendpointathttps://www.googleapis.com/oauth2/v1/tokeninfoisasimpleread-onlyAPI.Togetthescopeandexpirationdateofatoken,makeaHTTPrequesttotheendpointandpassanOAuthaccesstokenastheaccess_tokenqueryparameteroranIDtokenastheid_tokenparameter.

Page 86: Getting started with_o_auth_2_0

Apigee’sConsoleTheApigeeConsoleenablesexploringAPIsfrom20+APIproviders,suchasFacebook,Twitter,Salesforce,andSoundCloud.ForthoseAPIssupportingOAuth,itperformsatypicalOAuthflow,thoughwithoutexposingtheprotocol-leveldetailsoftheOAuthexchange.AfterOAuthauthorizationisgrantedusingavarietyofversionsoftheOAuth1.0andOAuth2.0draftspecifications,itprovideseasyaccesstocallAPIsbyselectingprepopulatedendpointURLs.WitheachAPIrequest,theconsoledisplaysthedetailedHTTPrequestandresponsedetails.

Page 87: Getting started with_o_auth_2_0

Facebook’sAccessTokenToolandAccessTokenDebuggerFacebookprovidesanAccessTokenTool,whichissuesaccesstokensthatcanbeusedfortestinganddebugging.Bothuser-basedandapp-basedtokensareissued.Theusertokensissuedbythetoolaresimilartothoseissuedbytheserver-sideWebApplicationfloworclient-sideflow.TheapptokensissuedbythetoolaresimilartothoseissuedbytheClientCredentialsflow.

TheyalsoprovideanAccessTokenDebugger,whichdisplaysinformationaboutOAuthaccesstokens,includingthescopes,validity,issuetime,expirationtimeandmore.

Page 88: Getting started with_o_auth_2_0

LibrariesManymajorAPIprovidersbuildandmaintainclientlibrariesforaccessingtheirspecificservices.Someoftheselibraries,suchastheGoogleAPIClientsandFacebookSDKsprovidebuilt-insupportforOAuth2.0.WhenOAuthsupportisprovided,theselibrariesoftenabstracttheimplementationsenoughtomakeitreallyeasytoimplement.

HerearesomeAPI-specificclientlibrarieswhichimplementOAuth2.0:

GoogleAPIsClientLibrariesforJava,Objective-C,PHP,Python,Ruby,JavaScript

FacebookSDKsforJavaScript,Android,iOS,PHP

Foursquaredoesnotprovideofficiallibraries,butitlinkstomanycommunity-contributedlibraries,manyofwhichsupportOAuth2.0

SomeoftheselibrariesmakeittriviallyeasytoimplementOAuth2.0.Here’sanexampleusingGoogle’sPythonlibraryonAppEnginewiththelibrary’sdecoratorpattern.ThisexamplerequiresonlyafewlinesofOAuth-specificcode:

from oauth2client.appengine import OAuth2Decorator...decorator = OAuth2Decorator( client_id='CLIENT_ID_FROM_DAILYMOTION', client_secret='CLIENT_SECRET_FROM_DAILYMOTION', scope='read', auth_uri='https://api.dailymotion.com/oauth/authorize', token_uri='https://api.dailymotion.com/oauth/token' )

class MainHandler(webapp.RequestHandler):

@decorator.oauth_required def get(self):

http = decorator.http() resp, content = http.request('https://api.dailymotion.com/me')

path = os.path.join(os.path.dirname(__file__), 'welcome.html') logout = users.create_logout_url('/') variables = { 'content': content, 'logout': logout } self.response.out.write(template.render(path, variables))...

Ifyou’relookingtoimplementOAuth2.0acrossawidevarietyofservices,accessyourownserviceswithOAuthauthorization,ormakerequeststoAPIsprovidedwithoutclientlibraries,youshouldconsiderusinganopensourcelibraryforOAuth2.0.

Sincethespecificationisstillunderactivedevelopment,theselibrarieseachsupportdifferentversionsofthedraftspecification.

Supportingdraft10,severaloftheOAuth2.0implementationsintheGoogleAPIclientlibrariesarealsoavailableasseparatelibraries:

oauth2clientinPython

Page 89: Getting started with_o_auth_2_0

GoogleOAuthClientLibraryforJava

Additionallibrariesforotherlanguagesareavailableonoauth.net.

Page 90: Getting started with_o_auth_2_0

GoingFurtherInthisGettingStartedbook,wehavegivenyouanoverviewofhowOAuth2.0worksforobtainingauthorizedaccesstouserdataandwhyitisimportanttoimprovesecurityanduserproductivity.Asanapplicationdeveloper,youshouldnowunderstandthedifferentauthorizationflowsavailableandhowtodecidebetweenthemwhenanAPIprovidersupportsmultipleflows.We’vealsointroducedOpenIDConnect,discussedhowitbuildsontopoftheOAuth2.0protocoltoenableuserauthentication,andsomeofthedifferentsecuritypropertiesofauthenticationversusauthorization.Wehopetheprotocol-levelfoundationprovidedbythisbookwillmakeyouabetterdeveloper,evenifyouendupusinglibrariesthatabstractmanyofthedetails.

AsyouuseOAuth2.0inyourapplication,thereareadditionalconsiderationsyoushouldtakeintoaccounttooptimizeuserexperienceandperformance.Whengettingaccesstoauser’sdata,youshouldexplorehowrequestsfordifferentlevelsofaccessandthetimingofthoserequestsaffectapprovalrates.WhenauthenticatinguserswithOpenIDConnect,youshouldthinkaboutwhichidentityproviderstosupport,howyoudealwithuserswhohaveaccountsonmultipleidentityproviders,howtoimprovesign-inperformancebydecodingtheid_tokenJWT,andotherpotentialfactorsthatcoulddecreasecustomerservicetickets.

WeprimarilyfocusedontheperspectiveofactingasanOAuthclient.ManyapplicationdevelopersmaywishtoopenuptheirdatabybuildingOAuth-authorizedAPIresourceserversandrunningtheirownauthorizationservers.TheknowledgeyougainedfromthisbookshouldhopefullymakeiteasiertounderstandthedetailedspecificationsandsecurityconsiderationsdocumentsthatarereferencedintheAppendixAandareimportantreadingforAPIproviderslaunchingOAuth2.0authorizedservices.

Page 91: Getting started with_o_auth_2_0

AppendixA.ReferencesWhilethespecificationsformedthebasisforthedescriptionanddiagramsoftheindividualprotocolflows,anumberofotheronlineresourceswereusedinpreparationofthisbook.

SpecificationsOAuth2.0draft

OAuth2.0threatmodelandsecurityconsiderations

OAuth2.0:Bearertokens

OAuth2.0:MACaccessauthentication

OpenIDConnectBasic,StandardandMessages

JSONWebToken(JWT)

OAuth2.0:Tokenrevocation

Page 93: Getting started with_o_auth_2_0

MailingListsOAuthIETFWorkingGroup

OpenIDConnectWorkingGroup

Google’soauth2-devforumforquestionsabouttheirOAuth2.0implementation

Page 95: Getting started with_o_auth_2_0

AbouttheAuthorRyanBoydisadeveloperadvocateatGooglefocusedonenablingdeveloperstoextendGoogleAppsandbuildbusinessesontopofGoogletechnology.HepreviouslyworkedonOpenSocialandledthedeveloperrelationsteamforGoogle’sAtomPubAPIs.PriortojoiningGoogle,RyanworkedinhighereducationasawebarchitectforRIT’scentralwebhostingenvironmentandaswebappdeveloperbuildingadmissionsandstudentsystems.

Page 96: Getting started with_o_auth_2_0

SPECIALOFFER:UpgradethisebookwithO’ReillyUpgradethisebooktodayfor$4.99atoreilly.comandgetaccesstoadditionalDRM-freeformats,includingPDFandEPUB,alongwithfreelifetimeupdates.