123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194 |
- 'use strict';
- var util = require('@firebase/util');
- var app = require('@firebase/app');
- var tslib = require('tslib');
- var logger = require('@firebase/logger');
- var component = require('@firebase/component');
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * An enum of factors that may be used for multifactor authentication.
- *
- * @public
- */
- const FactorId = {
- /** Phone as second factor */
- PHONE: 'phone',
- TOTP: 'totp'
- };
- /**
- * Enumeration of supported providers.
- *
- * @public
- */
- const ProviderId = {
- /** Facebook provider ID */
- FACEBOOK: 'facebook.com',
- /** GitHub provider ID */
- GITHUB: 'github.com',
- /** Google provider ID */
- GOOGLE: 'google.com',
- /** Password provider */
- PASSWORD: 'password',
- /** Phone provider */
- PHONE: 'phone',
- /** Twitter provider ID */
- TWITTER: 'twitter.com'
- };
- /**
- * Enumeration of supported sign-in methods.
- *
- * @public
- */
- const SignInMethod = {
- /** Email link sign in method */
- EMAIL_LINK: 'emailLink',
- /** Email/password sign in method */
- EMAIL_PASSWORD: 'password',
- /** Facebook sign in method */
- FACEBOOK: 'facebook.com',
- /** GitHub sign in method */
- GITHUB: 'github.com',
- /** Google sign in method */
- GOOGLE: 'google.com',
- /** Phone sign in method */
- PHONE: 'phone',
- /** Twitter sign in method */
- TWITTER: 'twitter.com'
- };
- /**
- * Enumeration of supported operation types.
- *
- * @public
- */
- const OperationType = {
- /** Operation involving linking an additional provider to an already signed-in user. */
- LINK: 'link',
- /** Operation involving using a provider to reauthenticate an already signed-in user. */
- REAUTHENTICATE: 'reauthenticate',
- /** Operation involving signing in a user. */
- SIGN_IN: 'signIn'
- };
- /**
- * An enumeration of the possible email action types.
- *
- * @public
- */
- const ActionCodeOperation = {
- /** The email link sign-in action. */
- EMAIL_SIGNIN: 'EMAIL_SIGNIN',
- /** The password reset action. */
- PASSWORD_RESET: 'PASSWORD_RESET',
- /** The email revocation action. */
- RECOVER_EMAIL: 'RECOVER_EMAIL',
- /** The revert second factor addition email action. */
- REVERT_SECOND_FACTOR_ADDITION: 'REVERT_SECOND_FACTOR_ADDITION',
- /** The revert second factor addition email action. */
- VERIFY_AND_CHANGE_EMAIL: 'VERIFY_AND_CHANGE_EMAIL',
- /** The email verification action. */
- VERIFY_EMAIL: 'VERIFY_EMAIL'
- };
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _debugErrorMap() {
- return {
- ["admin-restricted-operation" /* AuthErrorCode.ADMIN_ONLY_OPERATION */]: 'This operation is restricted to administrators only.',
- ["argument-error" /* AuthErrorCode.ARGUMENT_ERROR */]: '',
- ["app-not-authorized" /* AuthErrorCode.APP_NOT_AUTHORIZED */]: "This app, identified by the domain where it's hosted, is not " +
- 'authorized to use Firebase Authentication with the provided API key. ' +
- 'Review your key configuration in the Google API console.',
- ["app-not-installed" /* AuthErrorCode.APP_NOT_INSTALLED */]: 'The requested mobile application corresponding to the identifier (' +
- 'Android package name or iOS bundle ID) provided is not installed on ' +
- 'this device.',
- ["captcha-check-failed" /* AuthErrorCode.CAPTCHA_CHECK_FAILED */]: 'The reCAPTCHA response token provided is either invalid, expired, ' +
- 'already used or the domain associated with it does not match the list ' +
- 'of whitelisted domains.',
- ["code-expired" /* AuthErrorCode.CODE_EXPIRED */]: 'The SMS code has expired. Please re-send the verification code to try ' +
- 'again.',
- ["cordova-not-ready" /* AuthErrorCode.CORDOVA_NOT_READY */]: 'Cordova framework is not ready.',
- ["cors-unsupported" /* AuthErrorCode.CORS_UNSUPPORTED */]: 'This browser is not supported.',
- ["credential-already-in-use" /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */]: 'This credential is already associated with a different user account.',
- ["custom-token-mismatch" /* AuthErrorCode.CREDENTIAL_MISMATCH */]: 'The custom token corresponds to a different audience.',
- ["requires-recent-login" /* AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */]: 'This operation is sensitive and requires recent authentication. Log in ' +
- 'again before retrying this request.',
- ["dependent-sdk-initialized-before-auth" /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */]: 'Another Firebase SDK was initialized and is trying to use Auth before Auth is ' +
- 'initialized. Please be sure to call `initializeAuth` or `getAuth` before ' +
- 'starting any other Firebase SDK.',
- ["dynamic-link-not-activated" /* AuthErrorCode.DYNAMIC_LINK_NOT_ACTIVATED */]: 'Please activate Dynamic Links in the Firebase Console and agree to the terms and ' +
- 'conditions.',
- ["email-change-needs-verification" /* AuthErrorCode.EMAIL_CHANGE_NEEDS_VERIFICATION */]: 'Multi-factor users must always have a verified email.',
- ["email-already-in-use" /* AuthErrorCode.EMAIL_EXISTS */]: 'The email address is already in use by another account.',
- ["emulator-config-failed" /* AuthErrorCode.EMULATOR_CONFIG_FAILED */]: 'Auth instance has already been used to make a network call. Auth can ' +
- 'no longer be configured to use the emulator. Try calling ' +
- '"connectAuthEmulator()" sooner.',
- ["expired-action-code" /* AuthErrorCode.EXPIRED_OOB_CODE */]: 'The action code has expired.',
- ["cancelled-popup-request" /* AuthErrorCode.EXPIRED_POPUP_REQUEST */]: 'This operation has been cancelled due to another conflicting popup being opened.',
- ["internal-error" /* AuthErrorCode.INTERNAL_ERROR */]: 'An internal AuthError has occurred.',
- ["invalid-app-credential" /* AuthErrorCode.INVALID_APP_CREDENTIAL */]: 'The phone verification request contains an invalid application verifier.' +
- ' The reCAPTCHA token response is either invalid or expired.',
- ["invalid-app-id" /* AuthErrorCode.INVALID_APP_ID */]: 'The mobile app identifier is not registed for the current project.',
- ["invalid-user-token" /* AuthErrorCode.INVALID_AUTH */]: "This user's credential isn't valid for this project. This can happen " +
- "if the user's token has been tampered with, or if the user isn't for " +
- 'the project associated with this API key.',
- ["invalid-auth-event" /* AuthErrorCode.INVALID_AUTH_EVENT */]: 'An internal AuthError has occurred.',
- ["invalid-verification-code" /* AuthErrorCode.INVALID_CODE */]: 'The SMS verification code used to create the phone auth credential is ' +
- 'invalid. Please resend the verification code sms and be sure to use the ' +
- 'verification code provided by the user.',
- ["invalid-continue-uri" /* AuthErrorCode.INVALID_CONTINUE_URI */]: 'The continue URL provided in the request is invalid.',
- ["invalid-cordova-configuration" /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */]: 'The following Cordova plugins must be installed to enable OAuth sign-in: ' +
- 'cordova-plugin-buildinfo, cordova-universal-links-plugin, ' +
- 'cordova-plugin-browsertab, cordova-plugin-inappbrowser and ' +
- 'cordova-plugin-customurlscheme.',
- ["invalid-custom-token" /* AuthErrorCode.INVALID_CUSTOM_TOKEN */]: 'The custom token format is incorrect. Please check the documentation.',
- ["invalid-dynamic-link-domain" /* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */]: 'The provided dynamic link domain is not configured or authorized for the current project.',
- ["invalid-email" /* AuthErrorCode.INVALID_EMAIL */]: 'The email address is badly formatted.',
- ["invalid-emulator-scheme" /* AuthErrorCode.INVALID_EMULATOR_SCHEME */]: 'Emulator URL must start with a valid scheme (http:// or https://).',
- ["invalid-api-key" /* AuthErrorCode.INVALID_API_KEY */]: 'Your API key is invalid, please check you have copied it correctly.',
- ["invalid-cert-hash" /* AuthErrorCode.INVALID_CERT_HASH */]: 'The SHA-1 certificate hash provided is invalid.',
- ["invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */]: 'The supplied auth credential is malformed or has expired.',
- ["invalid-message-payload" /* AuthErrorCode.INVALID_MESSAGE_PAYLOAD */]: 'The email template corresponding to this action contains invalid characters in its message. ' +
- 'Please fix by going to the Auth email templates section in the Firebase Console.',
- ["invalid-multi-factor-session" /* AuthErrorCode.INVALID_MFA_SESSION */]: 'The request does not contain a valid proof of first factor successful sign-in.',
- ["invalid-oauth-provider" /* AuthErrorCode.INVALID_OAUTH_PROVIDER */]: 'EmailAuthProvider is not supported for this operation. This operation ' +
- 'only supports OAuth providers.',
- ["invalid-oauth-client-id" /* AuthErrorCode.INVALID_OAUTH_CLIENT_ID */]: 'The OAuth client ID provided is either invalid or does not match the ' +
- 'specified API key.',
- ["unauthorized-domain" /* AuthErrorCode.INVALID_ORIGIN */]: 'This domain is not authorized for OAuth operations for your Firebase ' +
- 'project. Edit the list of authorized domains from the Firebase console.',
- ["invalid-action-code" /* AuthErrorCode.INVALID_OOB_CODE */]: 'The action code is invalid. This can happen if the code is malformed, ' +
- 'expired, or has already been used.',
- ["wrong-password" /* AuthErrorCode.INVALID_PASSWORD */]: 'The password is invalid or the user does not have a password.',
- ["invalid-persistence-type" /* AuthErrorCode.INVALID_PERSISTENCE */]: 'The specified persistence type is invalid. It can only be local, session or none.',
- ["invalid-phone-number" /* AuthErrorCode.INVALID_PHONE_NUMBER */]: 'The format of the phone number provided is incorrect. Please enter the ' +
- 'phone number in a format that can be parsed into E.164 format. E.164 ' +
- 'phone numbers are written in the format [+][country code][subscriber ' +
- 'number including area code].',
- ["invalid-provider-id" /* AuthErrorCode.INVALID_PROVIDER_ID */]: 'The specified provider ID is invalid.',
- ["invalid-recipient-email" /* AuthErrorCode.INVALID_RECIPIENT_EMAIL */]: 'The email corresponding to this action failed to send as the provided ' +
- 'recipient email address is invalid.',
- ["invalid-sender" /* AuthErrorCode.INVALID_SENDER */]: 'The email template corresponding to this action contains an invalid sender email or name. ' +
- 'Please fix by going to the Auth email templates section in the Firebase Console.',
- ["invalid-verification-id" /* AuthErrorCode.INVALID_SESSION_INFO */]: 'The verification ID used to create the phone auth credential is invalid.',
- ["invalid-tenant-id" /* AuthErrorCode.INVALID_TENANT_ID */]: "The Auth instance's tenant ID is invalid.",
- ["login-blocked" /* AuthErrorCode.LOGIN_BLOCKED */]: 'Login blocked by user-provided method: {$originalMessage}',
- ["missing-android-pkg-name" /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */]: 'An Android Package Name must be provided if the Android App is required to be installed.',
- ["auth-domain-config-required" /* AuthErrorCode.MISSING_AUTH_DOMAIN */]: 'Be sure to include authDomain when calling firebase.initializeApp(), ' +
- 'by following the instructions in the Firebase console.',
- ["missing-app-credential" /* AuthErrorCode.MISSING_APP_CREDENTIAL */]: 'The phone verification request is missing an application verifier ' +
- 'assertion. A reCAPTCHA response token needs to be provided.',
- ["missing-verification-code" /* AuthErrorCode.MISSING_CODE */]: 'The phone auth credential was created with an empty SMS verification code.',
- ["missing-continue-uri" /* AuthErrorCode.MISSING_CONTINUE_URI */]: 'A continue URL must be provided in the request.',
- ["missing-iframe-start" /* AuthErrorCode.MISSING_IFRAME_START */]: 'An internal AuthError has occurred.',
- ["missing-ios-bundle-id" /* AuthErrorCode.MISSING_IOS_BUNDLE_ID */]: 'An iOS Bundle ID must be provided if an App Store ID is provided.',
- ["missing-or-invalid-nonce" /* AuthErrorCode.MISSING_OR_INVALID_NONCE */]: 'The request does not contain a valid nonce. This can occur if the ' +
- 'SHA-256 hash of the provided raw nonce does not match the hashed nonce ' +
- 'in the ID token payload.',
- ["missing-password" /* AuthErrorCode.MISSING_PASSWORD */]: 'A non-empty password must be provided',
- ["missing-multi-factor-info" /* AuthErrorCode.MISSING_MFA_INFO */]: 'No second factor identifier is provided.',
- ["missing-multi-factor-session" /* AuthErrorCode.MISSING_MFA_SESSION */]: 'The request is missing proof of first factor successful sign-in.',
- ["missing-phone-number" /* AuthErrorCode.MISSING_PHONE_NUMBER */]: 'To send verification codes, provide a phone number for the recipient.',
- ["missing-verification-id" /* AuthErrorCode.MISSING_SESSION_INFO */]: 'The phone auth credential was created with an empty verification ID.',
- ["app-deleted" /* AuthErrorCode.MODULE_DESTROYED */]: 'This instance of FirebaseApp has been deleted.',
- ["multi-factor-info-not-found" /* AuthErrorCode.MFA_INFO_NOT_FOUND */]: 'The user does not have a second factor matching the identifier provided.',
- ["multi-factor-auth-required" /* AuthErrorCode.MFA_REQUIRED */]: 'Proof of ownership of a second factor is required to complete sign-in.',
- ["account-exists-with-different-credential" /* AuthErrorCode.NEED_CONFIRMATION */]: 'An account already exists with the same email address but different ' +
- 'sign-in credentials. Sign in using a provider associated with this ' +
- 'email address.',
- ["network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */]: 'A network AuthError (such as timeout, interrupted connection or unreachable host) has occurred.',
- ["no-auth-event" /* AuthErrorCode.NO_AUTH_EVENT */]: 'An internal AuthError has occurred.',
- ["no-such-provider" /* AuthErrorCode.NO_SUCH_PROVIDER */]: 'User was not linked to an account with the given provider.',
- ["null-user" /* AuthErrorCode.NULL_USER */]: 'A null user object was provided as the argument for an operation which ' +
- 'requires a non-null user object.',
- ["operation-not-allowed" /* AuthErrorCode.OPERATION_NOT_ALLOWED */]: 'The given sign-in provider is disabled for this Firebase project. ' +
- 'Enable it in the Firebase console, under the sign-in method tab of the ' +
- 'Auth section.',
- ["operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */]: 'This operation is not supported in the environment this application is ' +
- 'running on. "location.protocol" must be http, https or chrome-extension' +
- ' and web storage must be enabled.',
- ["popup-blocked" /* AuthErrorCode.POPUP_BLOCKED */]: 'Unable to establish a connection with the popup. It may have been blocked by the browser.',
- ["popup-closed-by-user" /* AuthErrorCode.POPUP_CLOSED_BY_USER */]: 'The popup has been closed by the user before finalizing the operation.',
- ["provider-already-linked" /* AuthErrorCode.PROVIDER_ALREADY_LINKED */]: 'User can only be linked to one identity for the given provider.',
- ["quota-exceeded" /* AuthErrorCode.QUOTA_EXCEEDED */]: "The project's quota for this operation has been exceeded.",
- ["redirect-cancelled-by-user" /* AuthErrorCode.REDIRECT_CANCELLED_BY_USER */]: 'The redirect operation has been cancelled by the user before finalizing.',
- ["redirect-operation-pending" /* AuthErrorCode.REDIRECT_OPERATION_PENDING */]: 'A redirect sign-in operation is already pending.',
- ["rejected-credential" /* AuthErrorCode.REJECTED_CREDENTIAL */]: 'The request contains malformed or mismatching credentials.',
- ["second-factor-already-in-use" /* AuthErrorCode.SECOND_FACTOR_ALREADY_ENROLLED */]: 'The second factor is already enrolled on this account.',
- ["maximum-second-factor-count-exceeded" /* AuthErrorCode.SECOND_FACTOR_LIMIT_EXCEEDED */]: 'The maximum allowed number of second factors on a user has been exceeded.',
- ["tenant-id-mismatch" /* AuthErrorCode.TENANT_ID_MISMATCH */]: "The provided tenant ID does not match the Auth instance's tenant ID",
- ["timeout" /* AuthErrorCode.TIMEOUT */]: 'The operation has timed out.',
- ["user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */]: "The user's credential is no longer valid. The user must sign in again.",
- ["too-many-requests" /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */]: 'We have blocked all requests from this device due to unusual activity. ' +
- 'Try again later.',
- ["unauthorized-continue-uri" /* AuthErrorCode.UNAUTHORIZED_DOMAIN */]: 'The domain of the continue URL is not whitelisted. Please whitelist ' +
- 'the domain in the Firebase console.',
- ["unsupported-first-factor" /* AuthErrorCode.UNSUPPORTED_FIRST_FACTOR */]: 'Enrolling a second factor or signing in with a multi-factor account requires sign-in with a supported first factor.',
- ["unsupported-persistence-type" /* AuthErrorCode.UNSUPPORTED_PERSISTENCE */]: 'The current environment does not support the specified persistence type.',
- ["unsupported-tenant-operation" /* AuthErrorCode.UNSUPPORTED_TENANT_OPERATION */]: 'This operation is not supported in a multi-tenant context.',
- ["unverified-email" /* AuthErrorCode.UNVERIFIED_EMAIL */]: 'The operation requires a verified email.',
- ["user-cancelled" /* AuthErrorCode.USER_CANCELLED */]: 'The user did not grant your application the permissions it requested.',
- ["user-not-found" /* AuthErrorCode.USER_DELETED */]: 'There is no user record corresponding to this identifier. The user may ' +
- 'have been deleted.',
- ["user-disabled" /* AuthErrorCode.USER_DISABLED */]: 'The user account has been disabled by an administrator.',
- ["user-mismatch" /* AuthErrorCode.USER_MISMATCH */]: 'The supplied credentials do not correspond to the previously signed in user.',
- ["user-signed-out" /* AuthErrorCode.USER_SIGNED_OUT */]: '',
- ["weak-password" /* AuthErrorCode.WEAK_PASSWORD */]: 'The password must be 6 characters long or more.',
- ["web-storage-unsupported" /* AuthErrorCode.WEB_STORAGE_UNSUPPORTED */]: 'This browser is not supported or 3rd party cookies and data may be disabled.',
- ["already-initialized" /* AuthErrorCode.ALREADY_INITIALIZED */]: 'initializeAuth() has already been called with ' +
- 'different options. To avoid this error, call initializeAuth() with the ' +
- 'same options as when it was originally called, or call getAuth() to return the' +
- ' already initialized instance.',
- ["missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */]: 'The reCAPTCHA token is missing when sending request to the backend.',
- ["invalid-recaptcha-token" /* AuthErrorCode.INVALID_RECAPTCHA_TOKEN */]: 'The reCAPTCHA token is invalid when sending request to the backend.',
- ["invalid-recaptcha-action" /* AuthErrorCode.INVALID_RECAPTCHA_ACTION */]: 'The reCAPTCHA action is invalid when sending request to the backend.',
- ["recaptcha-not-enabled" /* AuthErrorCode.RECAPTCHA_NOT_ENABLED */]: 'reCAPTCHA Enterprise integration is not enabled for this project.',
- ["missing-client-type" /* AuthErrorCode.MISSING_CLIENT_TYPE */]: 'The reCAPTCHA client type is missing when sending request to the backend.',
- ["missing-recaptcha-version" /* AuthErrorCode.MISSING_RECAPTCHA_VERSION */]: 'The reCAPTCHA version is missing when sending request to the backend.',
- ["invalid-req-type" /* AuthErrorCode.INVALID_REQ_TYPE */]: 'Invalid request parameters.',
- ["invalid-recaptcha-version" /* AuthErrorCode.INVALID_RECAPTCHA_VERSION */]: 'The reCAPTCHA version is invalid when sending request to the backend.'
- };
- }
- function _prodErrorMap() {
- // We will include this one message in the prod error map since by the very
- // nature of this error, developers will never be able to see the message
- // using the debugErrorMap (which is installed during auth initialization).
- return {
- ["dependent-sdk-initialized-before-auth" /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */]: 'Another Firebase SDK was initialized and is trying to use Auth before Auth is ' +
- 'initialized. Please be sure to call `initializeAuth` or `getAuth` before ' +
- 'starting any other Firebase SDK.'
- };
- }
- /**
- * A verbose error map with detailed descriptions for most error codes.
- *
- * See discussion at {@link AuthErrorMap}
- *
- * @public
- */
- const debugErrorMap = _debugErrorMap;
- /**
- * A minimal error map with all verbose error messages stripped.
- *
- * See discussion at {@link AuthErrorMap}
- *
- * @public
- */
- const prodErrorMap = _prodErrorMap;
- const _DEFAULT_AUTH_ERROR_FACTORY = new util.ErrorFactory('auth', 'Firebase', _prodErrorMap());
- /**
- * A map of potential `Auth` error codes, for easier comparison with errors
- * thrown by the SDK.
- *
- * @remarks
- * Note that you can't tree-shake individual keys
- * in the map, so by using the map you might substantially increase your
- * bundle size.
- *
- * @public
- */
- const AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = {
- ADMIN_ONLY_OPERATION: 'auth/admin-restricted-operation',
- ARGUMENT_ERROR: 'auth/argument-error',
- APP_NOT_AUTHORIZED: 'auth/app-not-authorized',
- APP_NOT_INSTALLED: 'auth/app-not-installed',
- CAPTCHA_CHECK_FAILED: 'auth/captcha-check-failed',
- CODE_EXPIRED: 'auth/code-expired',
- CORDOVA_NOT_READY: 'auth/cordova-not-ready',
- CORS_UNSUPPORTED: 'auth/cors-unsupported',
- CREDENTIAL_ALREADY_IN_USE: 'auth/credential-already-in-use',
- CREDENTIAL_MISMATCH: 'auth/custom-token-mismatch',
- CREDENTIAL_TOO_OLD_LOGIN_AGAIN: 'auth/requires-recent-login',
- DEPENDENT_SDK_INIT_BEFORE_AUTH: 'auth/dependent-sdk-initialized-before-auth',
- DYNAMIC_LINK_NOT_ACTIVATED: 'auth/dynamic-link-not-activated',
- EMAIL_CHANGE_NEEDS_VERIFICATION: 'auth/email-change-needs-verification',
- EMAIL_EXISTS: 'auth/email-already-in-use',
- EMULATOR_CONFIG_FAILED: 'auth/emulator-config-failed',
- EXPIRED_OOB_CODE: 'auth/expired-action-code',
- EXPIRED_POPUP_REQUEST: 'auth/cancelled-popup-request',
- INTERNAL_ERROR: 'auth/internal-error',
- INVALID_API_KEY: 'auth/invalid-api-key',
- INVALID_APP_CREDENTIAL: 'auth/invalid-app-credential',
- INVALID_APP_ID: 'auth/invalid-app-id',
- INVALID_AUTH: 'auth/invalid-user-token',
- INVALID_AUTH_EVENT: 'auth/invalid-auth-event',
- INVALID_CERT_HASH: 'auth/invalid-cert-hash',
- INVALID_CODE: 'auth/invalid-verification-code',
- INVALID_CONTINUE_URI: 'auth/invalid-continue-uri',
- INVALID_CORDOVA_CONFIGURATION: 'auth/invalid-cordova-configuration',
- INVALID_CUSTOM_TOKEN: 'auth/invalid-custom-token',
- INVALID_DYNAMIC_LINK_DOMAIN: 'auth/invalid-dynamic-link-domain',
- INVALID_EMAIL: 'auth/invalid-email',
- INVALID_EMULATOR_SCHEME: 'auth/invalid-emulator-scheme',
- INVALID_IDP_RESPONSE: 'auth/invalid-credential',
- INVALID_MESSAGE_PAYLOAD: 'auth/invalid-message-payload',
- INVALID_MFA_SESSION: 'auth/invalid-multi-factor-session',
- INVALID_OAUTH_CLIENT_ID: 'auth/invalid-oauth-client-id',
- INVALID_OAUTH_PROVIDER: 'auth/invalid-oauth-provider',
- INVALID_OOB_CODE: 'auth/invalid-action-code',
- INVALID_ORIGIN: 'auth/unauthorized-domain',
- INVALID_PASSWORD: 'auth/wrong-password',
- INVALID_PERSISTENCE: 'auth/invalid-persistence-type',
- INVALID_PHONE_NUMBER: 'auth/invalid-phone-number',
- INVALID_PROVIDER_ID: 'auth/invalid-provider-id',
- INVALID_RECIPIENT_EMAIL: 'auth/invalid-recipient-email',
- INVALID_SENDER: 'auth/invalid-sender',
- INVALID_SESSION_INFO: 'auth/invalid-verification-id',
- INVALID_TENANT_ID: 'auth/invalid-tenant-id',
- MFA_INFO_NOT_FOUND: 'auth/multi-factor-info-not-found',
- MFA_REQUIRED: 'auth/multi-factor-auth-required',
- MISSING_ANDROID_PACKAGE_NAME: 'auth/missing-android-pkg-name',
- MISSING_APP_CREDENTIAL: 'auth/missing-app-credential',
- MISSING_AUTH_DOMAIN: 'auth/auth-domain-config-required',
- MISSING_CODE: 'auth/missing-verification-code',
- MISSING_CONTINUE_URI: 'auth/missing-continue-uri',
- MISSING_IFRAME_START: 'auth/missing-iframe-start',
- MISSING_IOS_BUNDLE_ID: 'auth/missing-ios-bundle-id',
- MISSING_OR_INVALID_NONCE: 'auth/missing-or-invalid-nonce',
- MISSING_MFA_INFO: 'auth/missing-multi-factor-info',
- MISSING_MFA_SESSION: 'auth/missing-multi-factor-session',
- MISSING_PHONE_NUMBER: 'auth/missing-phone-number',
- MISSING_SESSION_INFO: 'auth/missing-verification-id',
- MODULE_DESTROYED: 'auth/app-deleted',
- NEED_CONFIRMATION: 'auth/account-exists-with-different-credential',
- NETWORK_REQUEST_FAILED: 'auth/network-request-failed',
- NULL_USER: 'auth/null-user',
- NO_AUTH_EVENT: 'auth/no-auth-event',
- NO_SUCH_PROVIDER: 'auth/no-such-provider',
- OPERATION_NOT_ALLOWED: 'auth/operation-not-allowed',
- OPERATION_NOT_SUPPORTED: 'auth/operation-not-supported-in-this-environment',
- POPUP_BLOCKED: 'auth/popup-blocked',
- POPUP_CLOSED_BY_USER: 'auth/popup-closed-by-user',
- PROVIDER_ALREADY_LINKED: 'auth/provider-already-linked',
- QUOTA_EXCEEDED: 'auth/quota-exceeded',
- REDIRECT_CANCELLED_BY_USER: 'auth/redirect-cancelled-by-user',
- REDIRECT_OPERATION_PENDING: 'auth/redirect-operation-pending',
- REJECTED_CREDENTIAL: 'auth/rejected-credential',
- SECOND_FACTOR_ALREADY_ENROLLED: 'auth/second-factor-already-in-use',
- SECOND_FACTOR_LIMIT_EXCEEDED: 'auth/maximum-second-factor-count-exceeded',
- TENANT_ID_MISMATCH: 'auth/tenant-id-mismatch',
- TIMEOUT: 'auth/timeout',
- TOKEN_EXPIRED: 'auth/user-token-expired',
- TOO_MANY_ATTEMPTS_TRY_LATER: 'auth/too-many-requests',
- UNAUTHORIZED_DOMAIN: 'auth/unauthorized-continue-uri',
- UNSUPPORTED_FIRST_FACTOR: 'auth/unsupported-first-factor',
- UNSUPPORTED_PERSISTENCE: 'auth/unsupported-persistence-type',
- UNSUPPORTED_TENANT_OPERATION: 'auth/unsupported-tenant-operation',
- UNVERIFIED_EMAIL: 'auth/unverified-email',
- USER_CANCELLED: 'auth/user-cancelled',
- USER_DELETED: 'auth/user-not-found',
- USER_DISABLED: 'auth/user-disabled',
- USER_MISMATCH: 'auth/user-mismatch',
- USER_SIGNED_OUT: 'auth/user-signed-out',
- WEAK_PASSWORD: 'auth/weak-password',
- WEB_STORAGE_UNSUPPORTED: 'auth/web-storage-unsupported',
- ALREADY_INITIALIZED: 'auth/already-initialized',
- RECAPTCHA_NOT_ENABLED: 'auth/recaptcha-not-enabled',
- MISSING_RECAPTCHA_TOKEN: 'auth/missing-recaptcha-token',
- INVALID_RECAPTCHA_TOKEN: 'auth/invalid-recaptcha-token',
- INVALID_RECAPTCHA_ACTION: 'auth/invalid-recaptcha-action',
- MISSING_CLIENT_TYPE: 'auth/missing-client-type',
- MISSING_RECAPTCHA_VERSION: 'auth/missing-recaptcha-version',
- INVALID_RECAPTCHA_VERSION: 'auth/invalid-recaptcha-version',
- INVALID_REQ_TYPE: 'auth/invalid-req-type'
- };
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const logClient = new logger.Logger('@firebase/auth');
- function _logWarn(msg, ...args) {
- if (logClient.logLevel <= logger.LogLevel.WARN) {
- logClient.warn(`Auth (${app.SDK_VERSION}): ${msg}`, ...args);
- }
- }
- function _logError(msg, ...args) {
- if (logClient.logLevel <= logger.LogLevel.ERROR) {
- logClient.error(`Auth (${app.SDK_VERSION}): ${msg}`, ...args);
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _fail(authOrCode, ...rest) {
- throw createErrorInternal(authOrCode, ...rest);
- }
- function _createError(authOrCode, ...rest) {
- return createErrorInternal(authOrCode, ...rest);
- }
- function _errorWithCustomMessage(auth, code, message) {
- const errorMap = Object.assign(Object.assign({}, prodErrorMap()), { [code]: message });
- const factory = new util.ErrorFactory('auth', 'Firebase', errorMap);
- return factory.create(code, {
- appName: auth.name
- });
- }
- function _assertInstanceOf(auth, object, instance) {
- const constructorInstance = instance;
- if (!(object instanceof constructorInstance)) {
- if (constructorInstance.name !== object.constructor.name) {
- _fail(auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- }
- throw _errorWithCustomMessage(auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */, `Type of ${object.constructor.name} does not match expected instance.` +
- `Did you pass a reference from a different Auth SDK?`);
- }
- }
- function createErrorInternal(authOrCode, ...rest) {
- if (typeof authOrCode !== 'string') {
- const code = rest[0];
- const fullParams = [...rest.slice(1)];
- if (fullParams[0]) {
- fullParams[0].appName = authOrCode.name;
- }
- return authOrCode._errorFactory.create(code, ...fullParams);
- }
- return _DEFAULT_AUTH_ERROR_FACTORY.create(authOrCode, ...rest);
- }
- function _assert(assertion, authOrCode, ...rest) {
- if (!assertion) {
- throw createErrorInternal(authOrCode, ...rest);
- }
- }
- /**
- * Unconditionally fails, throwing an internal error with the given message.
- *
- * @param failure type of failure encountered
- * @throws Error
- */
- function debugFail(failure) {
- // Log the failure in addition to throw an exception, just in case the
- // exception is swallowed.
- const message = `INTERNAL ASSERTION FAILED: ` + failure;
- _logError(message);
- // NOTE: We don't use FirebaseError here because these are internal failures
- // that cannot be handled by the user. (Also it would create a circular
- // dependency between the error and assert modules which doesn't work.)
- throw new Error(message);
- }
- /**
- * Fails if the given assertion condition is false, throwing an Error with the
- * given message if it did.
- *
- * @param assertion
- * @param message
- */
- function debugAssert(assertion, message) {
- if (!assertion) {
- debugFail(message);
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _getCurrentUrl() {
- var _a;
- return (typeof self !== 'undefined' && ((_a = self.location) === null || _a === void 0 ? void 0 : _a.href)) || '';
- }
- function _isHttpOrHttps() {
- return _getCurrentScheme() === 'http:' || _getCurrentScheme() === 'https:';
- }
- function _getCurrentScheme() {
- var _a;
- return (typeof self !== 'undefined' && ((_a = self.location) === null || _a === void 0 ? void 0 : _a.protocol)) || null;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Determine whether the browser is working online
- */
- function _isOnline() {
- if (typeof navigator !== 'undefined' &&
- navigator &&
- 'onLine' in navigator &&
- typeof navigator.onLine === 'boolean' &&
- // Apply only for traditional web apps and Chrome extensions.
- // This is especially true for Cordova apps which have unreliable
- // navigator.onLine behavior unless cordova-plugin-network-information is
- // installed which overwrites the native navigator.onLine value and
- // defines navigator.connection.
- (_isHttpOrHttps() || util.isBrowserExtension() || 'connection' in navigator)) {
- return navigator.onLine;
- }
- // If we can't determine the state, assume it is online.
- return true;
- }
- function _getUserLanguage() {
- if (typeof navigator === 'undefined') {
- return null;
- }
- const navigatorLanguage = navigator;
- return (
- // Most reliable, but only supported in Chrome/Firefox.
- (navigatorLanguage.languages && navigatorLanguage.languages[0]) ||
- // Supported in most browsers, but returns the language of the browser
- // UI, not the language set in browser settings.
- navigatorLanguage.language ||
- // Couldn't determine language.
- null);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * A structure to help pick between a range of long and short delay durations
- * depending on the current environment. In general, the long delay is used for
- * mobile environments whereas short delays are used for desktop environments.
- */
- class Delay {
- constructor(shortDelay, longDelay) {
- this.shortDelay = shortDelay;
- this.longDelay = longDelay;
- // Internal error when improperly initialized.
- debugAssert(longDelay > shortDelay, 'Short delay should be less than long delay!');
- this.isMobile = util.isMobileCordova() || util.isReactNative();
- }
- get() {
- if (!_isOnline()) {
- // Pick the shorter timeout.
- return Math.min(5000 /* DelayMin.OFFLINE */, this.shortDelay);
- }
- // If running in a mobile environment, return the long delay, otherwise
- // return the short delay.
- // This could be improved in the future to dynamically change based on other
- // variables instead of just reading the current environment.
- return this.isMobile ? this.longDelay : this.shortDelay;
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _emulatorUrl(config, path) {
- debugAssert(config.emulator, 'Emulator should always be set here');
- const { url } = config.emulator;
- if (!path) {
- return url;
- }
- return `${url}${path.startsWith('/') ? path.slice(1) : path}`;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class FetchProvider {
- static initialize(fetchImpl, headersImpl, responseImpl) {
- this.fetchImpl = fetchImpl;
- if (headersImpl) {
- this.headersImpl = headersImpl;
- }
- if (responseImpl) {
- this.responseImpl = responseImpl;
- }
- }
- static fetch() {
- if (this.fetchImpl) {
- return this.fetchImpl;
- }
- if (typeof self !== 'undefined' && 'fetch' in self) {
- return self.fetch;
- }
- debugFail('Could not find fetch implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
- }
- static headers() {
- if (this.headersImpl) {
- return this.headersImpl;
- }
- if (typeof self !== 'undefined' && 'Headers' in self) {
- return self.Headers;
- }
- debugFail('Could not find Headers implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
- }
- static response() {
- if (this.responseImpl) {
- return this.responseImpl;
- }
- if (typeof self !== 'undefined' && 'Response' in self) {
- return self.Response;
- }
- debugFail('Could not find Response implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Map from errors returned by the server to errors to developer visible errors
- */
- const SERVER_ERROR_MAP = {
- // Custom token errors.
- ["CREDENTIAL_MISMATCH" /* ServerError.CREDENTIAL_MISMATCH */]: "custom-token-mismatch" /* AuthErrorCode.CREDENTIAL_MISMATCH */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_CUSTOM_TOKEN" /* ServerError.MISSING_CUSTOM_TOKEN */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Create Auth URI errors.
- ["INVALID_IDENTIFIER" /* ServerError.INVALID_IDENTIFIER */]: "invalid-email" /* AuthErrorCode.INVALID_EMAIL */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_CONTINUE_URI" /* ServerError.MISSING_CONTINUE_URI */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Sign in with email and password errors (some apply to sign up too).
- ["INVALID_PASSWORD" /* ServerError.INVALID_PASSWORD */]: "wrong-password" /* AuthErrorCode.INVALID_PASSWORD */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_PASSWORD" /* ServerError.MISSING_PASSWORD */]: "missing-password" /* AuthErrorCode.MISSING_PASSWORD */,
- // Sign up with email and password errors.
- ["EMAIL_EXISTS" /* ServerError.EMAIL_EXISTS */]: "email-already-in-use" /* AuthErrorCode.EMAIL_EXISTS */,
- ["PASSWORD_LOGIN_DISABLED" /* ServerError.PASSWORD_LOGIN_DISABLED */]: "operation-not-allowed" /* AuthErrorCode.OPERATION_NOT_ALLOWED */,
- // Verify assertion for sign in with credential errors:
- ["INVALID_IDP_RESPONSE" /* ServerError.INVALID_IDP_RESPONSE */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
- ["INVALID_PENDING_TOKEN" /* ServerError.INVALID_PENDING_TOKEN */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
- ["FEDERATED_USER_ID_ALREADY_LINKED" /* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */]: "credential-already-in-use" /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_REQ_TYPE" /* ServerError.MISSING_REQ_TYPE */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Send Password reset email errors:
- ["EMAIL_NOT_FOUND" /* ServerError.EMAIL_NOT_FOUND */]: "user-not-found" /* AuthErrorCode.USER_DELETED */,
- ["RESET_PASSWORD_EXCEED_LIMIT" /* ServerError.RESET_PASSWORD_EXCEED_LIMIT */]: "too-many-requests" /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */,
- ["EXPIRED_OOB_CODE" /* ServerError.EXPIRED_OOB_CODE */]: "expired-action-code" /* AuthErrorCode.EXPIRED_OOB_CODE */,
- ["INVALID_OOB_CODE" /* ServerError.INVALID_OOB_CODE */]: "invalid-action-code" /* AuthErrorCode.INVALID_OOB_CODE */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_OOB_CODE" /* ServerError.MISSING_OOB_CODE */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Operations that require ID token in request:
- ["CREDENTIAL_TOO_OLD_LOGIN_AGAIN" /* ServerError.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */]: "requires-recent-login" /* AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */,
- ["INVALID_ID_TOKEN" /* ServerError.INVALID_ID_TOKEN */]: "invalid-user-token" /* AuthErrorCode.INVALID_AUTH */,
- ["TOKEN_EXPIRED" /* ServerError.TOKEN_EXPIRED */]: "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */,
- ["USER_NOT_FOUND" /* ServerError.USER_NOT_FOUND */]: "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */,
- // Other errors.
- ["TOO_MANY_ATTEMPTS_TRY_LATER" /* ServerError.TOO_MANY_ATTEMPTS_TRY_LATER */]: "too-many-requests" /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */,
- // Phone Auth related errors.
- ["INVALID_CODE" /* ServerError.INVALID_CODE */]: "invalid-verification-code" /* AuthErrorCode.INVALID_CODE */,
- ["INVALID_SESSION_INFO" /* ServerError.INVALID_SESSION_INFO */]: "invalid-verification-id" /* AuthErrorCode.INVALID_SESSION_INFO */,
- ["INVALID_TEMPORARY_PROOF" /* ServerError.INVALID_TEMPORARY_PROOF */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
- ["MISSING_SESSION_INFO" /* ServerError.MISSING_SESSION_INFO */]: "missing-verification-id" /* AuthErrorCode.MISSING_SESSION_INFO */,
- ["SESSION_EXPIRED" /* ServerError.SESSION_EXPIRED */]: "code-expired" /* AuthErrorCode.CODE_EXPIRED */,
- // Other action code errors when additional settings passed.
- // MISSING_CONTINUE_URI is getting mapped to INTERNAL_ERROR above.
- // This is OK as this error will be caught by client side validation.
- ["MISSING_ANDROID_PACKAGE_NAME" /* ServerError.MISSING_ANDROID_PACKAGE_NAME */]: "missing-android-pkg-name" /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */,
- ["UNAUTHORIZED_DOMAIN" /* ServerError.UNAUTHORIZED_DOMAIN */]: "unauthorized-continue-uri" /* AuthErrorCode.UNAUTHORIZED_DOMAIN */,
- // getProjectConfig errors when clientId is passed.
- ["INVALID_OAUTH_CLIENT_ID" /* ServerError.INVALID_OAUTH_CLIENT_ID */]: "invalid-oauth-client-id" /* AuthErrorCode.INVALID_OAUTH_CLIENT_ID */,
- // User actions (sign-up or deletion) disabled errors.
- ["ADMIN_ONLY_OPERATION" /* ServerError.ADMIN_ONLY_OPERATION */]: "admin-restricted-operation" /* AuthErrorCode.ADMIN_ONLY_OPERATION */,
- // Multi factor related errors.
- ["INVALID_MFA_PENDING_CREDENTIAL" /* ServerError.INVALID_MFA_PENDING_CREDENTIAL */]: "invalid-multi-factor-session" /* AuthErrorCode.INVALID_MFA_SESSION */,
- ["MFA_ENROLLMENT_NOT_FOUND" /* ServerError.MFA_ENROLLMENT_NOT_FOUND */]: "multi-factor-info-not-found" /* AuthErrorCode.MFA_INFO_NOT_FOUND */,
- ["MISSING_MFA_ENROLLMENT_ID" /* ServerError.MISSING_MFA_ENROLLMENT_ID */]: "missing-multi-factor-info" /* AuthErrorCode.MISSING_MFA_INFO */,
- ["MISSING_MFA_PENDING_CREDENTIAL" /* ServerError.MISSING_MFA_PENDING_CREDENTIAL */]: "missing-multi-factor-session" /* AuthErrorCode.MISSING_MFA_SESSION */,
- ["SECOND_FACTOR_EXISTS" /* ServerError.SECOND_FACTOR_EXISTS */]: "second-factor-already-in-use" /* AuthErrorCode.SECOND_FACTOR_ALREADY_ENROLLED */,
- ["SECOND_FACTOR_LIMIT_EXCEEDED" /* ServerError.SECOND_FACTOR_LIMIT_EXCEEDED */]: "maximum-second-factor-count-exceeded" /* AuthErrorCode.SECOND_FACTOR_LIMIT_EXCEEDED */,
- // Blocking functions related errors.
- ["BLOCKING_FUNCTION_ERROR_RESPONSE" /* ServerError.BLOCKING_FUNCTION_ERROR_RESPONSE */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Recaptcha related errors.
- ["RECAPTCHA_NOT_ENABLED" /* ServerError.RECAPTCHA_NOT_ENABLED */]: "recaptcha-not-enabled" /* AuthErrorCode.RECAPTCHA_NOT_ENABLED */,
- ["MISSING_RECAPTCHA_TOKEN" /* ServerError.MISSING_RECAPTCHA_TOKEN */]: "missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */,
- ["INVALID_RECAPTCHA_TOKEN" /* ServerError.INVALID_RECAPTCHA_TOKEN */]: "invalid-recaptcha-token" /* AuthErrorCode.INVALID_RECAPTCHA_TOKEN */,
- ["INVALID_RECAPTCHA_ACTION" /* ServerError.INVALID_RECAPTCHA_ACTION */]: "invalid-recaptcha-action" /* AuthErrorCode.INVALID_RECAPTCHA_ACTION */,
- ["MISSING_CLIENT_TYPE" /* ServerError.MISSING_CLIENT_TYPE */]: "missing-client-type" /* AuthErrorCode.MISSING_CLIENT_TYPE */,
- ["MISSING_RECAPTCHA_VERSION" /* ServerError.MISSING_RECAPTCHA_VERSION */]: "missing-recaptcha-version" /* AuthErrorCode.MISSING_RECAPTCHA_VERSION */,
- ["INVALID_RECAPTCHA_VERSION" /* ServerError.INVALID_RECAPTCHA_VERSION */]: "invalid-recaptcha-version" /* AuthErrorCode.INVALID_RECAPTCHA_VERSION */,
- ["INVALID_REQ_TYPE" /* ServerError.INVALID_REQ_TYPE */]: "invalid-req-type" /* AuthErrorCode.INVALID_REQ_TYPE */
- };
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DEFAULT_API_TIMEOUT_MS = new Delay(30000, 60000);
- function _addTidIfNecessary(auth, request) {
- if (auth.tenantId && !request.tenantId) {
- return Object.assign(Object.assign({}, request), { tenantId: auth.tenantId });
- }
- return request;
- }
- async function _performApiRequest(auth, method, path, request, customErrorMap = {}) {
- return _performFetchWithErrorHandling(auth, customErrorMap, async () => {
- let body = {};
- let params = {};
- if (request) {
- if (method === "GET" /* HttpMethod.GET */) {
- params = request;
- }
- else {
- body = {
- body: JSON.stringify(request)
- };
- }
- }
- const query = util.querystring(Object.assign({ key: auth.config.apiKey }, params)).slice(1);
- const headers = await auth._getAdditionalHeaders();
- headers["Content-Type" /* HttpHeader.CONTENT_TYPE */] = 'application/json';
- if (auth.languageCode) {
- headers["X-Firebase-Locale" /* HttpHeader.X_FIREBASE_LOCALE */] = auth.languageCode;
- }
- return FetchProvider.fetch()(_getFinalTarget(auth, auth.config.apiHost, path, query), Object.assign({ method,
- headers, referrerPolicy: 'no-referrer' }, body));
- });
- }
- async function _performFetchWithErrorHandling(auth, customErrorMap, fetchFn) {
- auth._canInitEmulator = false;
- const errorMap = Object.assign(Object.assign({}, SERVER_ERROR_MAP), customErrorMap);
- try {
- const networkTimeout = new NetworkTimeout(auth);
- const response = await Promise.race([
- fetchFn(),
- networkTimeout.promise
- ]);
- // If we've reached this point, the fetch succeeded and the networkTimeout
- // didn't throw; clear the network timeout delay so that Node won't hang
- networkTimeout.clearNetworkTimeout();
- const json = await response.json();
- if ('needConfirmation' in json) {
- throw _makeTaggedError(auth, "account-exists-with-different-credential" /* AuthErrorCode.NEED_CONFIRMATION */, json);
- }
- if (response.ok && !('errorMessage' in json)) {
- return json;
- }
- else {
- const errorMessage = response.ok ? json.errorMessage : json.error.message;
- const [serverErrorCode, serverErrorMessage] = errorMessage.split(' : ');
- if (serverErrorCode === "FEDERATED_USER_ID_ALREADY_LINKED" /* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */) {
- throw _makeTaggedError(auth, "credential-already-in-use" /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */, json);
- }
- else if (serverErrorCode === "EMAIL_EXISTS" /* ServerError.EMAIL_EXISTS */) {
- throw _makeTaggedError(auth, "email-already-in-use" /* AuthErrorCode.EMAIL_EXISTS */, json);
- }
- else if (serverErrorCode === "USER_DISABLED" /* ServerError.USER_DISABLED */) {
- throw _makeTaggedError(auth, "user-disabled" /* AuthErrorCode.USER_DISABLED */, json);
- }
- const authError = errorMap[serverErrorCode] ||
- serverErrorCode
- .toLowerCase()
- .replace(/[_\s]+/g, '-');
- if (serverErrorMessage) {
- throw _errorWithCustomMessage(auth, authError, serverErrorMessage);
- }
- else {
- _fail(auth, authError);
- }
- }
- }
- catch (e) {
- if (e instanceof util.FirebaseError) {
- throw e;
- }
- // Changing this to a different error code will log user out when there is a network error
- // because we treat any error other than NETWORK_REQUEST_FAILED as token is invalid.
- // https://github.com/firebase/firebase-js-sdk/blob/4fbc73610d70be4e0852e7de63a39cb7897e8546/packages/auth/src/core/auth/auth_impl.ts#L309-L316
- _fail(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */, { 'message': String(e) });
- }
- }
- async function _performSignInRequest(auth, method, path, request, customErrorMap = {}) {
- const serverResponse = (await _performApiRequest(auth, method, path, request, customErrorMap));
- if ('mfaPendingCredential' in serverResponse) {
- _fail(auth, "multi-factor-auth-required" /* AuthErrorCode.MFA_REQUIRED */, {
- _serverResponse: serverResponse
- });
- }
- return serverResponse;
- }
- function _getFinalTarget(auth, host, path, query) {
- const base = `${host}${path}?${query}`;
- if (!auth.config.emulator) {
- return `${auth.config.apiScheme}://${base}`;
- }
- return _emulatorUrl(auth.config, base);
- }
- class NetworkTimeout {
- constructor(auth) {
- this.auth = auth;
- // Node timers and browser timers are fundamentally incompatible, but we
- // don't care about the value here
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.timer = null;
- this.promise = new Promise((_, reject) => {
- this.timer = setTimeout(() => {
- return reject(_createError(this.auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */));
- }, DEFAULT_API_TIMEOUT_MS.get());
- });
- }
- clearNetworkTimeout() {
- clearTimeout(this.timer);
- }
- }
- function _makeTaggedError(auth, code, response) {
- const errorParams = {
- appName: auth.name
- };
- if (response.email) {
- errorParams.email = response.email;
- }
- if (response.phoneNumber) {
- errorParams.phoneNumber = response.phoneNumber;
- }
- const error = _createError(auth, code, errorParams);
- // We know customData is defined on error because errorParams is defined
- error.customData._tokenResponse = response;
- return error;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function deleteAccount(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:delete" /* Endpoint.DELETE_ACCOUNT */, request);
- }
- async function deleteLinkedAccounts(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, request);
- }
- async function getAccountInfo(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:lookup" /* Endpoint.GET_ACCOUNT_INFO */, request);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function utcTimestampToDateString(utcTimestamp) {
- if (!utcTimestamp) {
- return undefined;
- }
- try {
- // Convert to date object.
- const date = new Date(Number(utcTimestamp));
- // Test date is valid.
- if (!isNaN(date.getTime())) {
- // Convert to UTC date string.
- return date.toUTCString();
- }
- }
- catch (e) {
- // Do nothing. undefined will be returned.
- }
- return undefined;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service.
- *
- * @remarks
- * Returns the current token if it has not expired or if it will not expire in the next five
- * minutes. Otherwise, this will refresh the token and return a new one.
- *
- * @param user - The user.
- * @param forceRefresh - Force refresh regardless of token expiration.
- *
- * @public
- */
- function getIdToken(user, forceRefresh = false) {
- return util.getModularInstance(user).getIdToken(forceRefresh);
- }
- /**
- * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service.
- *
- * @remarks
- * Returns the current token if it has not expired or if it will not expire in the next five
- * minutes. Otherwise, this will refresh the token and return a new one.
- *
- * @param user - The user.
- * @param forceRefresh - Force refresh regardless of token expiration.
- *
- * @public
- */
- async function getIdTokenResult(user, forceRefresh = false) {
- const userInternal = util.getModularInstance(user);
- const token = await userInternal.getIdToken(forceRefresh);
- const claims = _parseToken(token);
- _assert(claims && claims.exp && claims.auth_time && claims.iat, userInternal.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const firebase = typeof claims.firebase === 'object' ? claims.firebase : undefined;
- const signInProvider = firebase === null || firebase === void 0 ? void 0 : firebase['sign_in_provider'];
- return {
- claims,
- token,
- authTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.auth_time)),
- issuedAtTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.iat)),
- expirationTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.exp)),
- signInProvider: signInProvider || null,
- signInSecondFactor: (firebase === null || firebase === void 0 ? void 0 : firebase['sign_in_second_factor']) || null
- };
- }
- function secondsStringToMilliseconds(seconds) {
- return Number(seconds) * 1000;
- }
- function _parseToken(token) {
- const [algorithm, payload, signature] = token.split('.');
- if (algorithm === undefined ||
- payload === undefined ||
- signature === undefined) {
- _logError('JWT malformed, contained fewer than 3 sections');
- return null;
- }
- try {
- const decoded = util.base64Decode(payload);
- if (!decoded) {
- _logError('Failed to decode base64 JWT payload');
- return null;
- }
- return JSON.parse(decoded);
- }
- catch (e) {
- _logError('Caught error parsing JWT payload as JSON', e === null || e === void 0 ? void 0 : e.toString());
- return null;
- }
- }
- /**
- * Extract expiresIn TTL from a token by subtracting the expiration from the issuance.
- */
- function _tokenExpiresIn(token) {
- const parsedToken = _parseToken(token);
- _assert(parsedToken, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert(typeof parsedToken.exp !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert(typeof parsedToken.iat !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return Number(parsedToken.exp) - Number(parsedToken.iat);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _logoutIfInvalidated(user, promise, bypassAuthState = false) {
- if (bypassAuthState) {
- return promise;
- }
- try {
- return await promise;
- }
- catch (e) {
- if (e instanceof util.FirebaseError && isUserInvalidated(e)) {
- if (user.auth.currentUser === user) {
- await user.auth.signOut();
- }
- }
- throw e;
- }
- }
- function isUserInvalidated({ code }) {
- return (code === `auth/${"user-disabled" /* AuthErrorCode.USER_DISABLED */}` ||
- code === `auth/${"user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */}`);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class ProactiveRefresh {
- constructor(user) {
- this.user = user;
- this.isRunning = false;
- // Node timers and browser timers return fundamentally different types.
- // We don't actually care what the value is but TS won't accept unknown and
- // we can't cast properly in both environments.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.timerId = null;
- this.errorBackoff = 30000 /* Duration.RETRY_BACKOFF_MIN */;
- }
- _start() {
- if (this.isRunning) {
- return;
- }
- this.isRunning = true;
- this.schedule();
- }
- _stop() {
- if (!this.isRunning) {
- return;
- }
- this.isRunning = false;
- if (this.timerId !== null) {
- clearTimeout(this.timerId);
- }
- }
- getInterval(wasError) {
- var _a;
- if (wasError) {
- const interval = this.errorBackoff;
- this.errorBackoff = Math.min(this.errorBackoff * 2, 960000 /* Duration.RETRY_BACKOFF_MAX */);
- return interval;
- }
- else {
- // Reset the error backoff
- this.errorBackoff = 30000 /* Duration.RETRY_BACKOFF_MIN */;
- const expTime = (_a = this.user.stsTokenManager.expirationTime) !== null && _a !== void 0 ? _a : 0;
- const interval = expTime - Date.now() - 300000 /* Duration.OFFSET */;
- return Math.max(0, interval);
- }
- }
- schedule(wasError = false) {
- if (!this.isRunning) {
- // Just in case...
- return;
- }
- const interval = this.getInterval(wasError);
- this.timerId = setTimeout(async () => {
- await this.iteration();
- }, interval);
- }
- async iteration() {
- try {
- await this.user.getIdToken(true);
- }
- catch (e) {
- // Only retry on network errors
- if ((e === null || e === void 0 ? void 0 : e.code) ===
- `auth/${"network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */}`) {
- this.schedule(/* wasError */ true);
- }
- return;
- }
- this.schedule();
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class UserMetadata {
- constructor(createdAt, lastLoginAt) {
- this.createdAt = createdAt;
- this.lastLoginAt = lastLoginAt;
- this._initializeTime();
- }
- _initializeTime() {
- this.lastSignInTime = utcTimestampToDateString(this.lastLoginAt);
- this.creationTime = utcTimestampToDateString(this.createdAt);
- }
- _copy(metadata) {
- this.createdAt = metadata.createdAt;
- this.lastLoginAt = metadata.lastLoginAt;
- this._initializeTime();
- }
- toJSON() {
- return {
- createdAt: this.createdAt,
- lastLoginAt: this.lastLoginAt
- };
- }
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _reloadWithoutSaving(user) {
- var _a;
- const auth = user.auth;
- const idToken = await user.getIdToken();
- const response = await _logoutIfInvalidated(user, getAccountInfo(auth, { idToken }));
- _assert(response === null || response === void 0 ? void 0 : response.users.length, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const coreAccount = response.users[0];
- user._notifyReloadListener(coreAccount);
- const newProviderData = ((_a = coreAccount.providerUserInfo) === null || _a === void 0 ? void 0 : _a.length)
- ? extractProviderData(coreAccount.providerUserInfo)
- : [];
- const providerData = mergeProviderData(user.providerData, newProviderData);
- // Preserves the non-nonymous status of the stored user, even if no more
- // credentials (federated or email/password) are linked to the user. If
- // the user was previously anonymous, then use provider data to update.
- // On the other hand, if it was not anonymous before, it should never be
- // considered anonymous now.
- const oldIsAnonymous = user.isAnonymous;
- const newIsAnonymous = !(user.email && coreAccount.passwordHash) && !(providerData === null || providerData === void 0 ? void 0 : providerData.length);
- const isAnonymous = !oldIsAnonymous ? false : newIsAnonymous;
- const updates = {
- uid: coreAccount.localId,
- displayName: coreAccount.displayName || null,
- photoURL: coreAccount.photoUrl || null,
- email: coreAccount.email || null,
- emailVerified: coreAccount.emailVerified || false,
- phoneNumber: coreAccount.phoneNumber || null,
- tenantId: coreAccount.tenantId || null,
- providerData,
- metadata: new UserMetadata(coreAccount.createdAt, coreAccount.lastLoginAt),
- isAnonymous
- };
- Object.assign(user, updates);
- }
- /**
- * Reloads user account data, if signed in.
- *
- * @param user - The user.
- *
- * @public
- */
- async function reload(user) {
- const userInternal = util.getModularInstance(user);
- await _reloadWithoutSaving(userInternal);
- // Even though the current user hasn't changed, update
- // current user will trigger a persistence update w/ the
- // new info.
- await userInternal.auth._persistUserIfCurrent(userInternal);
- userInternal.auth._notifyListenersIfCurrent(userInternal);
- }
- function mergeProviderData(original, newData) {
- const deduped = original.filter(o => !newData.some(n => n.providerId === o.providerId));
- return [...deduped, ...newData];
- }
- function extractProviderData(providers) {
- return providers.map((_a) => {
- var { providerId } = _a, provider = tslib.__rest(_a, ["providerId"]);
- return {
- providerId,
- uid: provider.rawId || '',
- displayName: provider.displayName || null,
- email: provider.email || null,
- phoneNumber: provider.phoneNumber || null,
- photoURL: provider.photoUrl || null
- };
- });
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function requestStsToken(auth, refreshToken) {
- const response = await _performFetchWithErrorHandling(auth, {}, async () => {
- const body = util.querystring({
- 'grant_type': 'refresh_token',
- 'refresh_token': refreshToken
- }).slice(1);
- const { tokenApiHost, apiKey } = auth.config;
- const url = _getFinalTarget(auth, tokenApiHost, "/v1/token" /* Endpoint.TOKEN */, `key=${apiKey}`);
- const headers = await auth._getAdditionalHeaders();
- headers["Content-Type" /* HttpHeader.CONTENT_TYPE */] = 'application/x-www-form-urlencoded';
- return FetchProvider.fetch()(url, {
- method: "POST" /* HttpMethod.POST */,
- headers,
- body
- });
- });
- // The response comes back in snake_case. Convert to camel:
- return {
- accessToken: response.access_token,
- expiresIn: response.expires_in,
- refreshToken: response.refresh_token
- };
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * We need to mark this class as internal explicitly to exclude it in the public typings, because
- * it references AuthInternal which has a circular dependency with UserInternal.
- *
- * @internal
- */
- class StsTokenManager {
- constructor() {
- this.refreshToken = null;
- this.accessToken = null;
- this.expirationTime = null;
- }
- get isExpired() {
- return (!this.expirationTime ||
- Date.now() > this.expirationTime - 30000 /* Buffer.TOKEN_REFRESH */);
- }
- updateFromServerResponse(response) {
- _assert(response.idToken, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert(typeof response.idToken !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert(typeof response.refreshToken !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const expiresIn = 'expiresIn' in response && typeof response.expiresIn !== 'undefined'
- ? Number(response.expiresIn)
- : _tokenExpiresIn(response.idToken);
- this.updateTokensAndExpiration(response.idToken, response.refreshToken, expiresIn);
- }
- async getToken(auth, forceRefresh = false) {
- _assert(!this.accessToken || this.refreshToken, auth, "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */);
- if (!forceRefresh && this.accessToken && !this.isExpired) {
- return this.accessToken;
- }
- if (this.refreshToken) {
- await this.refresh(auth, this.refreshToken);
- return this.accessToken;
- }
- return null;
- }
- clearRefreshToken() {
- this.refreshToken = null;
- }
- async refresh(auth, oldToken) {
- const { accessToken, refreshToken, expiresIn } = await requestStsToken(auth, oldToken);
- this.updateTokensAndExpiration(accessToken, refreshToken, Number(expiresIn));
- }
- updateTokensAndExpiration(accessToken, refreshToken, expiresInSec) {
- this.refreshToken = refreshToken || null;
- this.accessToken = accessToken || null;
- this.expirationTime = Date.now() + expiresInSec * 1000;
- }
- static fromJSON(appName, object) {
- const { refreshToken, accessToken, expirationTime } = object;
- const manager = new StsTokenManager();
- if (refreshToken) {
- _assert(typeof refreshToken === 'string', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */, {
- appName
- });
- manager.refreshToken = refreshToken;
- }
- if (accessToken) {
- _assert(typeof accessToken === 'string', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */, {
- appName
- });
- manager.accessToken = accessToken;
- }
- if (expirationTime) {
- _assert(typeof expirationTime === 'number', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */, {
- appName
- });
- manager.expirationTime = expirationTime;
- }
- return manager;
- }
- toJSON() {
- return {
- refreshToken: this.refreshToken,
- accessToken: this.accessToken,
- expirationTime: this.expirationTime
- };
- }
- _assign(stsTokenManager) {
- this.accessToken = stsTokenManager.accessToken;
- this.refreshToken = stsTokenManager.refreshToken;
- this.expirationTime = stsTokenManager.expirationTime;
- }
- _clone() {
- return Object.assign(new StsTokenManager(), this.toJSON());
- }
- _performRefresh() {
- return debugFail('not implemented');
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function assertStringOrUndefined(assertion, appName) {
- _assert(typeof assertion === 'string' || typeof assertion === 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */, { appName });
- }
- class UserImpl {
- constructor(_a) {
- var { uid, auth, stsTokenManager } = _a, opt = tslib.__rest(_a, ["uid", "auth", "stsTokenManager"]);
- // For the user object, provider is always Firebase.
- this.providerId = "firebase" /* ProviderId.FIREBASE */;
- this.proactiveRefresh = new ProactiveRefresh(this);
- this.reloadUserInfo = null;
- this.reloadListener = null;
- this.uid = uid;
- this.auth = auth;
- this.stsTokenManager = stsTokenManager;
- this.accessToken = stsTokenManager.accessToken;
- this.displayName = opt.displayName || null;
- this.email = opt.email || null;
- this.emailVerified = opt.emailVerified || false;
- this.phoneNumber = opt.phoneNumber || null;
- this.photoURL = opt.photoURL || null;
- this.isAnonymous = opt.isAnonymous || false;
- this.tenantId = opt.tenantId || null;
- this.providerData = opt.providerData ? [...opt.providerData] : [];
- this.metadata = new UserMetadata(opt.createdAt || undefined, opt.lastLoginAt || undefined);
- }
- async getIdToken(forceRefresh) {
- const accessToken = await _logoutIfInvalidated(this, this.stsTokenManager.getToken(this.auth, forceRefresh));
- _assert(accessToken, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- if (this.accessToken !== accessToken) {
- this.accessToken = accessToken;
- await this.auth._persistUserIfCurrent(this);
- this.auth._notifyListenersIfCurrent(this);
- }
- return accessToken;
- }
- getIdTokenResult(forceRefresh) {
- return getIdTokenResult(this, forceRefresh);
- }
- reload() {
- return reload(this);
- }
- _assign(user) {
- if (this === user) {
- return;
- }
- _assert(this.uid === user.uid, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- this.displayName = user.displayName;
- this.photoURL = user.photoURL;
- this.email = user.email;
- this.emailVerified = user.emailVerified;
- this.phoneNumber = user.phoneNumber;
- this.isAnonymous = user.isAnonymous;
- this.tenantId = user.tenantId;
- this.providerData = user.providerData.map(userInfo => (Object.assign({}, userInfo)));
- this.metadata._copy(user.metadata);
- this.stsTokenManager._assign(user.stsTokenManager);
- }
- _clone(auth) {
- const newUser = new UserImpl(Object.assign(Object.assign({}, this), { auth, stsTokenManager: this.stsTokenManager._clone() }));
- newUser.metadata._copy(this.metadata);
- return newUser;
- }
- _onReload(callback) {
- // There should only ever be one listener, and that is a single instance of MultiFactorUser
- _assert(!this.reloadListener, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- this.reloadListener = callback;
- if (this.reloadUserInfo) {
- this._notifyReloadListener(this.reloadUserInfo);
- this.reloadUserInfo = null;
- }
- }
- _notifyReloadListener(userInfo) {
- if (this.reloadListener) {
- this.reloadListener(userInfo);
- }
- else {
- // If no listener is subscribed yet, save the result so it's available when they do subscribe
- this.reloadUserInfo = userInfo;
- }
- }
- _startProactiveRefresh() {
- this.proactiveRefresh._start();
- }
- _stopProactiveRefresh() {
- this.proactiveRefresh._stop();
- }
- async _updateTokensIfNecessary(response, reload = false) {
- let tokensRefreshed = false;
- if (response.idToken &&
- response.idToken !== this.stsTokenManager.accessToken) {
- this.stsTokenManager.updateFromServerResponse(response);
- tokensRefreshed = true;
- }
- if (reload) {
- await _reloadWithoutSaving(this);
- }
- await this.auth._persistUserIfCurrent(this);
- if (tokensRefreshed) {
- this.auth._notifyListenersIfCurrent(this);
- }
- }
- async delete() {
- const idToken = await this.getIdToken();
- await _logoutIfInvalidated(this, deleteAccount(this.auth, { idToken }));
- this.stsTokenManager.clearRefreshToken();
- // TODO: Determine if cancellable-promises are necessary to use in this class so that delete()
- // cancels pending actions...
- return this.auth.signOut();
- }
- toJSON() {
- return Object.assign(Object.assign({ uid: this.uid, email: this.email || undefined, emailVerified: this.emailVerified, displayName: this.displayName || undefined, isAnonymous: this.isAnonymous, photoURL: this.photoURL || undefined, phoneNumber: this.phoneNumber || undefined, tenantId: this.tenantId || undefined, providerData: this.providerData.map(userInfo => (Object.assign({}, userInfo))), stsTokenManager: this.stsTokenManager.toJSON(),
- // Redirect event ID must be maintained in case there is a pending
- // redirect event.
- _redirectEventId: this._redirectEventId }, this.metadata.toJSON()), {
- // Required for compatibility with the legacy SDK (go/firebase-auth-sdk-persistence-parsing):
- apiKey: this.auth.config.apiKey, appName: this.auth.name });
- }
- get refreshToken() {
- return this.stsTokenManager.refreshToken || '';
- }
- static _fromJSON(auth, object) {
- var _a, _b, _c, _d, _e, _f, _g, _h;
- const displayName = (_a = object.displayName) !== null && _a !== void 0 ? _a : undefined;
- const email = (_b = object.email) !== null && _b !== void 0 ? _b : undefined;
- const phoneNumber = (_c = object.phoneNumber) !== null && _c !== void 0 ? _c : undefined;
- const photoURL = (_d = object.photoURL) !== null && _d !== void 0 ? _d : undefined;
- const tenantId = (_e = object.tenantId) !== null && _e !== void 0 ? _e : undefined;
- const _redirectEventId = (_f = object._redirectEventId) !== null && _f !== void 0 ? _f : undefined;
- const createdAt = (_g = object.createdAt) !== null && _g !== void 0 ? _g : undefined;
- const lastLoginAt = (_h = object.lastLoginAt) !== null && _h !== void 0 ? _h : undefined;
- const { uid, emailVerified, isAnonymous, providerData, stsTokenManager: plainObjectTokenManager } = object;
- _assert(uid && plainObjectTokenManager, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const stsTokenManager = StsTokenManager.fromJSON(this.name, plainObjectTokenManager);
- _assert(typeof uid === 'string', auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- assertStringOrUndefined(displayName, auth.name);
- assertStringOrUndefined(email, auth.name);
- _assert(typeof emailVerified === 'boolean', auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert(typeof isAnonymous === 'boolean', auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- assertStringOrUndefined(phoneNumber, auth.name);
- assertStringOrUndefined(photoURL, auth.name);
- assertStringOrUndefined(tenantId, auth.name);
- assertStringOrUndefined(_redirectEventId, auth.name);
- assertStringOrUndefined(createdAt, auth.name);
- assertStringOrUndefined(lastLoginAt, auth.name);
- const user = new UserImpl({
- uid,
- auth,
- email,
- emailVerified,
- displayName,
- isAnonymous,
- photoURL,
- phoneNumber,
- tenantId,
- stsTokenManager,
- createdAt,
- lastLoginAt
- });
- if (providerData && Array.isArray(providerData)) {
- user.providerData = providerData.map(userInfo => (Object.assign({}, userInfo)));
- }
- if (_redirectEventId) {
- user._redirectEventId = _redirectEventId;
- }
- return user;
- }
- /**
- * Initialize a User from an idToken server response
- * @param auth
- * @param idTokenResponse
- */
- static async _fromIdTokenResponse(auth, idTokenResponse, isAnonymous = false) {
- const stsTokenManager = new StsTokenManager();
- stsTokenManager.updateFromServerResponse(idTokenResponse);
- // Initialize the Firebase Auth user.
- const user = new UserImpl({
- uid: idTokenResponse.localId,
- auth,
- stsTokenManager,
- isAnonymous
- });
- // Updates the user info and data and resolves with a user instance.
- await _reloadWithoutSaving(user);
- return user;
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const instanceCache = new Map();
- function _getInstance(cls) {
- debugAssert(cls instanceof Function, 'Expected a class definition');
- let instance = instanceCache.get(cls);
- if (instance) {
- debugAssert(instance instanceof cls, 'Instance stored in cache mismatched with class');
- return instance;
- }
- instance = new cls();
- instanceCache.set(cls, instance);
- return instance;
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class InMemoryPersistence {
- constructor() {
- this.type = "NONE" /* PersistenceType.NONE */;
- this.storage = {};
- }
- async _isAvailable() {
- return true;
- }
- async _set(key, value) {
- this.storage[key] = value;
- }
- async _get(key) {
- const value = this.storage[key];
- return value === undefined ? null : value;
- }
- async _remove(key) {
- delete this.storage[key];
- }
- _addListener(_key, _listener) {
- // Listeners are not supported for in-memory storage since it cannot be shared across windows/workers
- return;
- }
- _removeListener(_key, _listener) {
- // Listeners are not supported for in-memory storage since it cannot be shared across windows/workers
- return;
- }
- }
- InMemoryPersistence.type = 'NONE';
- /**
- * An implementation of {@link Persistence} of type 'NONE'.
- *
- * @public
- */
- const inMemoryPersistence = InMemoryPersistence;
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _persistenceKeyName(key, apiKey, appName) {
- return `${"firebase" /* Namespace.PERSISTENCE */}:${key}:${apiKey}:${appName}`;
- }
- class PersistenceUserManager {
- constructor(persistence, auth, userKey) {
- this.persistence = persistence;
- this.auth = auth;
- this.userKey = userKey;
- const { config, name } = this.auth;
- this.fullUserKey = _persistenceKeyName(this.userKey, config.apiKey, name);
- this.fullPersistenceKey = _persistenceKeyName("persistence" /* KeyName.PERSISTENCE_USER */, config.apiKey, name);
- this.boundEventHandler = auth._onStorageEvent.bind(auth);
- this.persistence._addListener(this.fullUserKey, this.boundEventHandler);
- }
- setCurrentUser(user) {
- return this.persistence._set(this.fullUserKey, user.toJSON());
- }
- async getCurrentUser() {
- const blob = await this.persistence._get(this.fullUserKey);
- return blob ? UserImpl._fromJSON(this.auth, blob) : null;
- }
- removeCurrentUser() {
- return this.persistence._remove(this.fullUserKey);
- }
- savePersistenceForRedirect() {
- return this.persistence._set(this.fullPersistenceKey, this.persistence.type);
- }
- async setPersistence(newPersistence) {
- if (this.persistence === newPersistence) {
- return;
- }
- const currentUser = await this.getCurrentUser();
- await this.removeCurrentUser();
- this.persistence = newPersistence;
- if (currentUser) {
- return this.setCurrentUser(currentUser);
- }
- }
- delete() {
- this.persistence._removeListener(this.fullUserKey, this.boundEventHandler);
- }
- static async create(auth, persistenceHierarchy, userKey = "authUser" /* KeyName.AUTH_USER */) {
- if (!persistenceHierarchy.length) {
- return new PersistenceUserManager(_getInstance(inMemoryPersistence), auth, userKey);
- }
- // Eliminate any persistences that are not available
- const availablePersistences = (await Promise.all(persistenceHierarchy.map(async (persistence) => {
- if (await persistence._isAvailable()) {
- return persistence;
- }
- return undefined;
- }))).filter(persistence => persistence);
- // Fall back to the first persistence listed, or in memory if none available
- let selectedPersistence = availablePersistences[0] ||
- _getInstance(inMemoryPersistence);
- const key = _persistenceKeyName(userKey, auth.config.apiKey, auth.name);
- // Pull out the existing user, setting the chosen persistence to that
- // persistence if the user exists.
- let userToMigrate = null;
- // Note, here we check for a user in _all_ persistences, not just the
- // ones deemed available. If we can migrate a user out of a broken
- // persistence, we will (but only if that persistence supports migration).
- for (const persistence of persistenceHierarchy) {
- try {
- const blob = await persistence._get(key);
- if (blob) {
- const user = UserImpl._fromJSON(auth, blob); // throws for unparsable blob (wrong format)
- if (persistence !== selectedPersistence) {
- userToMigrate = user;
- }
- selectedPersistence = persistence;
- break;
- }
- }
- catch (_a) { }
- }
- // If we find the user in a persistence that does support migration, use
- // that migration path (of only persistences that support migration)
- const migrationHierarchy = availablePersistences.filter(p => p._shouldAllowMigration);
- // If the persistence does _not_ allow migration, just finish off here
- if (!selectedPersistence._shouldAllowMigration ||
- !migrationHierarchy.length) {
- return new PersistenceUserManager(selectedPersistence, auth, userKey);
- }
- selectedPersistence = migrationHierarchy[0];
- if (userToMigrate) {
- // This normally shouldn't throw since chosenPersistence.isAvailable() is true, but if it does
- // we'll just let it bubble to surface the error.
- await selectedPersistence._set(key, userToMigrate.toJSON());
- }
- // Attempt to clear the key in other persistences but ignore errors. This helps prevent issues
- // such as users getting stuck with a previous account after signing out and refreshing the tab.
- await Promise.all(persistenceHierarchy.map(async (persistence) => {
- if (persistence !== selectedPersistence) {
- try {
- await persistence._remove(key);
- }
- catch (_a) { }
- }
- }));
- return new PersistenceUserManager(selectedPersistence, auth, userKey);
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Determine the browser for the purposes of reporting usage to the API
- */
- function _getBrowserName(userAgent) {
- const ua = userAgent.toLowerCase();
- if (ua.includes('opera/') || ua.includes('opr/') || ua.includes('opios/')) {
- return "Opera" /* BrowserName.OPERA */;
- }
- else if (_isIEMobile(ua)) {
- // Windows phone IEMobile browser.
- return "IEMobile" /* BrowserName.IEMOBILE */;
- }
- else if (ua.includes('msie') || ua.includes('trident/')) {
- return "IE" /* BrowserName.IE */;
- }
- else if (ua.includes('edge/')) {
- return "Edge" /* BrowserName.EDGE */;
- }
- else if (_isFirefox(ua)) {
- return "Firefox" /* BrowserName.FIREFOX */;
- }
- else if (ua.includes('silk/')) {
- return "Silk" /* BrowserName.SILK */;
- }
- else if (_isBlackBerry(ua)) {
- // Blackberry browser.
- return "Blackberry" /* BrowserName.BLACKBERRY */;
- }
- else if (_isWebOS(ua)) {
- // WebOS default browser.
- return "Webos" /* BrowserName.WEBOS */;
- }
- else if (_isSafari(ua)) {
- return "Safari" /* BrowserName.SAFARI */;
- }
- else if ((ua.includes('chrome/') || _isChromeIOS(ua)) &&
- !ua.includes('edge/')) {
- return "Chrome" /* BrowserName.CHROME */;
- }
- else if (_isAndroid(ua)) {
- // Android stock browser.
- return "Android" /* BrowserName.ANDROID */;
- }
- else {
- // Most modern browsers have name/version at end of user agent string.
- const re = /([a-zA-Z\d\.]+)\/[a-zA-Z\d\.]*$/;
- const matches = userAgent.match(re);
- if ((matches === null || matches === void 0 ? void 0 : matches.length) === 2) {
- return matches[1];
- }
- }
- return "Other" /* BrowserName.OTHER */;
- }
- function _isFirefox(ua = util.getUA()) {
- return /firefox\//i.test(ua);
- }
- function _isSafari(userAgent = util.getUA()) {
- const ua = userAgent.toLowerCase();
- return (ua.includes('safari/') &&
- !ua.includes('chrome/') &&
- !ua.includes('crios/') &&
- !ua.includes('android'));
- }
- function _isChromeIOS(ua = util.getUA()) {
- return /crios\//i.test(ua);
- }
- function _isIEMobile(ua = util.getUA()) {
- return /iemobile/i.test(ua);
- }
- function _isAndroid(ua = util.getUA()) {
- return /android/i.test(ua);
- }
- function _isBlackBerry(ua = util.getUA()) {
- return /blackberry/i.test(ua);
- }
- function _isWebOS(ua = util.getUA()) {
- return /webos/i.test(ua);
- }
- function _isIOS(ua = util.getUA()) {
- return (/iphone|ipad|ipod/i.test(ua) ||
- (/macintosh/i.test(ua) && /mobile/i.test(ua)));
- }
- function _isIOS7Or8(ua = util.getUA()) {
- return (/(iPad|iPhone|iPod).*OS 7_\d/i.test(ua) ||
- /(iPad|iPhone|iPod).*OS 8_\d/i.test(ua));
- }
- function _isIOSStandalone(ua = util.getUA()) {
- var _a;
- return _isIOS(ua) && !!((_a = window.navigator) === null || _a === void 0 ? void 0 : _a.standalone);
- }
- function _isIE10() {
- return util.isIE() && document.documentMode === 10;
- }
- function _isMobileBrowser(ua = util.getUA()) {
- // TODO: implement getBrowserName equivalent for OS.
- return (_isIOS(ua) ||
- _isAndroid(ua) ||
- _isWebOS(ua) ||
- _isBlackBerry(ua) ||
- /windows phone/i.test(ua) ||
- _isIEMobile(ua));
- }
- function _isIframe() {
- try {
- // Check that the current window is not the top window.
- // If so, return true.
- return !!(window && window !== window.top);
- }
- catch (e) {
- return false;
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * Determine the SDK version string
- */
- function _getClientVersion(clientPlatform, frameworks = []) {
- let reportedPlatform;
- switch (clientPlatform) {
- case "Browser" /* ClientPlatform.BROWSER */:
- // In a browser environment, report the browser name.
- reportedPlatform = _getBrowserName(util.getUA());
- break;
- case "Worker" /* ClientPlatform.WORKER */:
- // Technically a worker runs from a browser but we need to differentiate a
- // worker from a browser.
- // For example: Chrome-Worker/JsCore/4.9.1/FirebaseCore-web.
- reportedPlatform = `${_getBrowserName(util.getUA())}-${clientPlatform}`;
- break;
- default:
- reportedPlatform = clientPlatform;
- }
- const reportedFrameworks = frameworks.length
- ? frameworks.join(',')
- : 'FirebaseCore-web'; /* default value if no other framework is used */
- return `${reportedPlatform}/${"JsCore" /* ClientImplementation.CORE */}/${app.SDK_VERSION}/${reportedFrameworks}`;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function getRecaptchaParams(auth) {
- return ((await _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v1/recaptchaParams" /* Endpoint.GET_RECAPTCHA_PARAM */)).recaptchaSiteKey || '');
- }
- async function getRecaptchaConfig(auth, request) {
- return _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v2/recaptchaConfig" /* Endpoint.GET_RECAPTCHA_CONFIG */, _addTidIfNecessary(auth, request));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function isV2(grecaptcha) {
- return (grecaptcha !== undefined &&
- grecaptcha.getResponse !== undefined);
- }
- function isEnterprise(grecaptcha) {
- return (grecaptcha !== undefined &&
- grecaptcha.enterprise !== undefined);
- }
- class RecaptchaConfig {
- constructor(response) {
- /**
- * The reCAPTCHA site key.
- */
- this.siteKey = '';
- /**
- * The reCAPTCHA enablement status of the {@link EmailAuthProvider} for the current tenant.
- */
- this.emailPasswordEnabled = false;
- if (response.recaptchaKey === undefined) {
- throw new Error('recaptchaKey undefined');
- }
- // Example response.recaptchaKey: "projects/proj123/keys/sitekey123"
- this.siteKey = response.recaptchaKey.split('/')[3];
- this.emailPasswordEnabled = response.recaptchaEnforcementState.some(enforcementState => enforcementState.provider === 'EMAIL_PASSWORD_PROVIDER' &&
- enforcementState.enforcementState !== 'OFF');
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function getScriptParentElement() {
- var _a, _b;
- return (_b = (_a = document.getElementsByTagName('head')) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : document;
- }
- function _loadJS(url) {
- // TODO: consider adding timeout support & cancellation
- return new Promise((resolve, reject) => {
- const el = document.createElement('script');
- el.setAttribute('src', url);
- el.onload = resolve;
- el.onerror = e => {
- const error = _createError("internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- error.customData = e;
- reject(error);
- };
- el.type = 'text/javascript';
- el.charset = 'UTF-8';
- getScriptParentElement().appendChild(el);
- });
- }
- function _generateCallbackName(prefix) {
- return `__${prefix}${Math.floor(Math.random() * 1000000)}`;
- }
- /* eslint-disable @typescript-eslint/no-require-imports */
- const RECAPTCHA_ENTERPRISE_URL = 'https://www.google.com/recaptcha/enterprise.js?render=';
- const RECAPTCHA_ENTERPRISE_VERIFIER_TYPE = 'recaptcha-enterprise';
- const FAKE_TOKEN = 'NO_RECAPTCHA';
- class RecaptchaEnterpriseVerifier {
- /**
- *
- * @param authExtern - The corresponding Firebase {@link Auth} instance.
- *
- */
- constructor(authExtern) {
- /**
- * Identifies the type of application verifier (e.g. "recaptcha-enterprise").
- */
- this.type = RECAPTCHA_ENTERPRISE_VERIFIER_TYPE;
- this.auth = _castAuth(authExtern);
- }
- /**
- * Executes the verification process.
- *
- * @returns A Promise for a token that can be used to assert the validity of a request.
- */
- async verify(action = 'verify', forceRefresh = false) {
- async function retrieveSiteKey(auth) {
- if (!forceRefresh) {
- if (auth.tenantId == null && auth._agentRecaptchaConfig != null) {
- return auth._agentRecaptchaConfig.siteKey;
- }
- if (auth.tenantId != null &&
- auth._tenantRecaptchaConfigs[auth.tenantId] !== undefined) {
- return auth._tenantRecaptchaConfigs[auth.tenantId].siteKey;
- }
- }
- return new Promise(async (resolve, reject) => {
- getRecaptchaConfig(auth, {
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */,
- version: "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
- })
- .then(response => {
- if (response.recaptchaKey === undefined) {
- reject(new Error('recaptcha Enterprise site key undefined'));
- }
- else {
- const config = new RecaptchaConfig(response);
- if (auth.tenantId == null) {
- auth._agentRecaptchaConfig = config;
- }
- else {
- auth._tenantRecaptchaConfigs[auth.tenantId] = config;
- }
- return resolve(config.siteKey);
- }
- })
- .catch(error => {
- reject(error);
- });
- });
- }
- function retrieveRecaptchaToken(siteKey, resolve, reject) {
- const grecaptcha = window.grecaptcha;
- if (isEnterprise(grecaptcha)) {
- grecaptcha.enterprise.ready(() => {
- grecaptcha.enterprise
- .execute(siteKey, { action })
- .then(token => {
- resolve(token);
- })
- .catch(() => {
- resolve(FAKE_TOKEN);
- });
- });
- }
- else {
- reject(Error('No reCAPTCHA enterprise script loaded.'));
- }
- }
- return new Promise((resolve, reject) => {
- retrieveSiteKey(this.auth)
- .then(siteKey => {
- if (!forceRefresh && isEnterprise(window.grecaptcha)) {
- retrieveRecaptchaToken(siteKey, resolve, reject);
- }
- else {
- if (typeof window === 'undefined') {
- reject(new Error('RecaptchaVerifier is only supported in browser'));
- return;
- }
- _loadJS(RECAPTCHA_ENTERPRISE_URL + siteKey)
- .then(() => {
- retrieveRecaptchaToken(siteKey, resolve, reject);
- })
- .catch(error => {
- reject(error);
- });
- }
- })
- .catch(error => {
- reject(error);
- });
- });
- }
- }
- async function injectRecaptchaFields(auth, request, action, captchaResp = false) {
- const verifier = new RecaptchaEnterpriseVerifier(auth);
- let captchaResponse;
- try {
- captchaResponse = await verifier.verify(action);
- }
- catch (error) {
- captchaResponse = await verifier.verify(action, true);
- }
- const newRequest = Object.assign({}, request);
- if (!captchaResp) {
- Object.assign(newRequest, { captchaResponse });
- }
- else {
- Object.assign(newRequest, { 'captchaResp': captchaResponse });
- }
- Object.assign(newRequest, { 'clientType': "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */ });
- Object.assign(newRequest, {
- 'recaptchaVersion': "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
- });
- return newRequest;
- }
- /**
- * @license
- * Copyright 2022 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class AuthMiddlewareQueue {
- constructor(auth) {
- this.auth = auth;
- this.queue = [];
- }
- pushCallback(callback, onAbort) {
- // The callback could be sync or async. Wrap it into a
- // function that is always async.
- const wrappedCallback = (user) => new Promise((resolve, reject) => {
- try {
- const result = callback(user);
- // Either resolve with existing promise or wrap a non-promise
- // return value into a promise.
- resolve(result);
- }
- catch (e) {
- // Sync callback throws.
- reject(e);
- }
- });
- // Attach the onAbort if present
- wrappedCallback.onAbort = onAbort;
- this.queue.push(wrappedCallback);
- const index = this.queue.length - 1;
- return () => {
- // Unsubscribe. Replace with no-op. Do not remove from array, or it will disturb
- // indexing of other elements.
- this.queue[index] = () => Promise.resolve();
- };
- }
- async runMiddleware(nextUser) {
- if (this.auth.currentUser === nextUser) {
- return;
- }
- // While running the middleware, build a temporary stack of onAbort
- // callbacks to call if one middleware callback rejects.
- const onAbortStack = [];
- try {
- for (const beforeStateCallback of this.queue) {
- await beforeStateCallback(nextUser);
- // Only push the onAbort if the callback succeeds
- if (beforeStateCallback.onAbort) {
- onAbortStack.push(beforeStateCallback.onAbort);
- }
- }
- }
- catch (e) {
- // Run all onAbort, with separate try/catch to ignore any errors and
- // continue
- onAbortStack.reverse();
- for (const onAbort of onAbortStack) {
- try {
- onAbort();
- }
- catch (_) {
- /* swallow error */
- }
- }
- throw this.auth._errorFactory.create("login-blocked" /* AuthErrorCode.LOGIN_BLOCKED */, {
- originalMessage: e === null || e === void 0 ? void 0 : e.message
- });
- }
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class AuthImpl {
- constructor(app, heartbeatServiceProvider, appCheckServiceProvider, config) {
- this.app = app;
- this.heartbeatServiceProvider = heartbeatServiceProvider;
- this.appCheckServiceProvider = appCheckServiceProvider;
- this.config = config;
- this.currentUser = null;
- this.emulatorConfig = null;
- this.operations = Promise.resolve();
- this.authStateSubscription = new Subscription(this);
- this.idTokenSubscription = new Subscription(this);
- this.beforeStateQueue = new AuthMiddlewareQueue(this);
- this.redirectUser = null;
- this.isProactiveRefreshEnabled = false;
- // Any network calls will set this to true and prevent subsequent emulator
- // initialization
- this._canInitEmulator = true;
- this._isInitialized = false;
- this._deleted = false;
- this._initializationPromise = null;
- this._popupRedirectResolver = null;
- this._errorFactory = _DEFAULT_AUTH_ERROR_FACTORY;
- this._agentRecaptchaConfig = null;
- this._tenantRecaptchaConfigs = {};
- // Tracks the last notified UID for state change listeners to prevent
- // repeated calls to the callbacks. Undefined means it's never been
- // called, whereas null means it's been called with a signed out user
- this.lastNotifiedUid = undefined;
- this.languageCode = null;
- this.tenantId = null;
- this.settings = { appVerificationDisabledForTesting: false };
- this.frameworks = [];
- this.name = app.name;
- this.clientVersion = config.sdkClientVersion;
- }
- _initializeWithPersistence(persistenceHierarchy, popupRedirectResolver) {
- if (popupRedirectResolver) {
- this._popupRedirectResolver = _getInstance(popupRedirectResolver);
- }
- // Have to check for app deletion throughout initialization (after each
- // promise resolution)
- this._initializationPromise = this.queue(async () => {
- var _a, _b;
- if (this._deleted) {
- return;
- }
- this.persistenceManager = await PersistenceUserManager.create(this, persistenceHierarchy);
- if (this._deleted) {
- return;
- }
- // Initialize the resolver early if necessary (only applicable to web:
- // this will cause the iframe to load immediately in certain cases)
- if ((_a = this._popupRedirectResolver) === null || _a === void 0 ? void 0 : _a._shouldInitProactively) {
- // If this fails, don't halt auth loading
- try {
- await this._popupRedirectResolver._initialize(this);
- }
- catch (e) {
- /* Ignore the error */
- }
- }
- await this.initializeCurrentUser(popupRedirectResolver);
- this.lastNotifiedUid = ((_b = this.currentUser) === null || _b === void 0 ? void 0 : _b.uid) || null;
- if (this._deleted) {
- return;
- }
- this._isInitialized = true;
- });
- return this._initializationPromise;
- }
- /**
- * If the persistence is changed in another window, the user manager will let us know
- */
- async _onStorageEvent() {
- if (this._deleted) {
- return;
- }
- const user = await this.assertedPersistence.getCurrentUser();
- if (!this.currentUser && !user) {
- // No change, do nothing (was signed out and remained signed out).
- return;
- }
- // If the same user is to be synchronized.
- if (this.currentUser && user && this.currentUser.uid === user.uid) {
- // Data update, simply copy data changes.
- this._currentUser._assign(user);
- // If tokens changed from previous user tokens, this will trigger
- // notifyAuthListeners_.
- await this.currentUser.getIdToken();
- return;
- }
- // Update current Auth state. Either a new login or logout.
- // Skip blocking callbacks, they should not apply to a change in another tab.
- await this._updateCurrentUser(user, /* skipBeforeStateCallbacks */ true);
- }
- async initializeCurrentUser(popupRedirectResolver) {
- var _a;
- // First check to see if we have a pending redirect event.
- const previouslyStoredUser = (await this.assertedPersistence.getCurrentUser());
- let futureCurrentUser = previouslyStoredUser;
- let needsTocheckMiddleware = false;
- if (popupRedirectResolver && this.config.authDomain) {
- await this.getOrInitRedirectPersistenceManager();
- const redirectUserEventId = (_a = this.redirectUser) === null || _a === void 0 ? void 0 : _a._redirectEventId;
- const storedUserEventId = futureCurrentUser === null || futureCurrentUser === void 0 ? void 0 : futureCurrentUser._redirectEventId;
- const result = await this.tryRedirectSignIn(popupRedirectResolver);
- // If the stored user (i.e. the old "currentUser") has a redirectId that
- // matches the redirect user, then we want to initially sign in with the
- // new user object from result.
- // TODO(samgho): More thoroughly test all of this
- if ((!redirectUserEventId || redirectUserEventId === storedUserEventId) &&
- (result === null || result === void 0 ? void 0 : result.user)) {
- futureCurrentUser = result.user;
- needsTocheckMiddleware = true;
- }
- }
- // If no user in persistence, there is no current user. Set to null.
- if (!futureCurrentUser) {
- return this.directlySetCurrentUser(null);
- }
- if (!futureCurrentUser._redirectEventId) {
- // This isn't a redirect link operation, we can reload and bail.
- // First though, ensure that we check the middleware is happy.
- if (needsTocheckMiddleware) {
- try {
- await this.beforeStateQueue.runMiddleware(futureCurrentUser);
- }
- catch (e) {
- futureCurrentUser = previouslyStoredUser;
- // We know this is available since the bit is only set when the
- // resolver is available
- this._popupRedirectResolver._overrideRedirectResult(this, () => Promise.reject(e));
- }
- }
- if (futureCurrentUser) {
- return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
- }
- else {
- return this.directlySetCurrentUser(null);
- }
- }
- _assert(this._popupRedirectResolver, this, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- await this.getOrInitRedirectPersistenceManager();
- // If the redirect user's event ID matches the current user's event ID,
- // DO NOT reload the current user, otherwise they'll be cleared from storage.
- // This is important for the reauthenticateWithRedirect() flow.
- if (this.redirectUser &&
- this.redirectUser._redirectEventId === futureCurrentUser._redirectEventId) {
- return this.directlySetCurrentUser(futureCurrentUser);
- }
- return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
- }
- async tryRedirectSignIn(redirectResolver) {
- // The redirect user needs to be checked (and signed in if available)
- // during auth initialization. All of the normal sign in and link/reauth
- // flows call back into auth and push things onto the promise queue. We
- // need to await the result of the redirect sign in *inside the promise
- // queue*. This presents a problem: we run into deadlock. See:
- // ┌> [Initialization] ─────┐
- // ┌> [<other queue tasks>] │
- // └─ [getRedirectResult] <─┘
- // where [] are tasks on the queue and arrows denote awaits
- // Initialization will never complete because it's waiting on something
- // that's waiting for initialization to complete!
- //
- // Instead, this method calls getRedirectResult() (stored in
- // _completeRedirectFn) with an optional parameter that instructs all of
- // the underlying auth operations to skip anything that mutates auth state.
- let result = null;
- try {
- // We know this._popupRedirectResolver is set since redirectResolver
- // is passed in. The _completeRedirectFn expects the unwrapped extern.
- result = await this._popupRedirectResolver._completeRedirectFn(this, redirectResolver, true);
- }
- catch (e) {
- // Swallow any errors here; the code can retrieve them in
- // getRedirectResult().
- await this._setRedirectUser(null);
- }
- return result;
- }
- async reloadAndSetCurrentUserOrClear(user) {
- try {
- await _reloadWithoutSaving(user);
- }
- catch (e) {
- if ((e === null || e === void 0 ? void 0 : e.code) !==
- `auth/${"network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */}`) {
- // Something's wrong with the user's token. Log them out and remove
- // them from storage
- return this.directlySetCurrentUser(null);
- }
- }
- return this.directlySetCurrentUser(user);
- }
- useDeviceLanguage() {
- this.languageCode = _getUserLanguage();
- }
- async _delete() {
- this._deleted = true;
- }
- async updateCurrentUser(userExtern) {
- // The public updateCurrentUser method needs to make a copy of the user,
- // and also check that the project matches
- const user = userExtern
- ? util.getModularInstance(userExtern)
- : null;
- if (user) {
- _assert(user.auth.config.apiKey === this.config.apiKey, this, "invalid-user-token" /* AuthErrorCode.INVALID_AUTH */);
- }
- return this._updateCurrentUser(user && user._clone(this));
- }
- async _updateCurrentUser(user, skipBeforeStateCallbacks = false) {
- if (this._deleted) {
- return;
- }
- if (user) {
- _assert(this.tenantId === user.tenantId, this, "tenant-id-mismatch" /* AuthErrorCode.TENANT_ID_MISMATCH */);
- }
- if (!skipBeforeStateCallbacks) {
- await this.beforeStateQueue.runMiddleware(user);
- }
- return this.queue(async () => {
- await this.directlySetCurrentUser(user);
- this.notifyAuthListeners();
- });
- }
- async signOut() {
- // Run first, to block _setRedirectUser() if any callbacks fail.
- await this.beforeStateQueue.runMiddleware(null);
- // Clear the redirect user when signOut is called
- if (this.redirectPersistenceManager || this._popupRedirectResolver) {
- await this._setRedirectUser(null);
- }
- // Prevent callbacks from being called again in _updateCurrentUser, as
- // they were already called in the first line.
- return this._updateCurrentUser(null, /* skipBeforeStateCallbacks */ true);
- }
- setPersistence(persistence) {
- return this.queue(async () => {
- await this.assertedPersistence.setPersistence(_getInstance(persistence));
- });
- }
- async initializeRecaptchaConfig() {
- const response = await getRecaptchaConfig(this, {
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */,
- version: "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
- });
- const config = new RecaptchaConfig(response);
- if (this.tenantId == null) {
- this._agentRecaptchaConfig = config;
- }
- else {
- this._tenantRecaptchaConfigs[this.tenantId] = config;
- }
- if (config.emailPasswordEnabled) {
- const verifier = new RecaptchaEnterpriseVerifier(this);
- void verifier.verify();
- }
- }
- _getRecaptchaConfig() {
- if (this.tenantId == null) {
- return this._agentRecaptchaConfig;
- }
- else {
- return this._tenantRecaptchaConfigs[this.tenantId];
- }
- }
- _getPersistence() {
- return this.assertedPersistence.persistence.type;
- }
- _updateErrorMap(errorMap) {
- this._errorFactory = new util.ErrorFactory('auth', 'Firebase', errorMap());
- }
- onAuthStateChanged(nextOrObserver, error, completed) {
- return this.registerStateListener(this.authStateSubscription, nextOrObserver, error, completed);
- }
- beforeAuthStateChanged(callback, onAbort) {
- return this.beforeStateQueue.pushCallback(callback, onAbort);
- }
- onIdTokenChanged(nextOrObserver, error, completed) {
- return this.registerStateListener(this.idTokenSubscription, nextOrObserver, error, completed);
- }
- toJSON() {
- var _a;
- return {
- apiKey: this.config.apiKey,
- authDomain: this.config.authDomain,
- appName: this.name,
- currentUser: (_a = this._currentUser) === null || _a === void 0 ? void 0 : _a.toJSON()
- };
- }
- async _setRedirectUser(user, popupRedirectResolver) {
- const redirectManager = await this.getOrInitRedirectPersistenceManager(popupRedirectResolver);
- return user === null
- ? redirectManager.removeCurrentUser()
- : redirectManager.setCurrentUser(user);
- }
- async getOrInitRedirectPersistenceManager(popupRedirectResolver) {
- if (!this.redirectPersistenceManager) {
- const resolver = (popupRedirectResolver && _getInstance(popupRedirectResolver)) ||
- this._popupRedirectResolver;
- _assert(resolver, this, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- this.redirectPersistenceManager = await PersistenceUserManager.create(this, [_getInstance(resolver._redirectPersistence)], "redirectUser" /* KeyName.REDIRECT_USER */);
- this.redirectUser =
- await this.redirectPersistenceManager.getCurrentUser();
- }
- return this.redirectPersistenceManager;
- }
- async _redirectUserForId(id) {
- var _a, _b;
- // Make sure we've cleared any pending persistence actions if we're not in
- // the initializer
- if (this._isInitialized) {
- await this.queue(async () => { });
- }
- if (((_a = this._currentUser) === null || _a === void 0 ? void 0 : _a._redirectEventId) === id) {
- return this._currentUser;
- }
- if (((_b = this.redirectUser) === null || _b === void 0 ? void 0 : _b._redirectEventId) === id) {
- return this.redirectUser;
- }
- return null;
- }
- async _persistUserIfCurrent(user) {
- if (user === this.currentUser) {
- return this.queue(async () => this.directlySetCurrentUser(user));
- }
- }
- /** Notifies listeners only if the user is current */
- _notifyListenersIfCurrent(user) {
- if (user === this.currentUser) {
- this.notifyAuthListeners();
- }
- }
- _key() {
- return `${this.config.authDomain}:${this.config.apiKey}:${this.name}`;
- }
- _startProactiveRefresh() {
- this.isProactiveRefreshEnabled = true;
- if (this.currentUser) {
- this._currentUser._startProactiveRefresh();
- }
- }
- _stopProactiveRefresh() {
- this.isProactiveRefreshEnabled = false;
- if (this.currentUser) {
- this._currentUser._stopProactiveRefresh();
- }
- }
- /** Returns the current user cast as the internal type */
- get _currentUser() {
- return this.currentUser;
- }
- notifyAuthListeners() {
- var _a, _b;
- if (!this._isInitialized) {
- return;
- }
- this.idTokenSubscription.next(this.currentUser);
- const currentUid = (_b = (_a = this.currentUser) === null || _a === void 0 ? void 0 : _a.uid) !== null && _b !== void 0 ? _b : null;
- if (this.lastNotifiedUid !== currentUid) {
- this.lastNotifiedUid = currentUid;
- this.authStateSubscription.next(this.currentUser);
- }
- }
- registerStateListener(subscription, nextOrObserver, error, completed) {
- if (this._deleted) {
- return () => { };
- }
- const cb = typeof nextOrObserver === 'function'
- ? nextOrObserver
- : nextOrObserver.next.bind(nextOrObserver);
- const promise = this._isInitialized
- ? Promise.resolve()
- : this._initializationPromise;
- _assert(promise, this, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- // The callback needs to be called asynchronously per the spec.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- promise.then(() => cb(this.currentUser));
- if (typeof nextOrObserver === 'function') {
- return subscription.addObserver(nextOrObserver, error, completed);
- }
- else {
- return subscription.addObserver(nextOrObserver);
- }
- }
- /**
- * Unprotected (from race conditions) method to set the current user. This
- * should only be called from within a queued callback. This is necessary
- * because the queue shouldn't rely on another queued callback.
- */
- async directlySetCurrentUser(user) {
- if (this.currentUser && this.currentUser !== user) {
- this._currentUser._stopProactiveRefresh();
- }
- if (user && this.isProactiveRefreshEnabled) {
- user._startProactiveRefresh();
- }
- this.currentUser = user;
- if (user) {
- await this.assertedPersistence.setCurrentUser(user);
- }
- else {
- await this.assertedPersistence.removeCurrentUser();
- }
- }
- queue(action) {
- // In case something errors, the callback still should be called in order
- // to keep the promise chain alive
- this.operations = this.operations.then(action, action);
- return this.operations;
- }
- get assertedPersistence() {
- _assert(this.persistenceManager, this, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return this.persistenceManager;
- }
- _logFramework(framework) {
- if (!framework || this.frameworks.includes(framework)) {
- return;
- }
- this.frameworks.push(framework);
- // Sort alphabetically so that "FirebaseCore-web,FirebaseUI-web" and
- // "FirebaseUI-web,FirebaseCore-web" aren't viewed as different.
- this.frameworks.sort();
- this.clientVersion = _getClientVersion(this.config.clientPlatform, this._getFrameworks());
- }
- _getFrameworks() {
- return this.frameworks;
- }
- async _getAdditionalHeaders() {
- var _a;
- // Additional headers on every request
- const headers = {
- ["X-Client-Version" /* HttpHeader.X_CLIENT_VERSION */]: this.clientVersion
- };
- if (this.app.options.appId) {
- headers["X-Firebase-gmpid" /* HttpHeader.X_FIREBASE_GMPID */] = this.app.options.appId;
- }
- // If the heartbeat service exists, add the heartbeat string
- const heartbeatsHeader = await ((_a = this.heartbeatServiceProvider
- .getImmediate({
- optional: true
- })) === null || _a === void 0 ? void 0 : _a.getHeartbeatsHeader());
- if (heartbeatsHeader) {
- headers["X-Firebase-Client" /* HttpHeader.X_FIREBASE_CLIENT */] = heartbeatsHeader;
- }
- // If the App Check service exists, add the App Check token in the headers
- const appCheckToken = await this._getAppCheckToken();
- if (appCheckToken) {
- headers["X-Firebase-AppCheck" /* HttpHeader.X_FIREBASE_APP_CHECK */] = appCheckToken;
- }
- return headers;
- }
- async _getAppCheckToken() {
- var _a;
- const appCheckTokenResult = await ((_a = this.appCheckServiceProvider
- .getImmediate({ optional: true })) === null || _a === void 0 ? void 0 : _a.getToken());
- if (appCheckTokenResult === null || appCheckTokenResult === void 0 ? void 0 : appCheckTokenResult.error) {
- // Context: appCheck.getToken() will never throw even if an error happened.
- // In the error case, a dummy token will be returned along with an error field describing
- // the error. In general, we shouldn't care about the error condition and just use
- // the token (actual or dummy) to send requests.
- _logWarn(`Error while retrieving App Check token: ${appCheckTokenResult.error}`);
- }
- return appCheckTokenResult === null || appCheckTokenResult === void 0 ? void 0 : appCheckTokenResult.token;
- }
- }
- /**
- * Method to be used to cast down to our private implmentation of Auth.
- * It will also handle unwrapping from the compat type if necessary
- *
- * @param auth Auth object passed in from developer
- */
- function _castAuth(auth) {
- return util.getModularInstance(auth);
- }
- /** Helper class to wrap subscriber logic */
- class Subscription {
- constructor(auth) {
- this.auth = auth;
- this.observer = null;
- this.addObserver = util.createSubscribe(observer => (this.observer = observer));
- }
- get next() {
- _assert(this.observer, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return this.observer.next.bind(this.observer);
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Initializes an {@link Auth} instance with fine-grained control over
- * {@link Dependencies}.
- *
- * @remarks
- *
- * This function allows more control over the {@link Auth} instance than
- * {@link getAuth}. `getAuth` uses platform-specific defaults to supply
- * the {@link Dependencies}. In general, `getAuth` is the easiest way to
- * initialize Auth and works for most use cases. Use `initializeAuth` if you
- * need control over which persistence layer is used, or to minimize bundle
- * size if you're not using either `signInWithPopup` or `signInWithRedirect`.
- *
- * For example, if your app only uses anonymous accounts and you only want
- * accounts saved for the current session, initialize `Auth` with:
- *
- * ```js
- * const auth = initializeAuth(app, {
- * persistence: browserSessionPersistence,
- * popupRedirectResolver: undefined,
- * });
- * ```
- *
- * @public
- */
- function initializeAuth(app$1, deps) {
- const provider = app._getProvider(app$1, 'auth');
- if (provider.isInitialized()) {
- const auth = provider.getImmediate();
- const initialOptions = provider.getOptions();
- if (util.deepEqual(initialOptions, deps !== null && deps !== void 0 ? deps : {})) {
- return auth;
- }
- else {
- _fail(auth, "already-initialized" /* AuthErrorCode.ALREADY_INITIALIZED */);
- }
- }
- const auth = provider.initialize({ options: deps });
- return auth;
- }
- function _initializeAuthInstance(auth, deps) {
- const persistence = (deps === null || deps === void 0 ? void 0 : deps.persistence) || [];
- const hierarchy = (Array.isArray(persistence) ? persistence : [persistence]).map(_getInstance);
- if (deps === null || deps === void 0 ? void 0 : deps.errorMap) {
- auth._updateErrorMap(deps.errorMap);
- }
- // This promise is intended to float; auth initialization happens in the
- // background, meanwhile the auth object may be used by the app.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- auth._initializeWithPersistence(hierarchy, deps === null || deps === void 0 ? void 0 : deps.popupRedirectResolver);
- }
- /**
- * Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production
- * Firebase Auth services.
- *
- * @remarks
- * This must be called synchronously immediately following the first call to
- * {@link initializeAuth}. Do not use with production credentials as emulator
- * traffic is not encrypted.
- *
- *
- * @example
- * ```javascript
- * connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true });
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param url - The URL at which the emulator is running (eg, 'http://localhost:9099').
- * @param options - Optional. `options.disableWarnings` defaults to `false`. Set it to
- * `true` to disable the warning banner attached to the DOM.
- *
- * @public
- */
- function connectAuthEmulator(auth, url, options) {
- const authInternal = _castAuth(auth);
- _assert(authInternal._canInitEmulator, authInternal, "emulator-config-failed" /* AuthErrorCode.EMULATOR_CONFIG_FAILED */);
- _assert(/^https?:\/\//.test(url), authInternal, "invalid-emulator-scheme" /* AuthErrorCode.INVALID_EMULATOR_SCHEME */);
- const disableWarnings = !!(options === null || options === void 0 ? void 0 : options.disableWarnings);
- const protocol = extractProtocol(url);
- const { host, port } = extractHostAndPort(url);
- const portStr = port === null ? '' : `:${port}`;
- // Always replace path with "/" (even if input url had no path at all, or had a different one).
- authInternal.config.emulator = { url: `${protocol}//${host}${portStr}/` };
- authInternal.settings.appVerificationDisabledForTesting = true;
- authInternal.emulatorConfig = Object.freeze({
- host,
- port,
- protocol: protocol.replace(':', ''),
- options: Object.freeze({ disableWarnings })
- });
- if (!disableWarnings) {
- emitEmulatorWarning();
- }
- }
- function extractProtocol(url) {
- const protocolEnd = url.indexOf(':');
- return protocolEnd < 0 ? '' : url.substr(0, protocolEnd + 1);
- }
- function extractHostAndPort(url) {
- const protocol = extractProtocol(url);
- const authority = /(\/\/)?([^?#/]+)/.exec(url.substr(protocol.length)); // Between // and /, ? or #.
- if (!authority) {
- return { host: '', port: null };
- }
- const hostAndPort = authority[2].split('@').pop() || ''; // Strip out "username:password@".
- const bracketedIPv6 = /^(\[[^\]]+\])(:|$)/.exec(hostAndPort);
- if (bracketedIPv6) {
- const host = bracketedIPv6[1];
- return { host, port: parsePort(hostAndPort.substr(host.length + 1)) };
- }
- else {
- const [host, port] = hostAndPort.split(':');
- return { host, port: parsePort(port) };
- }
- }
- function parsePort(portStr) {
- if (!portStr) {
- return null;
- }
- const port = Number(portStr);
- if (isNaN(port)) {
- return null;
- }
- return port;
- }
- function emitEmulatorWarning() {
- function attachBanner() {
- const el = document.createElement('p');
- const sty = el.style;
- el.innerText =
- 'Running in emulator mode. Do not use with production credentials.';
- sty.position = 'fixed';
- sty.width = '100%';
- sty.backgroundColor = '#ffffff';
- sty.border = '.1em solid #000000';
- sty.color = '#b50000';
- sty.bottom = '0px';
- sty.left = '0px';
- sty.margin = '0px';
- sty.zIndex = '10000';
- sty.textAlign = 'center';
- el.classList.add('firebase-emulator-warning');
- document.body.appendChild(el);
- }
- if (typeof console !== 'undefined' && typeof console.info === 'function') {
- console.info('WARNING: You are using the Auth Emulator,' +
- ' which is intended for local testing only. Do not use with' +
- ' production credentials.');
- }
- if (typeof window !== 'undefined' && typeof document !== 'undefined') {
- if (document.readyState === 'loading') {
- window.addEventListener('DOMContentLoaded', attachBanner);
- }
- else {
- attachBanner();
- }
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Interface that represents the credentials returned by an {@link AuthProvider}.
- *
- * @remarks
- * Implementations specify the details about each auth provider's credential requirements.
- *
- * @public
- */
- class AuthCredential {
- /** @internal */
- constructor(
- /**
- * The authentication provider ID for the credential.
- *
- * @remarks
- * For example, 'facebook.com', or 'google.com'.
- */
- providerId,
- /**
- * The authentication sign in method for the credential.
- *
- * @remarks
- * For example, {@link SignInMethod}.EMAIL_PASSWORD, or
- * {@link SignInMethod}.EMAIL_LINK. This corresponds to the sign-in method
- * identifier as returned in {@link fetchSignInMethodsForEmail}.
- */
- signInMethod) {
- this.providerId = providerId;
- this.signInMethod = signInMethod;
- }
- /**
- * Returns a JSON-serializable representation of this object.
- *
- * @returns a JSON-serializable representation of this object.
- */
- toJSON() {
- return debugFail('not implemented');
- }
- /** @internal */
- _getIdTokenResponse(_auth) {
- return debugFail('not implemented');
- }
- /** @internal */
- _linkToIdToken(_auth, _idToken) {
- return debugFail('not implemented');
- }
- /** @internal */
- _getReauthenticationResolver(_auth) {
- return debugFail('not implemented');
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function resetPassword(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:resetPassword" /* Endpoint.RESET_PASSWORD */, _addTidIfNecessary(auth, request));
- }
- async function updateEmailPassword(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, request);
- }
- async function applyActionCode$1(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, _addTidIfNecessary(auth, request));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signInWithPassword(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithPassword" /* Endpoint.SIGN_IN_WITH_PASSWORD */, _addTidIfNecessary(auth, request));
- }
- async function sendOobCode(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:sendOobCode" /* Endpoint.SEND_OOB_CODE */, _addTidIfNecessary(auth, request));
- }
- async function sendEmailVerification$1(auth, request) {
- return sendOobCode(auth, request);
- }
- async function sendPasswordResetEmail$1(auth, request) {
- return sendOobCode(auth, request);
- }
- async function sendSignInLinkToEmail$1(auth, request) {
- return sendOobCode(auth, request);
- }
- async function verifyAndChangeEmail(auth, request) {
- return sendOobCode(auth, request);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signInWithEmailLink$1(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithEmailLink" /* Endpoint.SIGN_IN_WITH_EMAIL_LINK */, _addTidIfNecessary(auth, request));
- }
- async function signInWithEmailLinkForLinking(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithEmailLink" /* Endpoint.SIGN_IN_WITH_EMAIL_LINK */, _addTidIfNecessary(auth, request));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Interface that represents the credentials returned by {@link EmailAuthProvider} for
- * {@link ProviderId}.PASSWORD
- *
- * @remarks
- * Covers both {@link SignInMethod}.EMAIL_PASSWORD and
- * {@link SignInMethod}.EMAIL_LINK.
- *
- * @public
- */
- class EmailAuthCredential extends AuthCredential {
- /** @internal */
- constructor(
- /** @internal */
- _email,
- /** @internal */
- _password, signInMethod,
- /** @internal */
- _tenantId = null) {
- super("password" /* ProviderId.PASSWORD */, signInMethod);
- this._email = _email;
- this._password = _password;
- this._tenantId = _tenantId;
- }
- /** @internal */
- static _fromEmailAndPassword(email, password) {
- return new EmailAuthCredential(email, password, "password" /* SignInMethod.EMAIL_PASSWORD */);
- }
- /** @internal */
- static _fromEmailAndCode(email, oobCode, tenantId = null) {
- return new EmailAuthCredential(email, oobCode, "emailLink" /* SignInMethod.EMAIL_LINK */, tenantId);
- }
- /** {@inheritdoc AuthCredential.toJSON} */
- toJSON() {
- return {
- email: this._email,
- password: this._password,
- signInMethod: this.signInMethod,
- tenantId: this._tenantId
- };
- }
- /**
- * Static method to deserialize a JSON representation of an object into an {@link AuthCredential}.
- *
- * @param json - Either `object` or the stringified representation of the object. When string is
- * provided, `JSON.parse` would be called first.
- *
- * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
- */
- static fromJSON(json) {
- const obj = typeof json === 'string' ? JSON.parse(json) : json;
- if ((obj === null || obj === void 0 ? void 0 : obj.email) && (obj === null || obj === void 0 ? void 0 : obj.password)) {
- if (obj.signInMethod === "password" /* SignInMethod.EMAIL_PASSWORD */) {
- return this._fromEmailAndPassword(obj.email, obj.password);
- }
- else if (obj.signInMethod === "emailLink" /* SignInMethod.EMAIL_LINK */) {
- return this._fromEmailAndCode(obj.email, obj.password, obj.tenantId);
- }
- }
- return null;
- }
- /** @internal */
- async _getIdTokenResponse(auth) {
- var _a;
- switch (this.signInMethod) {
- case "password" /* SignInMethod.EMAIL_PASSWORD */:
- const request = {
- returnSecureToken: true,
- email: this._email,
- password: this._password,
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
- };
- if ((_a = auth._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
- const requestWithRecaptcha = await injectRecaptchaFields(auth, request, "signInWithPassword" /* RecaptchaActionName.SIGN_IN_WITH_PASSWORD */);
- return signInWithPassword(auth, requestWithRecaptcha);
- }
- else {
- return signInWithPassword(auth, request).catch(async (error) => {
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
- console.log('Sign-in with email address and password is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-in flow.');
- const requestWithRecaptcha = await injectRecaptchaFields(auth, request, "signInWithPassword" /* RecaptchaActionName.SIGN_IN_WITH_PASSWORD */);
- return signInWithPassword(auth, requestWithRecaptcha);
- }
- else {
- return Promise.reject(error);
- }
- });
- }
- case "emailLink" /* SignInMethod.EMAIL_LINK */:
- return signInWithEmailLink$1(auth, {
- email: this._email,
- oobCode: this._password
- });
- default:
- _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- }
- /** @internal */
- async _linkToIdToken(auth, idToken) {
- switch (this.signInMethod) {
- case "password" /* SignInMethod.EMAIL_PASSWORD */:
- return updateEmailPassword(auth, {
- idToken,
- returnSecureToken: true,
- email: this._email,
- password: this._password
- });
- case "emailLink" /* SignInMethod.EMAIL_LINK */:
- return signInWithEmailLinkForLinking(auth, {
- idToken,
- email: this._email,
- oobCode: this._password
- });
- default:
- _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- }
- /** @internal */
- _getReauthenticationResolver(auth) {
- return this._getIdTokenResponse(auth);
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signInWithIdp(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithIdp" /* Endpoint.SIGN_IN_WITH_IDP */, _addTidIfNecessary(auth, request));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const IDP_REQUEST_URI$1 = 'http://localhost';
- /**
- * Represents the OAuth credentials returned by an {@link OAuthProvider}.
- *
- * @remarks
- * Implementations specify the details about each auth provider's credential requirements.
- *
- * @public
- */
- class OAuthCredential extends AuthCredential {
- constructor() {
- super(...arguments);
- this.pendingToken = null;
- }
- /** @internal */
- static _fromParams(params) {
- const cred = new OAuthCredential(params.providerId, params.signInMethod);
- if (params.idToken || params.accessToken) {
- // OAuth 2 and either ID token or access token.
- if (params.idToken) {
- cred.idToken = params.idToken;
- }
- if (params.accessToken) {
- cred.accessToken = params.accessToken;
- }
- // Add nonce if available and no pendingToken is present.
- if (params.nonce && !params.pendingToken) {
- cred.nonce = params.nonce;
- }
- if (params.pendingToken) {
- cred.pendingToken = params.pendingToken;
- }
- }
- else if (params.oauthToken && params.oauthTokenSecret) {
- // OAuth 1 and OAuth token with token secret
- cred.accessToken = params.oauthToken;
- cred.secret = params.oauthTokenSecret;
- }
- else {
- _fail("argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- }
- return cred;
- }
- /** {@inheritdoc AuthCredential.toJSON} */
- toJSON() {
- return {
- idToken: this.idToken,
- accessToken: this.accessToken,
- secret: this.secret,
- nonce: this.nonce,
- pendingToken: this.pendingToken,
- providerId: this.providerId,
- signInMethod: this.signInMethod
- };
- }
- /**
- * Static method to deserialize a JSON representation of an object into an
- * {@link AuthCredential}.
- *
- * @param json - Input can be either Object or the stringified representation of the object.
- * When string is provided, JSON.parse would be called first.
- *
- * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
- */
- static fromJSON(json) {
- const obj = typeof json === 'string' ? JSON.parse(json) : json;
- const { providerId, signInMethod } = obj, rest = tslib.__rest(obj, ["providerId", "signInMethod"]);
- if (!providerId || !signInMethod) {
- return null;
- }
- const cred = new OAuthCredential(providerId, signInMethod);
- cred.idToken = rest.idToken || undefined;
- cred.accessToken = rest.accessToken || undefined;
- cred.secret = rest.secret;
- cred.nonce = rest.nonce;
- cred.pendingToken = rest.pendingToken || null;
- return cred;
- }
- /** @internal */
- _getIdTokenResponse(auth) {
- const request = this.buildRequest();
- return signInWithIdp(auth, request);
- }
- /** @internal */
- _linkToIdToken(auth, idToken) {
- const request = this.buildRequest();
- request.idToken = idToken;
- return signInWithIdp(auth, request);
- }
- /** @internal */
- _getReauthenticationResolver(auth) {
- const request = this.buildRequest();
- request.autoCreate = false;
- return signInWithIdp(auth, request);
- }
- buildRequest() {
- const request = {
- requestUri: IDP_REQUEST_URI$1,
- returnSecureToken: true
- };
- if (this.pendingToken) {
- request.pendingToken = this.pendingToken;
- }
- else {
- const postBody = {};
- if (this.idToken) {
- postBody['id_token'] = this.idToken;
- }
- if (this.accessToken) {
- postBody['access_token'] = this.accessToken;
- }
- if (this.secret) {
- postBody['oauth_token_secret'] = this.secret;
- }
- postBody['providerId'] = this.providerId;
- if (this.nonce && !this.pendingToken) {
- postBody['nonce'] = this.nonce;
- }
- request.postBody = util.querystring(postBody);
- }
- return request;
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function sendPhoneVerificationCode(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:sendVerificationCode" /* Endpoint.SEND_VERIFICATION_CODE */, _addTidIfNecessary(auth, request));
- }
- async function signInWithPhoneNumber$1(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithPhoneNumber" /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */, _addTidIfNecessary(auth, request));
- }
- async function linkWithPhoneNumber$1(auth, request) {
- const response = await _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithPhoneNumber" /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */, _addTidIfNecessary(auth, request));
- if (response.temporaryProof) {
- throw _makeTaggedError(auth, "account-exists-with-different-credential" /* AuthErrorCode.NEED_CONFIRMATION */, response);
- }
- return response;
- }
- const VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_ = {
- ["USER_NOT_FOUND" /* ServerError.USER_NOT_FOUND */]: "user-not-found" /* AuthErrorCode.USER_DELETED */
- };
- async function verifyPhoneNumberForExisting(auth, request) {
- const apiRequest = Object.assign(Object.assign({}, request), { operation: 'REAUTH' });
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithPhoneNumber" /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */, _addTidIfNecessary(auth, apiRequest), VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Represents the credentials returned by {@link PhoneAuthProvider}.
- *
- * @public
- */
- class PhoneAuthCredential extends AuthCredential {
- constructor(params) {
- super("phone" /* ProviderId.PHONE */, "phone" /* SignInMethod.PHONE */);
- this.params = params;
- }
- /** @internal */
- static _fromVerification(verificationId, verificationCode) {
- return new PhoneAuthCredential({ verificationId, verificationCode });
- }
- /** @internal */
- static _fromTokenResponse(phoneNumber, temporaryProof) {
- return new PhoneAuthCredential({ phoneNumber, temporaryProof });
- }
- /** @internal */
- _getIdTokenResponse(auth) {
- return signInWithPhoneNumber$1(auth, this._makeVerificationRequest());
- }
- /** @internal */
- _linkToIdToken(auth, idToken) {
- return linkWithPhoneNumber$1(auth, Object.assign({ idToken }, this._makeVerificationRequest()));
- }
- /** @internal */
- _getReauthenticationResolver(auth) {
- return verifyPhoneNumberForExisting(auth, this._makeVerificationRequest());
- }
- /** @internal */
- _makeVerificationRequest() {
- const { temporaryProof, phoneNumber, verificationId, verificationCode } = this.params;
- if (temporaryProof && phoneNumber) {
- return { temporaryProof, phoneNumber };
- }
- return {
- sessionInfo: verificationId,
- code: verificationCode
- };
- }
- /** {@inheritdoc AuthCredential.toJSON} */
- toJSON() {
- const obj = {
- providerId: this.providerId
- };
- if (this.params.phoneNumber) {
- obj.phoneNumber = this.params.phoneNumber;
- }
- if (this.params.temporaryProof) {
- obj.temporaryProof = this.params.temporaryProof;
- }
- if (this.params.verificationCode) {
- obj.verificationCode = this.params.verificationCode;
- }
- if (this.params.verificationId) {
- obj.verificationId = this.params.verificationId;
- }
- return obj;
- }
- /** Generates a phone credential based on a plain object or a JSON string. */
- static fromJSON(json) {
- if (typeof json === 'string') {
- json = JSON.parse(json);
- }
- const { verificationId, verificationCode, phoneNumber, temporaryProof } = json;
- if (!verificationCode &&
- !verificationId &&
- !phoneNumber &&
- !temporaryProof) {
- return null;
- }
- return new PhoneAuthCredential({
- verificationId,
- verificationCode,
- phoneNumber,
- temporaryProof
- });
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Maps the mode string in action code URL to Action Code Info operation.
- *
- * @param mode
- */
- function parseMode(mode) {
- switch (mode) {
- case 'recoverEmail':
- return "RECOVER_EMAIL" /* ActionCodeOperation.RECOVER_EMAIL */;
- case 'resetPassword':
- return "PASSWORD_RESET" /* ActionCodeOperation.PASSWORD_RESET */;
- case 'signIn':
- return "EMAIL_SIGNIN" /* ActionCodeOperation.EMAIL_SIGNIN */;
- case 'verifyEmail':
- return "VERIFY_EMAIL" /* ActionCodeOperation.VERIFY_EMAIL */;
- case 'verifyAndChangeEmail':
- return "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */;
- case 'revertSecondFactorAddition':
- return "REVERT_SECOND_FACTOR_ADDITION" /* ActionCodeOperation.REVERT_SECOND_FACTOR_ADDITION */;
- default:
- return null;
- }
- }
- /**
- * Helper to parse FDL links
- *
- * @param url
- */
- function parseDeepLink(url) {
- const link = util.querystringDecode(util.extractQuerystring(url))['link'];
- // Double link case (automatic redirect).
- const doubleDeepLink = link
- ? util.querystringDecode(util.extractQuerystring(link))['deep_link_id']
- : null;
- // iOS custom scheme links.
- const iOSDeepLink = util.querystringDecode(util.extractQuerystring(url))['deep_link_id'];
- const iOSDoubleDeepLink = iOSDeepLink
- ? util.querystringDecode(util.extractQuerystring(iOSDeepLink))['link']
- : null;
- return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
- }
- /**
- * A utility class to parse email action URLs such as password reset, email verification,
- * email link sign in, etc.
- *
- * @public
- */
- class ActionCodeURL {
- /**
- * @param actionLink - The link from which to extract the URL.
- * @returns The {@link ActionCodeURL} object, or null if the link is invalid.
- *
- * @internal
- */
- constructor(actionLink) {
- var _a, _b, _c, _d, _e, _f;
- const searchParams = util.querystringDecode(util.extractQuerystring(actionLink));
- const apiKey = (_a = searchParams["apiKey" /* QueryField.API_KEY */]) !== null && _a !== void 0 ? _a : null;
- const code = (_b = searchParams["oobCode" /* QueryField.CODE */]) !== null && _b !== void 0 ? _b : null;
- const operation = parseMode((_c = searchParams["mode" /* QueryField.MODE */]) !== null && _c !== void 0 ? _c : null);
- // Validate API key, code and mode.
- _assert(apiKey && code && operation, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- this.apiKey = apiKey;
- this.operation = operation;
- this.code = code;
- this.continueUrl = (_d = searchParams["continueUrl" /* QueryField.CONTINUE_URL */]) !== null && _d !== void 0 ? _d : null;
- this.languageCode = (_e = searchParams["languageCode" /* QueryField.LANGUAGE_CODE */]) !== null && _e !== void 0 ? _e : null;
- this.tenantId = (_f = searchParams["tenantId" /* QueryField.TENANT_ID */]) !== null && _f !== void 0 ? _f : null;
- }
- /**
- * Parses the email action link string and returns an {@link ActionCodeURL} if the link is valid,
- * otherwise returns null.
- *
- * @param link - The email action link string.
- * @returns The {@link ActionCodeURL} object, or null if the link is invalid.
- *
- * @public
- */
- static parseLink(link) {
- const actionLink = parseDeepLink(link);
- try {
- return new ActionCodeURL(actionLink);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /**
- * Parses the email action link string and returns an {@link ActionCodeURL} if
- * the link is valid, otherwise returns null.
- *
- * @public
- */
- function parseActionCodeURL(link) {
- return ActionCodeURL.parseLink(link);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating {@link EmailAuthCredential}.
- *
- * @public
- */
- class EmailAuthProvider {
- constructor() {
- /**
- * Always set to {@link ProviderId}.PASSWORD, even for email link.
- */
- this.providerId = EmailAuthProvider.PROVIDER_ID;
- }
- /**
- * Initialize an {@link AuthCredential} using an email and password.
- *
- * @example
- * ```javascript
- * const authCredential = EmailAuthProvider.credential(email, password);
- * const userCredential = await signInWithCredential(auth, authCredential);
- * ```
- *
- * @example
- * ```javascript
- * const userCredential = await signInWithEmailAndPassword(auth, email, password);
- * ```
- *
- * @param email - Email address.
- * @param password - User account password.
- * @returns The auth provider credential.
- */
- static credential(email, password) {
- return EmailAuthCredential._fromEmailAndPassword(email, password);
- }
- /**
- * Initialize an {@link AuthCredential} using an email and an email link after a sign in with
- * email link operation.
- *
- * @example
- * ```javascript
- * const authCredential = EmailAuthProvider.credentialWithLink(auth, email, emailLink);
- * const userCredential = await signInWithCredential(auth, authCredential);
- * ```
- *
- * @example
- * ```javascript
- * await sendSignInLinkToEmail(auth, email);
- * // Obtain emailLink from user.
- * const userCredential = await signInWithEmailLink(auth, email, emailLink);
- * ```
- *
- * @param auth - The {@link Auth} instance used to verify the link.
- * @param email - Email address.
- * @param emailLink - Sign-in email link.
- * @returns - The auth provider credential.
- */
- static credentialWithLink(email, emailLink) {
- const actionCodeUrl = ActionCodeURL.parseLink(emailLink);
- _assert(actionCodeUrl, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return EmailAuthCredential._fromEmailAndCode(email, actionCodeUrl.code, actionCodeUrl.tenantId);
- }
- }
- /**
- * Always set to {@link ProviderId}.PASSWORD, even for email link.
- */
- EmailAuthProvider.PROVIDER_ID = "password" /* ProviderId.PASSWORD */;
- /**
- * Always set to {@link SignInMethod}.EMAIL_PASSWORD.
- */
- EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD = "password" /* SignInMethod.EMAIL_PASSWORD */;
- /**
- * Always set to {@link SignInMethod}.EMAIL_LINK.
- */
- EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD = "emailLink" /* SignInMethod.EMAIL_LINK */;
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * The base class for all Federated providers (OAuth (including OIDC), SAML).
- *
- * This class is not meant to be instantiated directly.
- *
- * @public
- */
- class FederatedAuthProvider {
- /**
- * Constructor for generic OAuth providers.
- *
- * @param providerId - Provider for which credentials should be generated.
- */
- constructor(providerId) {
- this.providerId = providerId;
- /** @internal */
- this.defaultLanguageCode = null;
- /** @internal */
- this.customParameters = {};
- }
- /**
- * Set the language gode.
- *
- * @param languageCode - language code
- */
- setDefaultLanguage(languageCode) {
- this.defaultLanguageCode = languageCode;
- }
- /**
- * Sets the OAuth custom parameters to pass in an OAuth request for popup and redirect sign-in
- * operations.
- *
- * @remarks
- * For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`,
- * `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored.
- *
- * @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request.
- */
- setCustomParameters(customOAuthParameters) {
- this.customParameters = customOAuthParameters;
- return this;
- }
- /**
- * Retrieve the current list of {@link CustomParameters}.
- */
- getCustomParameters() {
- return this.customParameters;
- }
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Common code to all OAuth providers. This is separate from the
- * {@link OAuthProvider} so that child providers (like
- * {@link GoogleAuthProvider}) don't inherit the `credential` instance method.
- * Instead, they rely on a static `credential` method.
- */
- class BaseOAuthProvider extends FederatedAuthProvider {
- constructor() {
- super(...arguments);
- /** @internal */
- this.scopes = [];
- }
- /**
- * Add an OAuth scope to the credential.
- *
- * @param scope - Provider OAuth scope to add.
- */
- addScope(scope) {
- // If not already added, add scope to list.
- if (!this.scopes.includes(scope)) {
- this.scopes.push(scope);
- }
- return this;
- }
- /**
- * Retrieve the current list of OAuth scopes.
- */
- getScopes() {
- return [...this.scopes];
- }
- }
- /**
- * Provider for generating generic {@link OAuthCredential}.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new OAuthProvider('google.com');
- * // Start a sign in process for an unauthenticated user.
- * provider.addScope('profile');
- * provider.addScope('email');
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a OAuth Access Token for the provider.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new OAuthProvider('google.com');
- * provider.addScope('profile');
- * provider.addScope('email');
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a OAuth Access Token for the provider.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * ```
- * @public
- */
- class OAuthProvider extends BaseOAuthProvider {
- /**
- * Creates an {@link OAuthCredential} from a JSON string or a plain object.
- * @param json - A plain object or a JSON string
- */
- static credentialFromJSON(json) {
- const obj = typeof json === 'string' ? JSON.parse(json) : json;
- _assert('providerId' in obj && 'signInMethod' in obj, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return OAuthCredential._fromParams(obj);
- }
- /**
- * Creates a {@link OAuthCredential} from a generic OAuth provider's access token or ID token.
- *
- * @remarks
- * The raw nonce is required when an ID token with a nonce field is provided. The SHA-256 hash of
- * the raw nonce must match the nonce field in the ID token.
- *
- * @example
- * ```javascript
- * // `googleUser` from the onsuccess Google Sign In callback.
- * // Initialize a generate OAuth provider with a `google.com` providerId.
- * const provider = new OAuthProvider('google.com');
- * const credential = provider.credential({
- * idToken: googleUser.getAuthResponse().id_token,
- * });
- * const result = await signInWithCredential(credential);
- * ```
- *
- * @param params - Either the options object containing the ID token, access token and raw nonce
- * or the ID token string.
- */
- credential(params) {
- return this._credential(Object.assign(Object.assign({}, params), { nonce: params.rawNonce }));
- }
- /** An internal credential method that accepts more permissive options */
- _credential(params) {
- _assert(params.idToken || params.accessToken, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- // For OAuthCredential, sign in method is same as providerId.
- return OAuthCredential._fromParams(Object.assign(Object.assign({}, params), { providerId: this.providerId, signInMethod: this.providerId }));
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return OAuthProvider.oauthCredentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return OAuthProvider.oauthCredentialFromTaggedObject((error.customData || {}));
- }
- static oauthCredentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { oauthIdToken, oauthAccessToken, oauthTokenSecret, pendingToken, nonce, providerId } = tokenResponse;
- if (!oauthAccessToken &&
- !oauthTokenSecret &&
- !oauthIdToken &&
- !pendingToken) {
- return null;
- }
- if (!providerId) {
- return null;
- }
- try {
- return new OAuthProvider(providerId)._credential({
- idToken: oauthIdToken,
- accessToken: oauthAccessToken,
- nonce,
- pendingToken
- });
- }
- catch (e) {
- return null;
- }
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.FACEBOOK.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new FacebookAuthProvider();
- * // Start a sign in process for an unauthenticated user.
- * provider.addScope('user_birthday');
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = FacebookAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new FacebookAuthProvider();
- * provider.addScope('user_birthday');
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = FacebookAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * ```
- *
- * @public
- */
- class FacebookAuthProvider extends BaseOAuthProvider {
- constructor() {
- super("facebook.com" /* ProviderId.FACEBOOK */);
- }
- /**
- * Creates a credential for Facebook.
- *
- * @example
- * ```javascript
- * // `event` from the Facebook auth.authResponseChange callback.
- * const credential = FacebookAuthProvider.credential(event.authResponse.accessToken);
- * const result = await signInWithCredential(credential);
- * ```
- *
- * @param accessToken - Facebook access token.
- */
- static credential(accessToken) {
- return OAuthCredential._fromParams({
- providerId: FacebookAuthProvider.PROVIDER_ID,
- signInMethod: FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD,
- accessToken
- });
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return FacebookAuthProvider.credentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return FacebookAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse || !('oauthAccessToken' in tokenResponse)) {
- return null;
- }
- if (!tokenResponse.oauthAccessToken) {
- return null;
- }
- try {
- return FacebookAuthProvider.credential(tokenResponse.oauthAccessToken);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /** Always set to {@link SignInMethod}.FACEBOOK. */
- FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD = "facebook.com" /* SignInMethod.FACEBOOK */;
- /** Always set to {@link ProviderId}.FACEBOOK. */
- FacebookAuthProvider.PROVIDER_ID = "facebook.com" /* ProviderId.FACEBOOK */;
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an an {@link OAuthCredential} for {@link ProviderId}.GOOGLE.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new GoogleAuthProvider();
- * // Start a sign in process for an unauthenticated user.
- * provider.addScope('profile');
- * provider.addScope('email');
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Google Access Token.
- * const credential = GoogleAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new GoogleAuthProvider();
- * provider.addScope('profile');
- * provider.addScope('email');
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Google Access Token.
- * const credential = GoogleAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * ```
- *
- * @public
- */
- class GoogleAuthProvider extends BaseOAuthProvider {
- constructor() {
- super("google.com" /* ProviderId.GOOGLE */);
- this.addScope('profile');
- }
- /**
- * Creates a credential for Google. At least one of ID token and access token is required.
- *
- * @example
- * ```javascript
- * // \`googleUser\` from the onsuccess Google Sign In callback.
- * const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
- * const result = await signInWithCredential(credential);
- * ```
- *
- * @param idToken - Google ID token.
- * @param accessToken - Google access token.
- */
- static credential(idToken, accessToken) {
- return OAuthCredential._fromParams({
- providerId: GoogleAuthProvider.PROVIDER_ID,
- signInMethod: GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD,
- idToken,
- accessToken
- });
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return GoogleAuthProvider.credentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return GoogleAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { oauthIdToken, oauthAccessToken } = tokenResponse;
- if (!oauthIdToken && !oauthAccessToken) {
- // This could be an oauth 1 credential or a phone credential
- return null;
- }
- try {
- return GoogleAuthProvider.credential(oauthIdToken, oauthAccessToken);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /** Always set to {@link SignInMethod}.GOOGLE. */
- GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD = "google.com" /* SignInMethod.GOOGLE */;
- /** Always set to {@link ProviderId}.GOOGLE. */
- GoogleAuthProvider.PROVIDER_ID = "google.com" /* ProviderId.GOOGLE */;
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GITHUB.
- *
- * @remarks
- * GitHub requires an OAuth 2.0 redirect, so you can either handle the redirect directly, or use
- * the {@link signInWithPopup} handler:
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new GithubAuthProvider();
- * // Start a sign in process for an unauthenticated user.
- * provider.addScope('repo');
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Github Access Token.
- * const credential = GithubAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new GithubAuthProvider();
- * provider.addScope('repo');
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Github Access Token.
- * const credential = GithubAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * ```
- * @public
- */
- class GithubAuthProvider extends BaseOAuthProvider {
- constructor() {
- super("github.com" /* ProviderId.GITHUB */);
- }
- /**
- * Creates a credential for Github.
- *
- * @param accessToken - Github access token.
- */
- static credential(accessToken) {
- return OAuthCredential._fromParams({
- providerId: GithubAuthProvider.PROVIDER_ID,
- signInMethod: GithubAuthProvider.GITHUB_SIGN_IN_METHOD,
- accessToken
- });
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return GithubAuthProvider.credentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return GithubAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse || !('oauthAccessToken' in tokenResponse)) {
- return null;
- }
- if (!tokenResponse.oauthAccessToken) {
- return null;
- }
- try {
- return GithubAuthProvider.credential(tokenResponse.oauthAccessToken);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /** Always set to {@link SignInMethod}.GITHUB. */
- GithubAuthProvider.GITHUB_SIGN_IN_METHOD = "github.com" /* SignInMethod.GITHUB */;
- /** Always set to {@link ProviderId}.GITHUB. */
- GithubAuthProvider.PROVIDER_ID = "github.com" /* ProviderId.GITHUB */;
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const IDP_REQUEST_URI = 'http://localhost';
- /**
- * @public
- */
- class SAMLAuthCredential extends AuthCredential {
- /** @internal */
- constructor(providerId, pendingToken) {
- super(providerId, providerId);
- this.pendingToken = pendingToken;
- }
- /** @internal */
- _getIdTokenResponse(auth) {
- const request = this.buildRequest();
- return signInWithIdp(auth, request);
- }
- /** @internal */
- _linkToIdToken(auth, idToken) {
- const request = this.buildRequest();
- request.idToken = idToken;
- return signInWithIdp(auth, request);
- }
- /** @internal */
- _getReauthenticationResolver(auth) {
- const request = this.buildRequest();
- request.autoCreate = false;
- return signInWithIdp(auth, request);
- }
- /** {@inheritdoc AuthCredential.toJSON} */
- toJSON() {
- return {
- signInMethod: this.signInMethod,
- providerId: this.providerId,
- pendingToken: this.pendingToken
- };
- }
- /**
- * Static method to deserialize a JSON representation of an object into an
- * {@link AuthCredential}.
- *
- * @param json - Input can be either Object or the stringified representation of the object.
- * When string is provided, JSON.parse would be called first.
- *
- * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
- */
- static fromJSON(json) {
- const obj = typeof json === 'string' ? JSON.parse(json) : json;
- const { providerId, signInMethod, pendingToken } = obj;
- if (!providerId ||
- !signInMethod ||
- !pendingToken ||
- providerId !== signInMethod) {
- return null;
- }
- return new SAMLAuthCredential(providerId, pendingToken);
- }
- /**
- * Helper static method to avoid exposing the constructor to end users.
- *
- * @internal
- */
- static _create(providerId, pendingToken) {
- return new SAMLAuthCredential(providerId, pendingToken);
- }
- buildRequest() {
- return {
- requestUri: IDP_REQUEST_URI,
- returnSecureToken: true,
- pendingToken: this.pendingToken
- };
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const SAML_PROVIDER_PREFIX = 'saml.';
- /**
- * An {@link AuthProvider} for SAML.
- *
- * @public
- */
- class SAMLAuthProvider extends FederatedAuthProvider {
- /**
- * Constructor. The providerId must start with "saml."
- * @param providerId - SAML provider ID.
- */
- constructor(providerId) {
- _assert(providerId.startsWith(SAML_PROVIDER_PREFIX), "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- super(providerId);
- }
- /**
- * Generates an {@link AuthCredential} from a {@link UserCredential} after a
- * successful SAML flow completes.
- *
- * @remarks
- *
- * For example, to get an {@link AuthCredential}, you could write the
- * following code:
- *
- * ```js
- * const userCredential = await signInWithPopup(auth, samlProvider);
- * const credential = SAMLAuthProvider.credentialFromResult(userCredential);
- * ```
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return SAMLAuthProvider.samlCredentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return SAMLAuthProvider.samlCredentialFromTaggedObject((error.customData || {}));
- }
- /**
- * Creates an {@link AuthCredential} from a JSON string or a plain object.
- * @param json - A plain object or a JSON string
- */
- static credentialFromJSON(json) {
- const credential = SAMLAuthCredential.fromJSON(json);
- _assert(credential, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return credential;
- }
- static samlCredentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { pendingToken, providerId } = tokenResponse;
- if (!pendingToken || !providerId) {
- return null;
- }
- try {
- return SAMLAuthCredential._create(providerId, pendingToken);
- }
- catch (e) {
- return null;
- }
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.TWITTER.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new TwitterAuthProvider();
- * // Start a sign in process for an unauthenticated user.
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Twitter Access Token and Secret.
- * const credential = TwitterAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * const secret = credential.secret;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new TwitterAuthProvider();
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Twitter Access Token and Secret.
- * const credential = TwitterAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * const secret = credential.secret;
- * ```
- *
- * @public
- */
- class TwitterAuthProvider extends BaseOAuthProvider {
- constructor() {
- super("twitter.com" /* ProviderId.TWITTER */);
- }
- /**
- * Creates a credential for Twitter.
- *
- * @param token - Twitter access token.
- * @param secret - Twitter secret.
- */
- static credential(token, secret) {
- return OAuthCredential._fromParams({
- providerId: TwitterAuthProvider.PROVIDER_ID,
- signInMethod: TwitterAuthProvider.TWITTER_SIGN_IN_METHOD,
- oauthToken: token,
- oauthTokenSecret: secret
- });
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return TwitterAuthProvider.credentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return TwitterAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { oauthAccessToken, oauthTokenSecret } = tokenResponse;
- if (!oauthAccessToken || !oauthTokenSecret) {
- return null;
- }
- try {
- return TwitterAuthProvider.credential(oauthAccessToken, oauthTokenSecret);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /** Always set to {@link SignInMethod}.TWITTER. */
- TwitterAuthProvider.TWITTER_SIGN_IN_METHOD = "twitter.com" /* SignInMethod.TWITTER */;
- /** Always set to {@link ProviderId}.TWITTER. */
- TwitterAuthProvider.PROVIDER_ID = "twitter.com" /* ProviderId.TWITTER */;
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signUp(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signUp" /* Endpoint.SIGN_UP */, _addTidIfNecessary(auth, request));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class UserCredentialImpl {
- constructor(params) {
- this.user = params.user;
- this.providerId = params.providerId;
- this._tokenResponse = params._tokenResponse;
- this.operationType = params.operationType;
- }
- static async _fromIdTokenResponse(auth, operationType, idTokenResponse, isAnonymous = false) {
- const user = await UserImpl._fromIdTokenResponse(auth, idTokenResponse, isAnonymous);
- const providerId = providerIdForResponse(idTokenResponse);
- const userCred = new UserCredentialImpl({
- user,
- providerId,
- _tokenResponse: idTokenResponse,
- operationType
- });
- return userCred;
- }
- static async _forOperation(user, operationType, response) {
- await user._updateTokensIfNecessary(response, /* reload */ true);
- const providerId = providerIdForResponse(response);
- return new UserCredentialImpl({
- user,
- providerId,
- _tokenResponse: response,
- operationType
- });
- }
- }
- function providerIdForResponse(response) {
- if (response.providerId) {
- return response.providerId;
- }
- if ('phoneNumber' in response) {
- return "phone" /* ProviderId.PHONE */;
- }
- return null;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Asynchronously signs in as an anonymous user.
- *
- * @remarks
- * If there is already an anonymous user signed in, that user will be returned; otherwise, a
- * new anonymous user identity will be created and returned.
- *
- * @param auth - The {@link Auth} instance.
- *
- * @public
- */
- async function signInAnonymously(auth) {
- var _a;
- const authInternal = _castAuth(auth);
- await authInternal._initializationPromise;
- if ((_a = authInternal.currentUser) === null || _a === void 0 ? void 0 : _a.isAnonymous) {
- // If an anonymous user is already signed in, no need to sign them in again.
- return new UserCredentialImpl({
- user: authInternal.currentUser,
- providerId: null,
- operationType: "signIn" /* OperationType.SIGN_IN */
- });
- }
- const response = await signUp(authInternal, {
- returnSecureToken: true
- });
- const userCredential = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn" /* OperationType.SIGN_IN */, response, true);
- await authInternal._updateCurrentUser(userCredential.user);
- return userCredential;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class MultiFactorError extends util.FirebaseError {
- constructor(auth, error, operationType, user) {
- var _a;
- super(error.code, error.message);
- this.operationType = operationType;
- this.user = user;
- // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
- Object.setPrototypeOf(this, MultiFactorError.prototype);
- this.customData = {
- appName: auth.name,
- tenantId: (_a = auth.tenantId) !== null && _a !== void 0 ? _a : undefined,
- _serverResponse: error.customData._serverResponse,
- operationType
- };
- }
- static _fromErrorAndOperation(auth, error, operationType, user) {
- return new MultiFactorError(auth, error, operationType, user);
- }
- }
- function _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential, user) {
- const idTokenProvider = operationType === "reauthenticate" /* OperationType.REAUTHENTICATE */
- ? credential._getReauthenticationResolver(auth)
- : credential._getIdTokenResponse(auth);
- return idTokenProvider.catch(error => {
- if (error.code === `auth/${"multi-factor-auth-required" /* AuthErrorCode.MFA_REQUIRED */}`) {
- throw MultiFactorError._fromErrorAndOperation(auth, error, operationType, user);
- }
- throw error;
- });
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Takes a set of UserInfo provider data and converts it to a set of names
- */
- function providerDataAsNames(providerData) {
- return new Set(providerData
- .map(({ providerId }) => providerId)
- .filter(pid => !!pid));
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Unlinks a provider from a user account.
- *
- * @param user - The user.
- * @param providerId - The provider to unlink.
- *
- * @public
- */
- async function unlink(user, providerId) {
- const userInternal = util.getModularInstance(user);
- await _assertLinkedStatus(true, userInternal, providerId);
- const { providerUserInfo } = await deleteLinkedAccounts(userInternal.auth, {
- idToken: await userInternal.getIdToken(),
- deleteProvider: [providerId]
- });
- const providersLeft = providerDataAsNames(providerUserInfo || []);
- userInternal.providerData = userInternal.providerData.filter(pd => providersLeft.has(pd.providerId));
- if (!providersLeft.has("phone" /* ProviderId.PHONE */)) {
- userInternal.phoneNumber = null;
- }
- await userInternal.auth._persistUserIfCurrent(userInternal);
- return userInternal;
- }
- async function _link$1(user, credential, bypassAuthState = false) {
- const response = await _logoutIfInvalidated(user, credential._linkToIdToken(user.auth, await user.getIdToken()), bypassAuthState);
- return UserCredentialImpl._forOperation(user, "link" /* OperationType.LINK */, response);
- }
- async function _assertLinkedStatus(expected, user, provider) {
- await _reloadWithoutSaving(user);
- const providerIds = providerDataAsNames(user.providerData);
- const code = expected === false
- ? "provider-already-linked" /* AuthErrorCode.PROVIDER_ALREADY_LINKED */
- : "no-such-provider" /* AuthErrorCode.NO_SUCH_PROVIDER */;
- _assert(providerIds.has(provider) === expected, user.auth, code);
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _reauthenticate(user, credential, bypassAuthState = false) {
- const { auth } = user;
- const operationType = "reauthenticate" /* OperationType.REAUTHENTICATE */;
- try {
- const response = await _logoutIfInvalidated(user, _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential, user), bypassAuthState);
- _assert(response.idToken, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const parsed = _parseToken(response.idToken);
- _assert(parsed, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const { sub: localId } = parsed;
- _assert(user.uid === localId, auth, "user-mismatch" /* AuthErrorCode.USER_MISMATCH */);
- return UserCredentialImpl._forOperation(user, operationType, response);
- }
- catch (e) {
- // Convert user deleted error into user mismatch
- if ((e === null || e === void 0 ? void 0 : e.code) === `auth/${"user-not-found" /* AuthErrorCode.USER_DELETED */}`) {
- _fail(auth, "user-mismatch" /* AuthErrorCode.USER_MISMATCH */);
- }
- throw e;
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _signInWithCredential(auth, credential, bypassAuthState = false) {
- const operationType = "signIn" /* OperationType.SIGN_IN */;
- const response = await _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential);
- const userCredential = await UserCredentialImpl._fromIdTokenResponse(auth, operationType, response);
- if (!bypassAuthState) {
- await auth._updateCurrentUser(userCredential.user);
- }
- return userCredential;
- }
- /**
- * Asynchronously signs in with the given credentials.
- *
- * @remarks
- * An {@link AuthProvider} can be used to generate the credential.
- *
- * @param auth - The {@link Auth} instance.
- * @param credential - The auth credential.
- *
- * @public
- */
- async function signInWithCredential(auth, credential) {
- return _signInWithCredential(_castAuth(auth), credential);
- }
- /**
- * Links the user account with the given credentials.
- *
- * @remarks
- * An {@link AuthProvider} can be used to generate the credential.
- *
- * @param user - The user.
- * @param credential - The auth credential.
- *
- * @public
- */
- async function linkWithCredential(user, credential) {
- const userInternal = util.getModularInstance(user);
- await _assertLinkedStatus(false, userInternal, credential.providerId);
- return _link$1(userInternal, credential);
- }
- /**
- * Re-authenticates a user using a fresh credential.
- *
- * @remarks
- * Use before operations such as {@link updatePassword} that require tokens from recent sign-in
- * attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error
- * or a `TOKEN_EXPIRED` error.
- *
- * @param user - The user.
- * @param credential - The auth credential.
- *
- * @public
- */
- async function reauthenticateWithCredential(user, credential) {
- return _reauthenticate(util.getModularInstance(user), credential);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signInWithCustomToken$1(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithCustomToken" /* Endpoint.SIGN_IN_WITH_CUSTOM_TOKEN */, _addTidIfNecessary(auth, request));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Asynchronously signs in using a custom token.
- *
- * @remarks
- * Custom tokens are used to integrate Firebase Auth with existing auth systems, and must
- * be generated by an auth backend using the
- * {@link https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createcustomtoken | createCustomToken}
- * method in the {@link https://firebase.google.com/docs/auth/admin | Admin SDK} .
- *
- * Fails with an error if the token is invalid, expired, or not accepted by the Firebase Auth service.
- *
- * @param auth - The {@link Auth} instance.
- * @param customToken - The custom token to sign in with.
- *
- * @public
- */
- async function signInWithCustomToken(auth, customToken) {
- const authInternal = _castAuth(auth);
- const response = await signInWithCustomToken$1(authInternal, {
- token: customToken,
- returnSecureToken: true
- });
- const cred = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn" /* OperationType.SIGN_IN */, response);
- await authInternal._updateCurrentUser(cred.user);
- return cred;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class MultiFactorInfoImpl {
- constructor(factorId, response) {
- this.factorId = factorId;
- this.uid = response.mfaEnrollmentId;
- this.enrollmentTime = new Date(response.enrolledAt).toUTCString();
- this.displayName = response.displayName;
- }
- static _fromServerResponse(auth, enrollment) {
- if ('phoneInfo' in enrollment) {
- return PhoneMultiFactorInfoImpl._fromServerResponse(auth, enrollment);
- }
- else if ('totpInfo' in enrollment) {
- return TotpMultiFactorInfoImpl._fromServerResponse(auth, enrollment);
- }
- return _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- }
- class PhoneMultiFactorInfoImpl extends MultiFactorInfoImpl {
- constructor(response) {
- super("phone" /* FactorId.PHONE */, response);
- this.phoneNumber = response.phoneInfo;
- }
- static _fromServerResponse(_auth, enrollment) {
- return new PhoneMultiFactorInfoImpl(enrollment);
- }
- }
- class TotpMultiFactorInfoImpl extends MultiFactorInfoImpl {
- constructor(response) {
- super("totp" /* FactorId.TOTP */, response);
- }
- static _fromServerResponse(_auth, enrollment) {
- return new TotpMultiFactorInfoImpl(enrollment);
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _setActionCodeSettingsOnRequest(auth, request, actionCodeSettings) {
- var _a;
- _assert(((_a = actionCodeSettings.url) === null || _a === void 0 ? void 0 : _a.length) > 0, auth, "invalid-continue-uri" /* AuthErrorCode.INVALID_CONTINUE_URI */);
- _assert(typeof actionCodeSettings.dynamicLinkDomain === 'undefined' ||
- actionCodeSettings.dynamicLinkDomain.length > 0, auth, "invalid-dynamic-link-domain" /* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */);
- request.continueUrl = actionCodeSettings.url;
- request.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
- request.canHandleCodeInApp = actionCodeSettings.handleCodeInApp;
- if (actionCodeSettings.iOS) {
- _assert(actionCodeSettings.iOS.bundleId.length > 0, auth, "missing-ios-bundle-id" /* AuthErrorCode.MISSING_IOS_BUNDLE_ID */);
- request.iOSBundleId = actionCodeSettings.iOS.bundleId;
- }
- if (actionCodeSettings.android) {
- _assert(actionCodeSettings.android.packageName.length > 0, auth, "missing-android-pkg-name" /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */);
- request.androidInstallApp = actionCodeSettings.android.installApp;
- request.androidMinimumVersionCode =
- actionCodeSettings.android.minimumVersion;
- request.androidPackageName = actionCodeSettings.android.packageName;
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Sends a password reset email to the given email address.
- *
- * @remarks
- * To complete the password reset, call {@link confirmPasswordReset} with the code supplied in
- * the email sent to the user, along with the new password specified by the user.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await sendPasswordResetEmail(auth, 'user@example.com', actionCodeSettings);
- * // Obtain code from user.
- * await confirmPasswordReset('user@example.com', code);
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The user's email address.
- * @param actionCodeSettings - The {@link ActionCodeSettings}.
- *
- * @public
- */
- async function sendPasswordResetEmail(auth, email, actionCodeSettings) {
- var _a;
- const authInternal = _castAuth(auth);
- const request = {
- requestType: "PASSWORD_RESET" /* ActionCodeOperation.PASSWORD_RESET */,
- email,
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
- };
- if ((_a = authInternal._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(authInternal, requestWithRecaptcha, actionCodeSettings);
- }
- await sendPasswordResetEmail$1(authInternal, requestWithRecaptcha);
- }
- else {
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(authInternal, request, actionCodeSettings);
- }
- await sendPasswordResetEmail$1(authInternal, request)
- .catch(async (error) => {
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
- console.log('Password resets are protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the password reset flow.');
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(authInternal, requestWithRecaptcha, actionCodeSettings);
- }
- await sendPasswordResetEmail$1(authInternal, requestWithRecaptcha);
- }
- else {
- return Promise.reject(error);
- }
- });
- }
- }
- /**
- * Completes the password reset process, given a confirmation code and new password.
- *
- * @param auth - The {@link Auth} instance.
- * @param oobCode - A confirmation code sent to the user.
- * @param newPassword - The new password.
- *
- * @public
- */
- async function confirmPasswordReset(auth, oobCode, newPassword) {
- await resetPassword(util.getModularInstance(auth), {
- oobCode,
- newPassword
- });
- // Do not return the email.
- }
- /**
- * Applies a verification code sent to the user by email or other out-of-band mechanism.
- *
- * @param auth - The {@link Auth} instance.
- * @param oobCode - A verification code sent to the user.
- *
- * @public
- */
- async function applyActionCode(auth, oobCode) {
- await applyActionCode$1(util.getModularInstance(auth), { oobCode });
- }
- /**
- * Checks a verification code sent to the user by email or other out-of-band mechanism.
- *
- * @returns metadata about the code.
- *
- * @param auth - The {@link Auth} instance.
- * @param oobCode - A verification code sent to the user.
- *
- * @public
- */
- async function checkActionCode(auth, oobCode) {
- const authModular = util.getModularInstance(auth);
- const response = await resetPassword(authModular, { oobCode });
- // Email could be empty only if the request type is EMAIL_SIGNIN or
- // VERIFY_AND_CHANGE_EMAIL.
- // New email should not be empty if the request type is
- // VERIFY_AND_CHANGE_EMAIL.
- // Multi-factor info could not be empty if the request type is
- // REVERT_SECOND_FACTOR_ADDITION.
- const operation = response.requestType;
- _assert(operation, authModular, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- switch (operation) {
- case "EMAIL_SIGNIN" /* ActionCodeOperation.EMAIL_SIGNIN */:
- break;
- case "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */:
- _assert(response.newEmail, authModular, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- break;
- case "REVERT_SECOND_FACTOR_ADDITION" /* ActionCodeOperation.REVERT_SECOND_FACTOR_ADDITION */:
- _assert(response.mfaInfo, authModular, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- // fall through
- default:
- _assert(response.email, authModular, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- // The multi-factor info for revert second factor addition
- let multiFactorInfo = null;
- if (response.mfaInfo) {
- multiFactorInfo = MultiFactorInfoImpl._fromServerResponse(_castAuth(authModular), response.mfaInfo);
- }
- return {
- data: {
- email: (response.requestType === "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
- ? response.newEmail
- : response.email) || null,
- previousEmail: (response.requestType === "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
- ? response.email
- : response.newEmail) || null,
- multiFactorInfo
- },
- operation
- };
- }
- /**
- * Checks a password reset code sent to the user by email or other out-of-band mechanism.
- *
- * @returns the user's email address if valid.
- *
- * @param auth - The {@link Auth} instance.
- * @param code - A verification code sent to the user.
- *
- * @public
- */
- async function verifyPasswordResetCode(auth, code) {
- const { data } = await checkActionCode(util.getModularInstance(auth), code);
- // Email should always be present since a code was sent to it
- return data.email;
- }
- /**
- * Creates a new user account associated with the specified email address and password.
- *
- * @remarks
- * On successful creation of the user account, this user will also be signed in to your application.
- *
- * User account creation can fail if the account already exists or the password is invalid.
- *
- * Note: The email address acts as a unique identifier for the user and enables an email-based
- * password reset. This function will create a new user account and set the initial user password.
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The user's email address.
- * @param password - The user's chosen password.
- *
- * @public
- */
- async function createUserWithEmailAndPassword(auth, email, password) {
- var _a;
- const authInternal = _castAuth(auth);
- const request = {
- returnSecureToken: true,
- email,
- password,
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
- };
- let signUpResponse;
- if ((_a = authInternal._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "signUpPassword" /* RecaptchaActionName.SIGN_UP_PASSWORD */);
- signUpResponse = signUp(authInternal, requestWithRecaptcha);
- }
- else {
- signUpResponse = signUp(authInternal, request).catch(async (error) => {
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
- console.log('Sign-up is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-up flow.');
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "signUpPassword" /* RecaptchaActionName.SIGN_UP_PASSWORD */);
- return signUp(authInternal, requestWithRecaptcha);
- }
- else {
- return Promise.reject(error);
- }
- });
- }
- const response = await signUpResponse.catch(error => {
- return Promise.reject(error);
- });
- const userCredential = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn" /* OperationType.SIGN_IN */, response);
- await authInternal._updateCurrentUser(userCredential.user);
- return userCredential;
- }
- /**
- * Asynchronously signs in using an email and password.
- *
- * @remarks
- * Fails with an error if the email address and password do not match.
- *
- * Note: The user's password is NOT the password used to access the user's email account. The
- * email address serves as a unique identifier for the user, and the password is used to access
- * the user's account in your Firebase project. See also: {@link createUserWithEmailAndPassword}.
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The users email address.
- * @param password - The users password.
- *
- * @public
- */
- function signInWithEmailAndPassword(auth, email, password) {
- return signInWithCredential(util.getModularInstance(auth), EmailAuthProvider.credential(email, password));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Sends a sign-in email link to the user with the specified email.
- *
- * @remarks
- * The sign-in operation has to always be completed in the app unlike other out of band email
- * actions (password reset and email verifications). This is because, at the end of the flow,
- * the user is expected to be signed in and their Auth state persisted within the app.
- *
- * To complete sign in with the email link, call {@link signInWithEmailLink} with the email
- * address and the email link supplied in the email sent to the user.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings);
- * // Obtain emailLink from the user.
- * if(isSignInWithEmailLink(auth, emailLink)) {
- * await signInWithEmailLink(auth, 'user@example.com', emailLink);
- * }
- * ```
- *
- * @param authInternal - The {@link Auth} instance.
- * @param email - The user's email address.
- * @param actionCodeSettings - The {@link ActionCodeSettings}.
- *
- * @public
- */
- async function sendSignInLinkToEmail(auth, email, actionCodeSettings) {
- var _a;
- const authInternal = _castAuth(auth);
- const request = {
- requestType: "EMAIL_SIGNIN" /* ActionCodeOperation.EMAIL_SIGNIN */,
- email,
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
- };
- function setActionCodeSettings(request, actionCodeSettings) {
- _assert(actionCodeSettings.handleCodeInApp, authInternal, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(authInternal, request, actionCodeSettings);
- }
- }
- if ((_a = authInternal._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
- setActionCodeSettings(requestWithRecaptcha, actionCodeSettings);
- await sendSignInLinkToEmail$1(authInternal, requestWithRecaptcha);
- }
- else {
- setActionCodeSettings(request, actionCodeSettings);
- await sendSignInLinkToEmail$1(authInternal, request)
- .catch(async (error) => {
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
- console.log('Email link sign-in is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-in flow.');
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
- setActionCodeSettings(requestWithRecaptcha, actionCodeSettings);
- await sendSignInLinkToEmail$1(authInternal, requestWithRecaptcha);
- }
- else {
- return Promise.reject(error);
- }
- });
- }
- }
- /**
- * Checks if an incoming link is a sign-in with email link suitable for {@link signInWithEmailLink}.
- *
- * @param auth - The {@link Auth} instance.
- * @param emailLink - The link sent to the user's email address.
- *
- * @public
- */
- function isSignInWithEmailLink(auth, emailLink) {
- const actionCodeUrl = ActionCodeURL.parseLink(emailLink);
- return (actionCodeUrl === null || actionCodeUrl === void 0 ? void 0 : actionCodeUrl.operation) === "EMAIL_SIGNIN" /* ActionCodeOperation.EMAIL_SIGNIN */;
- }
- /**
- * Asynchronously signs in using an email and sign-in email link.
- *
- * @remarks
- * If no link is passed, the link is inferred from the current URL.
- *
- * Fails with an error if the email address is invalid or OTP in email link expires.
- *
- * Note: Confirm the link is a sign-in email link before calling this method firebase.auth.Auth.isSignInWithEmailLink.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings);
- * // Obtain emailLink from the user.
- * if(isSignInWithEmailLink(auth, emailLink)) {
- * await signInWithEmailLink(auth, 'user@example.com', emailLink);
- * }
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The user's email address.
- * @param emailLink - The link sent to the user's email address.
- *
- * @public
- */
- async function signInWithEmailLink(auth, email, emailLink) {
- const authModular = util.getModularInstance(auth);
- const credential = EmailAuthProvider.credentialWithLink(email, emailLink || _getCurrentUrl());
- // Check if the tenant ID in the email link matches the tenant ID on Auth
- // instance.
- _assert(credential._tenantId === (authModular.tenantId || null), authModular, "tenant-id-mismatch" /* AuthErrorCode.TENANT_ID_MISMATCH */);
- return signInWithCredential(authModular, credential);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function createAuthUri(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:createAuthUri" /* Endpoint.CREATE_AUTH_URI */, _addTidIfNecessary(auth, request));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Gets the list of possible sign in methods for the given email address.
- *
- * @remarks
- * This is useful to differentiate methods of sign-in for the same provider, eg.
- * {@link EmailAuthProvider} which has 2 methods of sign-in,
- * {@link SignInMethod}.EMAIL_PASSWORD and
- * {@link SignInMethod}.EMAIL_LINK.
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The user's email address.
- *
- * @public
- */
- async function fetchSignInMethodsForEmail(auth, email) {
- // createAuthUri returns an error if continue URI is not http or https.
- // For environments like Cordova, Chrome extensions, native frameworks, file
- // systems, etc, use http://localhost as continue URL.
- const continueUri = _isHttpOrHttps() ? _getCurrentUrl() : 'http://localhost';
- const request = {
- identifier: email,
- continueUri
- };
- const { signinMethods } = await createAuthUri(util.getModularInstance(auth), request);
- return signinMethods || [];
- }
- /**
- * Sends a verification email to a user.
- *
- * @remarks
- * The verification process is completed by calling {@link applyActionCode}.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await sendEmailVerification(user, actionCodeSettings);
- * // Obtain code from the user.
- * await applyActionCode(auth, code);
- * ```
- *
- * @param user - The user.
- * @param actionCodeSettings - The {@link ActionCodeSettings}.
- *
- * @public
- */
- async function sendEmailVerification(user, actionCodeSettings) {
- const userInternal = util.getModularInstance(user);
- const idToken = await user.getIdToken();
- const request = {
- requestType: "VERIFY_EMAIL" /* ActionCodeOperation.VERIFY_EMAIL */,
- idToken
- };
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(userInternal.auth, request, actionCodeSettings);
- }
- const { email } = await sendEmailVerification$1(userInternal.auth, request);
- if (email !== user.email) {
- await user.reload();
- }
- }
- /**
- * Sends a verification email to a new email address.
- *
- * @remarks
- * The user's email will be updated to the new one after being verified.
- *
- * If you have a custom email action handler, you can complete the verification process by calling
- * {@link applyActionCode}.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await verifyBeforeUpdateEmail(user, 'newemail@example.com', actionCodeSettings);
- * // Obtain code from the user.
- * await applyActionCode(auth, code);
- * ```
- *
- * @param user - The user.
- * @param newEmail - The new email address to be verified before update.
- * @param actionCodeSettings - The {@link ActionCodeSettings}.
- *
- * @public
- */
- async function verifyBeforeUpdateEmail(user, newEmail, actionCodeSettings) {
- const userInternal = util.getModularInstance(user);
- const idToken = await user.getIdToken();
- const request = {
- requestType: "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */,
- idToken,
- newEmail
- };
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(userInternal.auth, request, actionCodeSettings);
- }
- const { email } = await verifyAndChangeEmail(userInternal.auth, request);
- if (email !== user.email) {
- // If the local copy of the email on user is outdated, reload the
- // user.
- await user.reload();
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function updateProfile$1(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, request);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Updates a user's profile data.
- *
- * @param user - The user.
- * @param profile - The profile's `displayName` and `photoURL` to update.
- *
- * @public
- */
- async function updateProfile(user, { displayName, photoURL: photoUrl }) {
- if (displayName === undefined && photoUrl === undefined) {
- return;
- }
- const userInternal = util.getModularInstance(user);
- const idToken = await userInternal.getIdToken();
- const profileRequest = {
- idToken,
- displayName,
- photoUrl,
- returnSecureToken: true
- };
- const response = await _logoutIfInvalidated(userInternal, updateProfile$1(userInternal.auth, profileRequest));
- userInternal.displayName = response.displayName || null;
- userInternal.photoURL = response.photoUrl || null;
- // Update the password provider as well
- const passwordProvider = userInternal.providerData.find(({ providerId }) => providerId === "password" /* ProviderId.PASSWORD */);
- if (passwordProvider) {
- passwordProvider.displayName = userInternal.displayName;
- passwordProvider.photoURL = userInternal.photoURL;
- }
- await userInternal._updateTokensIfNecessary(response);
- }
- /**
- * Updates the user's email address.
- *
- * @remarks
- * An email will be sent to the original email address (if it was set) that allows to revoke the
- * email address change, in order to protect them from account hijacking.
- *
- * Important: this is a security sensitive operation that requires the user to have recently signed
- * in. If this requirement isn't met, ask the user to authenticate again and then call
- * {@link reauthenticateWithCredential}.
- *
- * @param user - The user.
- * @param newEmail - The new email address.
- *
- * @public
- */
- function updateEmail(user, newEmail) {
- return updateEmailOrPassword(util.getModularInstance(user), newEmail, null);
- }
- /**
- * Updates the user's password.
- *
- * @remarks
- * Important: this is a security sensitive operation that requires the user to have recently signed
- * in. If this requirement isn't met, ask the user to authenticate again and then call
- * {@link reauthenticateWithCredential}.
- *
- * @param user - The user.
- * @param newPassword - The new password.
- *
- * @public
- */
- function updatePassword(user, newPassword) {
- return updateEmailOrPassword(util.getModularInstance(user), null, newPassword);
- }
- async function updateEmailOrPassword(user, email, password) {
- const { auth } = user;
- const idToken = await user.getIdToken();
- const request = {
- idToken,
- returnSecureToken: true
- };
- if (email) {
- request.email = email;
- }
- if (password) {
- request.password = password;
- }
- const response = await _logoutIfInvalidated(user, updateEmailPassword(auth, request));
- await user._updateTokensIfNecessary(response, /* reload */ true);
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Parse the `AdditionalUserInfo` from the ID token response.
- *
- */
- function _fromIdTokenResponse(idTokenResponse) {
- var _a, _b;
- if (!idTokenResponse) {
- return null;
- }
- const { providerId } = idTokenResponse;
- const profile = idTokenResponse.rawUserInfo
- ? JSON.parse(idTokenResponse.rawUserInfo)
- : {};
- const isNewUser = idTokenResponse.isNewUser ||
- idTokenResponse.kind === "identitytoolkit#SignupNewUserResponse" /* IdTokenResponseKind.SignupNewUser */;
- if (!providerId && (idTokenResponse === null || idTokenResponse === void 0 ? void 0 : idTokenResponse.idToken)) {
- const signInProvider = (_b = (_a = _parseToken(idTokenResponse.idToken)) === null || _a === void 0 ? void 0 : _a.firebase) === null || _b === void 0 ? void 0 : _b['sign_in_provider'];
- if (signInProvider) {
- const filteredProviderId = signInProvider !== "anonymous" /* ProviderId.ANONYMOUS */ &&
- signInProvider !== "custom" /* ProviderId.CUSTOM */
- ? signInProvider
- : null;
- // Uses generic class in accordance with the legacy SDK.
- return new GenericAdditionalUserInfo(isNewUser, filteredProviderId);
- }
- }
- if (!providerId) {
- return null;
- }
- switch (providerId) {
- case "facebook.com" /* ProviderId.FACEBOOK */:
- return new FacebookAdditionalUserInfo(isNewUser, profile);
- case "github.com" /* ProviderId.GITHUB */:
- return new GithubAdditionalUserInfo(isNewUser, profile);
- case "google.com" /* ProviderId.GOOGLE */:
- return new GoogleAdditionalUserInfo(isNewUser, profile);
- case "twitter.com" /* ProviderId.TWITTER */:
- return new TwitterAdditionalUserInfo(isNewUser, profile, idTokenResponse.screenName || null);
- case "custom" /* ProviderId.CUSTOM */:
- case "anonymous" /* ProviderId.ANONYMOUS */:
- return new GenericAdditionalUserInfo(isNewUser, null);
- default:
- return new GenericAdditionalUserInfo(isNewUser, providerId, profile);
- }
- }
- class GenericAdditionalUserInfo {
- constructor(isNewUser, providerId, profile = {}) {
- this.isNewUser = isNewUser;
- this.providerId = providerId;
- this.profile = profile;
- }
- }
- class FederatedAdditionalUserInfoWithUsername extends GenericAdditionalUserInfo {
- constructor(isNewUser, providerId, profile, username) {
- super(isNewUser, providerId, profile);
- this.username = username;
- }
- }
- class FacebookAdditionalUserInfo extends GenericAdditionalUserInfo {
- constructor(isNewUser, profile) {
- super(isNewUser, "facebook.com" /* ProviderId.FACEBOOK */, profile);
- }
- }
- class GithubAdditionalUserInfo extends FederatedAdditionalUserInfoWithUsername {
- constructor(isNewUser, profile) {
- super(isNewUser, "github.com" /* ProviderId.GITHUB */, profile, typeof (profile === null || profile === void 0 ? void 0 : profile.login) === 'string' ? profile === null || profile === void 0 ? void 0 : profile.login : null);
- }
- }
- class GoogleAdditionalUserInfo extends GenericAdditionalUserInfo {
- constructor(isNewUser, profile) {
- super(isNewUser, "google.com" /* ProviderId.GOOGLE */, profile);
- }
- }
- class TwitterAdditionalUserInfo extends FederatedAdditionalUserInfoWithUsername {
- constructor(isNewUser, profile, screenName) {
- super(isNewUser, "twitter.com" /* ProviderId.TWITTER */, profile, screenName);
- }
- }
- /**
- * Extracts provider specific {@link AdditionalUserInfo} for the given credential.
- *
- * @param userCredential - The user credential.
- *
- * @public
- */
- function getAdditionalUserInfo(userCredential) {
- const { user, _tokenResponse } = userCredential;
- if (user.isAnonymous && !_tokenResponse) {
- // Handle the special case where signInAnonymously() gets called twice.
- // No network call is made so there's nothing to actually fill this in
- return {
- providerId: null,
- isNewUser: false,
- profile: null
- };
- }
- return _fromIdTokenResponse(_tokenResponse);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // Non-optional auth methods.
- /**
- * Changes the type of persistence on the {@link Auth} instance for the currently saved
- * `Auth` session and applies this type of persistence for future sign-in requests, including
- * sign-in with redirect requests.
- *
- * @remarks
- * This makes it easy for a user signing in to specify whether their session should be
- * remembered or not. It also makes it easier to never persist the `Auth` state for applications
- * that are shared by other users or have sensitive data.
- *
- * @example
- * ```javascript
- * setPersistence(auth, browserSessionPersistence);
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param persistence - The {@link Persistence} to use.
- * @returns A `Promise` that resolves once the persistence change has completed
- *
- * @public
- */
- function setPersistence(auth, persistence) {
- return util.getModularInstance(auth).setPersistence(persistence);
- }
- /**
- * Loads the reCAPTCHA configuration into the `Auth` instance.
- *
- * @remarks
- * This will load the reCAPTCHA config, which indicates whether the reCAPTCHA
- * verification flow should be triggered for each auth provider, into the
- * current Auth session.
- *
- * If initializeRecaptchaConfig() is not invoked, the auth flow will always start
- * without reCAPTCHA verification. If the provider is configured to require reCAPTCHA
- * verification, the SDK will transparently load the reCAPTCHA config and restart the
- * auth flows.
- *
- * Thus, by calling this optional method, you will reduce the latency of future auth flows.
- * Loading the reCAPTCHA config early will also enhance the signal collected by reCAPTCHA.
- *
- * @example
- * ```javascript
- * initializeRecaptchaConfig(auth);
- * ```
- *
- * @param auth - The {@link Auth} instance.
- *
- * @public
- */
- function initializeRecaptchaConfig(auth) {
- const authInternal = _castAuth(auth);
- return authInternal.initializeRecaptchaConfig();
- }
- /**
- * Adds an observer for changes to the signed-in user's ID token.
- *
- * @remarks
- * This includes sign-in, sign-out, and token refresh events.
- * This will not be triggered automatically upon ID token expiration. Use {@link User.getIdToken} to refresh the ID token.
- *
- * @param auth - The {@link Auth} instance.
- * @param nextOrObserver - callback triggered on change.
- * @param error - Deprecated. This callback is never triggered. Errors
- * on signing in/out can be caught in promises returned from
- * sign-in/sign-out functions.
- * @param completed - Deprecated. This callback is never triggered.
- *
- * @public
- */
- function onIdTokenChanged(auth, nextOrObserver, error, completed) {
- return util.getModularInstance(auth).onIdTokenChanged(nextOrObserver, error, completed);
- }
- /**
- * Adds a blocking callback that runs before an auth state change
- * sets a new user.
- *
- * @param auth - The {@link Auth} instance.
- * @param callback - callback triggered before new user value is set.
- * If this throws, it blocks the user from being set.
- * @param onAbort - callback triggered if a later `beforeAuthStateChanged()`
- * callback throws, allowing you to undo any side effects.
- */
- function beforeAuthStateChanged(auth, callback, onAbort) {
- return util.getModularInstance(auth).beforeAuthStateChanged(callback, onAbort);
- }
- /**
- * Adds an observer for changes to the user's sign-in state.
- *
- * @remarks
- * To keep the old behavior, see {@link onIdTokenChanged}.
- *
- * @param auth - The {@link Auth} instance.
- * @param nextOrObserver - callback triggered on change.
- * @param error - Deprecated. This callback is never triggered. Errors
- * on signing in/out can be caught in promises returned from
- * sign-in/sign-out functions.
- * @param completed - Deprecated. This callback is never triggered.
- *
- * @public
- */
- function onAuthStateChanged(auth, nextOrObserver, error, completed) {
- return util.getModularInstance(auth).onAuthStateChanged(nextOrObserver, error, completed);
- }
- /**
- * Sets the current language to the default device/browser preference.
- *
- * @param auth - The {@link Auth} instance.
- *
- * @public
- */
- function useDeviceLanguage(auth) {
- util.getModularInstance(auth).useDeviceLanguage();
- }
- /**
- * Asynchronously sets the provided user as {@link Auth.currentUser} on the
- * {@link Auth} instance.
- *
- * @remarks
- * A new instance copy of the user provided will be made and set as currentUser.
- *
- * This will trigger {@link onAuthStateChanged} and {@link onIdTokenChanged} listeners
- * like other sign in methods.
- *
- * The operation fails with an error if the user to be updated belongs to a different Firebase
- * project.
- *
- * @param auth - The {@link Auth} instance.
- * @param user - The new {@link User}.
- *
- * @public
- */
- function updateCurrentUser(auth, user) {
- return util.getModularInstance(auth).updateCurrentUser(user);
- }
- /**
- * Signs out the current user.
- *
- * @param auth - The {@link Auth} instance.
- *
- * @public
- */
- function signOut(auth) {
- return util.getModularInstance(auth).signOut();
- }
- /**
- * Deletes and signs out the user.
- *
- * @remarks
- * Important: this is a security-sensitive operation that requires the user to have recently
- * signed in. If this requirement isn't met, ask the user to authenticate again and then call
- * {@link reauthenticateWithCredential}.
- *
- * @param user - The user.
- *
- * @public
- */
- async function deleteUser(user) {
- return util.getModularInstance(user).delete();
- }
- class MultiFactorSessionImpl {
- constructor(type, credential, auth) {
- this.type = type;
- this.credential = credential;
- this.auth = auth;
- }
- static _fromIdtoken(idToken, auth) {
- return new MultiFactorSessionImpl("enroll" /* MultiFactorSessionType.ENROLL */, idToken, auth);
- }
- static _fromMfaPendingCredential(mfaPendingCredential) {
- return new MultiFactorSessionImpl("signin" /* MultiFactorSessionType.SIGN_IN */, mfaPendingCredential);
- }
- toJSON() {
- const key = this.type === "enroll" /* MultiFactorSessionType.ENROLL */
- ? 'idToken'
- : 'pendingCredential';
- return {
- multiFactorSession: {
- [key]: this.credential
- }
- };
- }
- static fromJSON(obj) {
- var _a, _b;
- if (obj === null || obj === void 0 ? void 0 : obj.multiFactorSession) {
- if ((_a = obj.multiFactorSession) === null || _a === void 0 ? void 0 : _a.pendingCredential) {
- return MultiFactorSessionImpl._fromMfaPendingCredential(obj.multiFactorSession.pendingCredential);
- }
- else if ((_b = obj.multiFactorSession) === null || _b === void 0 ? void 0 : _b.idToken) {
- return MultiFactorSessionImpl._fromIdtoken(obj.multiFactorSession.idToken);
- }
- }
- return null;
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class MultiFactorResolverImpl {
- constructor(session, hints, signInResolver) {
- this.session = session;
- this.hints = hints;
- this.signInResolver = signInResolver;
- }
- /** @internal */
- static _fromError(authExtern, error) {
- const auth = _castAuth(authExtern);
- const serverResponse = error.customData._serverResponse;
- const hints = (serverResponse.mfaInfo || []).map(enrollment => MultiFactorInfoImpl._fromServerResponse(auth, enrollment));
- _assert(serverResponse.mfaPendingCredential, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const session = MultiFactorSessionImpl._fromMfaPendingCredential(serverResponse.mfaPendingCredential);
- return new MultiFactorResolverImpl(session, hints, async (assertion) => {
- const mfaResponse = await assertion._process(auth, session);
- // Clear out the unneeded fields from the old login response
- delete serverResponse.mfaInfo;
- delete serverResponse.mfaPendingCredential;
- // Use in the new token & refresh token in the old response
- const idTokenResponse = Object.assign(Object.assign({}, serverResponse), { idToken: mfaResponse.idToken, refreshToken: mfaResponse.refreshToken });
- // TODO: we should collapse this switch statement into UserCredentialImpl._forOperation and have it support the SIGN_IN case
- switch (error.operationType) {
- case "signIn" /* OperationType.SIGN_IN */:
- const userCredential = await UserCredentialImpl._fromIdTokenResponse(auth, error.operationType, idTokenResponse);
- await auth._updateCurrentUser(userCredential.user);
- return userCredential;
- case "reauthenticate" /* OperationType.REAUTHENTICATE */:
- _assert(error.user, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return UserCredentialImpl._forOperation(error.user, error.operationType, idTokenResponse);
- default:
- _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- });
- }
- async resolveSignIn(assertionExtern) {
- const assertion = assertionExtern;
- return this.signInResolver(assertion);
- }
- }
- /**
- * Provides a {@link MultiFactorResolver} suitable for completion of a
- * multi-factor flow.
- *
- * @param auth - The {@link Auth} instance.
- * @param error - The {@link MultiFactorError} raised during a sign-in, or
- * reauthentication operation.
- *
- * @public
- */
- function getMultiFactorResolver(auth, error) {
- var _a;
- const authModular = util.getModularInstance(auth);
- const errorInternal = error;
- _assert(error.customData.operationType, authModular, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- _assert((_a = errorInternal.customData._serverResponse) === null || _a === void 0 ? void 0 : _a.mfaPendingCredential, authModular, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return MultiFactorResolverImpl._fromError(authModular, errorInternal);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function startEnrollPhoneMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaEnrollment:start" /* Endpoint.START_MFA_ENROLLMENT */, _addTidIfNecessary(auth, request));
- }
- function finalizeEnrollPhoneMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaEnrollment:finalize" /* Endpoint.FINALIZE_MFA_ENROLLMENT */, _addTidIfNecessary(auth, request));
- }
- function startEnrollTotpMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaEnrollment:start" /* Endpoint.START_MFA_ENROLLMENT */, _addTidIfNecessary(auth, request));
- }
- function finalizeEnrollTotpMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaEnrollment:finalize" /* Endpoint.FINALIZE_MFA_ENROLLMENT */, _addTidIfNecessary(auth, request));
- }
- function withdrawMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaEnrollment:withdraw" /* Endpoint.WITHDRAW_MFA */, _addTidIfNecessary(auth, request));
- }
- class MultiFactorUserImpl {
- constructor(user) {
- this.user = user;
- this.enrolledFactors = [];
- user._onReload(userInfo => {
- if (userInfo.mfaInfo) {
- this.enrolledFactors = userInfo.mfaInfo.map(enrollment => MultiFactorInfoImpl._fromServerResponse(user.auth, enrollment));
- }
- });
- }
- static _fromUser(user) {
- return new MultiFactorUserImpl(user);
- }
- async getSession() {
- return MultiFactorSessionImpl._fromIdtoken(await this.user.getIdToken(), this.user.auth);
- }
- async enroll(assertionExtern, displayName) {
- const assertion = assertionExtern;
- const session = (await this.getSession());
- const finalizeMfaResponse = await _logoutIfInvalidated(this.user, assertion._process(this.user.auth, session, displayName));
- // New tokens will be issued after enrollment of the new second factors.
- // They need to be updated on the user.
- await this.user._updateTokensIfNecessary(finalizeMfaResponse);
- // The user needs to be reloaded to get the new multi-factor information
- // from server. USER_RELOADED event will be triggered and `enrolledFactors`
- // will be updated.
- return this.user.reload();
- }
- async unenroll(infoOrUid) {
- const mfaEnrollmentId = typeof infoOrUid === 'string' ? infoOrUid : infoOrUid.uid;
- const idToken = await this.user.getIdToken();
- try {
- const idTokenResponse = await _logoutIfInvalidated(this.user, withdrawMfa(this.user.auth, {
- idToken,
- mfaEnrollmentId
- }));
- // Remove the second factor from the user's list.
- this.enrolledFactors = this.enrolledFactors.filter(({ uid }) => uid !== mfaEnrollmentId);
- // Depending on whether the backend decided to revoke the user's session,
- // the tokenResponse may be empty. If the tokens were not updated (and they
- // are now invalid), reloading the user will discover this and invalidate
- // the user's state accordingly.
- await this.user._updateTokensIfNecessary(idTokenResponse);
- await this.user.reload();
- }
- catch (e) {
- throw e;
- }
- }
- }
- const multiFactorUserCache = new WeakMap();
- /**
- * The {@link MultiFactorUser} corresponding to the user.
- *
- * @remarks
- * This is used to access all multi-factor properties and operations related to the user.
- *
- * @param user - The user.
- *
- * @public
- */
- function multiFactor(user) {
- const userModular = util.getModularInstance(user);
- if (!multiFactorUserCache.has(userModular)) {
- multiFactorUserCache.set(userModular, MultiFactorUserImpl._fromUser(userModular));
- }
- return multiFactorUserCache.get(userModular);
- }
- const STORAGE_AVAILABLE_KEY = '__sak';
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // There are two different browser persistence types: local and session.
- // Both have the same implementation but use a different underlying storage
- // object.
- class BrowserPersistenceClass {
- constructor(storageRetriever, type) {
- this.storageRetriever = storageRetriever;
- this.type = type;
- }
- _isAvailable() {
- try {
- if (!this.storage) {
- return Promise.resolve(false);
- }
- this.storage.setItem(STORAGE_AVAILABLE_KEY, '1');
- this.storage.removeItem(STORAGE_AVAILABLE_KEY);
- return Promise.resolve(true);
- }
- catch (_a) {
- return Promise.resolve(false);
- }
- }
- _set(key, value) {
- this.storage.setItem(key, JSON.stringify(value));
- return Promise.resolve();
- }
- _get(key) {
- const json = this.storage.getItem(key);
- return Promise.resolve(json ? JSON.parse(json) : null);
- }
- _remove(key) {
- this.storage.removeItem(key);
- return Promise.resolve();
- }
- get storage() {
- return this.storageRetriever();
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _iframeCannotSyncWebStorage() {
- const ua = util.getUA();
- return _isSafari(ua) || _isIOS(ua);
- }
- // The polling period in case events are not supported
- const _POLLING_INTERVAL_MS$1 = 1000;
- // The IE 10 localStorage cross tab synchronization delay in milliseconds
- const IE10_LOCAL_STORAGE_SYNC_DELAY = 10;
- class BrowserLocalPersistence extends BrowserPersistenceClass {
- constructor() {
- super(() => window.localStorage, "LOCAL" /* PersistenceType.LOCAL */);
- this.boundEventHandler = (event, poll) => this.onStorageEvent(event, poll);
- this.listeners = {};
- this.localCache = {};
- // setTimeout return value is platform specific
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.pollTimer = null;
- // Safari or iOS browser and embedded in an iframe.
- this.safariLocalStorageNotSynced = _iframeCannotSyncWebStorage() && _isIframe();
- // Whether to use polling instead of depending on window events
- this.fallbackToPolling = _isMobileBrowser();
- this._shouldAllowMigration = true;
- }
- forAllChangedKeys(cb) {
- // Check all keys with listeners on them.
- for (const key of Object.keys(this.listeners)) {
- // Get value from localStorage.
- const newValue = this.storage.getItem(key);
- const oldValue = this.localCache[key];
- // If local map value does not match, trigger listener with storage event.
- // Differentiate this simulated event from the real storage event.
- if (newValue !== oldValue) {
- cb(key, oldValue, newValue);
- }
- }
- }
- onStorageEvent(event, poll = false) {
- // Key would be null in some situations, like when localStorage is cleared
- if (!event.key) {
- this.forAllChangedKeys((key, _oldValue, newValue) => {
- this.notifyListeners(key, newValue);
- });
- return;
- }
- const key = event.key;
- // Check the mechanism how this event was detected.
- // The first event will dictate the mechanism to be used.
- if (poll) {
- // Environment detects storage changes via polling.
- // Remove storage event listener to prevent possible event duplication.
- this.detachListener();
- }
- else {
- // Environment detects storage changes via storage event listener.
- // Remove polling listener to prevent possible event duplication.
- this.stopPolling();
- }
- // Safari embedded iframe. Storage event will trigger with the delta
- // changes but no changes will be applied to the iframe localStorage.
- if (this.safariLocalStorageNotSynced) {
- // Get current iframe page value.
- const storedValue = this.storage.getItem(key);
- // Value not synchronized, synchronize manually.
- if (event.newValue !== storedValue) {
- if (event.newValue !== null) {
- // Value changed from current value.
- this.storage.setItem(key, event.newValue);
- }
- else {
- // Current value deleted.
- this.storage.removeItem(key);
- }
- }
- else if (this.localCache[key] === event.newValue && !poll) {
- // Already detected and processed, do not trigger listeners again.
- return;
- }
- }
- const triggerListeners = () => {
- // Keep local map up to date in case storage event is triggered before
- // poll.
- const storedValue = this.storage.getItem(key);
- if (!poll && this.localCache[key] === storedValue) {
- // Real storage event which has already been detected, do nothing.
- // This seems to trigger in some IE browsers for some reason.
- return;
- }
- this.notifyListeners(key, storedValue);
- };
- const storedValue = this.storage.getItem(key);
- if (_isIE10() &&
- storedValue !== event.newValue &&
- event.newValue !== event.oldValue) {
- // IE 10 has this weird bug where a storage event would trigger with the
- // correct key, oldValue and newValue but localStorage.getItem(key) does
- // not yield the updated value until a few milliseconds. This ensures
- // this recovers from that situation.
- setTimeout(triggerListeners, IE10_LOCAL_STORAGE_SYNC_DELAY);
- }
- else {
- triggerListeners();
- }
- }
- notifyListeners(key, value) {
- this.localCache[key] = value;
- const listeners = this.listeners[key];
- if (listeners) {
- for (const listener of Array.from(listeners)) {
- listener(value ? JSON.parse(value) : value);
- }
- }
- }
- startPolling() {
- this.stopPolling();
- this.pollTimer = setInterval(() => {
- this.forAllChangedKeys((key, oldValue, newValue) => {
- this.onStorageEvent(new StorageEvent('storage', {
- key,
- oldValue,
- newValue
- }),
- /* poll */ true);
- });
- }, _POLLING_INTERVAL_MS$1);
- }
- stopPolling() {
- if (this.pollTimer) {
- clearInterval(this.pollTimer);
- this.pollTimer = null;
- }
- }
- attachListener() {
- window.addEventListener('storage', this.boundEventHandler);
- }
- detachListener() {
- window.removeEventListener('storage', this.boundEventHandler);
- }
- _addListener(key, listener) {
- if (Object.keys(this.listeners).length === 0) {
- // Whether browser can detect storage event when it had already been pushed to the background.
- // This may happen in some mobile browsers. A localStorage change in the foreground window
- // will not be detected in the background window via the storage event.
- // This was detected in iOS 7.x mobile browsers
- if (this.fallbackToPolling) {
- this.startPolling();
- }
- else {
- this.attachListener();
- }
- }
- if (!this.listeners[key]) {
- this.listeners[key] = new Set();
- // Populate the cache to avoid spuriously triggering on first poll.
- this.localCache[key] = this.storage.getItem(key);
- }
- this.listeners[key].add(listener);
- }
- _removeListener(key, listener) {
- if (this.listeners[key]) {
- this.listeners[key].delete(listener);
- if (this.listeners[key].size === 0) {
- delete this.listeners[key];
- }
- }
- if (Object.keys(this.listeners).length === 0) {
- this.detachListener();
- this.stopPolling();
- }
- }
- // Update local cache on base operations:
- async _set(key, value) {
- await super._set(key, value);
- this.localCache[key] = JSON.stringify(value);
- }
- async _get(key) {
- const value = await super._get(key);
- this.localCache[key] = JSON.stringify(value);
- return value;
- }
- async _remove(key) {
- await super._remove(key);
- delete this.localCache[key];
- }
- }
- BrowserLocalPersistence.type = 'LOCAL';
- /**
- * An implementation of {@link Persistence} of type `LOCAL` using `localStorage`
- * for the underlying storage.
- *
- * @public
- */
- const browserLocalPersistence = BrowserLocalPersistence;
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class BrowserSessionPersistence extends BrowserPersistenceClass {
- constructor() {
- super(() => window.sessionStorage, "SESSION" /* PersistenceType.SESSION */);
- }
- _addListener(_key, _listener) {
- // Listeners are not supported for session storage since it cannot be shared across windows
- return;
- }
- _removeListener(_key, _listener) {
- // Listeners are not supported for session storage since it cannot be shared across windows
- return;
- }
- }
- BrowserSessionPersistence.type = 'SESSION';
- /**
- * An implementation of {@link Persistence} of `SESSION` using `sessionStorage`
- * for the underlying storage.
- *
- * @public
- */
- const browserSessionPersistence = BrowserSessionPersistence;
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Shim for Promise.allSettled, note the slightly different format of `fulfilled` vs `status`.
- *
- * @param promises - Array of promises to wait on.
- */
- function _allSettled(promises) {
- return Promise.all(promises.map(async (promise) => {
- try {
- const value = await promise;
- return {
- fulfilled: true,
- value
- };
- }
- catch (reason) {
- return {
- fulfilled: false,
- reason
- };
- }
- }));
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Interface class for receiving messages.
- *
- */
- class Receiver {
- constructor(eventTarget) {
- this.eventTarget = eventTarget;
- this.handlersMap = {};
- this.boundEventHandler = this.handleEvent.bind(this);
- }
- /**
- * Obtain an instance of a Receiver for a given event target, if none exists it will be created.
- *
- * @param eventTarget - An event target (such as window or self) through which the underlying
- * messages will be received.
- */
- static _getInstance(eventTarget) {
- // The results are stored in an array since objects can't be keys for other
- // objects. In addition, setting a unique property on an event target as a
- // hash map key may not be allowed due to CORS restrictions.
- const existingInstance = this.receivers.find(receiver => receiver.isListeningto(eventTarget));
- if (existingInstance) {
- return existingInstance;
- }
- const newInstance = new Receiver(eventTarget);
- this.receivers.push(newInstance);
- return newInstance;
- }
- isListeningto(eventTarget) {
- return this.eventTarget === eventTarget;
- }
- /**
- * Fans out a MessageEvent to the appropriate listeners.
- *
- * @remarks
- * Sends an {@link Status.ACK} upon receipt and a {@link Status.DONE} once all handlers have
- * finished processing.
- *
- * @param event - The MessageEvent.
- *
- */
- async handleEvent(event) {
- const messageEvent = event;
- const { eventId, eventType, data } = messageEvent.data;
- const handlers = this.handlersMap[eventType];
- if (!(handlers === null || handlers === void 0 ? void 0 : handlers.size)) {
- return;
- }
- messageEvent.ports[0].postMessage({
- status: "ack" /* _Status.ACK */,
- eventId,
- eventType
- });
- const promises = Array.from(handlers).map(async (handler) => handler(messageEvent.origin, data));
- const response = await _allSettled(promises);
- messageEvent.ports[0].postMessage({
- status: "done" /* _Status.DONE */,
- eventId,
- eventType,
- response
- });
- }
- /**
- * Subscribe an event handler for a particular event.
- *
- * @param eventType - Event name to subscribe to.
- * @param eventHandler - The event handler which should receive the events.
- *
- */
- _subscribe(eventType, eventHandler) {
- if (Object.keys(this.handlersMap).length === 0) {
- this.eventTarget.addEventListener('message', this.boundEventHandler);
- }
- if (!this.handlersMap[eventType]) {
- this.handlersMap[eventType] = new Set();
- }
- this.handlersMap[eventType].add(eventHandler);
- }
- /**
- * Unsubscribe an event handler from a particular event.
- *
- * @param eventType - Event name to unsubscribe from.
- * @param eventHandler - Optinoal event handler, if none provided, unsubscribe all handlers on this event.
- *
- */
- _unsubscribe(eventType, eventHandler) {
- if (this.handlersMap[eventType] && eventHandler) {
- this.handlersMap[eventType].delete(eventHandler);
- }
- if (!eventHandler || this.handlersMap[eventType].size === 0) {
- delete this.handlersMap[eventType];
- }
- if (Object.keys(this.handlersMap).length === 0) {
- this.eventTarget.removeEventListener('message', this.boundEventHandler);
- }
- }
- }
- Receiver.receivers = [];
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _generateEventId(prefix = '', digits = 10) {
- let random = '';
- for (let i = 0; i < digits; i++) {
- random += Math.floor(Math.random() * 10);
- }
- return prefix + random;
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Interface for sending messages and waiting for a completion response.
- *
- */
- class Sender {
- constructor(target) {
- this.target = target;
- this.handlers = new Set();
- }
- /**
- * Unsubscribe the handler and remove it from our tracking Set.
- *
- * @param handler - The handler to unsubscribe.
- */
- removeMessageHandler(handler) {
- if (handler.messageChannel) {
- handler.messageChannel.port1.removeEventListener('message', handler.onMessage);
- handler.messageChannel.port1.close();
- }
- this.handlers.delete(handler);
- }
- /**
- * Send a message to the Receiver located at {@link target}.
- *
- * @remarks
- * We'll first wait a bit for an ACK , if we get one we will wait significantly longer until the
- * receiver has had a chance to fully process the event.
- *
- * @param eventType - Type of event to send.
- * @param data - The payload of the event.
- * @param timeout - Timeout for waiting on an ACK from the receiver.
- *
- * @returns An array of settled promises from all the handlers that were listening on the receiver.
- */
- async _send(eventType, data, timeout = 50 /* _TimeoutDuration.ACK */) {
- const messageChannel = typeof MessageChannel !== 'undefined' ? new MessageChannel() : null;
- if (!messageChannel) {
- throw new Error("connection_unavailable" /* _MessageError.CONNECTION_UNAVAILABLE */);
- }
- // Node timers and browser timers return fundamentally different types.
- // We don't actually care what the value is but TS won't accept unknown and
- // we can't cast properly in both environments.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- let completionTimer;
- let handler;
- return new Promise((resolve, reject) => {
- const eventId = _generateEventId('', 20);
- messageChannel.port1.start();
- const ackTimer = setTimeout(() => {
- reject(new Error("unsupported_event" /* _MessageError.UNSUPPORTED_EVENT */));
- }, timeout);
- handler = {
- messageChannel,
- onMessage(event) {
- const messageEvent = event;
- if (messageEvent.data.eventId !== eventId) {
- return;
- }
- switch (messageEvent.data.status) {
- case "ack" /* _Status.ACK */:
- // The receiver should ACK first.
- clearTimeout(ackTimer);
- completionTimer = setTimeout(() => {
- reject(new Error("timeout" /* _MessageError.TIMEOUT */));
- }, 3000 /* _TimeoutDuration.COMPLETION */);
- break;
- case "done" /* _Status.DONE */:
- // Once the receiver's handlers are finished we will get the results.
- clearTimeout(completionTimer);
- resolve(messageEvent.data.response);
- break;
- default:
- clearTimeout(ackTimer);
- clearTimeout(completionTimer);
- reject(new Error("invalid_response" /* _MessageError.INVALID_RESPONSE */));
- break;
- }
- }
- };
- this.handlers.add(handler);
- messageChannel.port1.addEventListener('message', handler.onMessage);
- this.target.postMessage({
- eventType,
- eventId,
- data
- }, [messageChannel.port2]);
- }).finally(() => {
- if (handler) {
- this.removeMessageHandler(handler);
- }
- });
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Lazy accessor for window, since the compat layer won't tree shake this out,
- * we need to make sure not to mess with window unless we have to
- */
- function _window() {
- return window;
- }
- function _setWindowLocation(url) {
- _window().location.href = url;
- }
- /**
- * @license
- * Copyright 2020 Google LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _isWorker() {
- return (typeof _window()['WorkerGlobalScope'] !== 'undefined' &&
- typeof _window()['importScripts'] === 'function');
- }
- async function _getActiveServiceWorker() {
- if (!(navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker)) {
- return null;
- }
- try {
- const registration = await navigator.serviceWorker.ready;
- return registration.active;
- }
- catch (_a) {
- return null;
- }
- }
- function _getServiceWorkerController() {
- var _a;
- return ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker) === null || _a === void 0 ? void 0 : _a.controller) || null;
- }
- function _getWorkerGlobalScope() {
- return _isWorker() ? self : null;
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DB_NAME = 'firebaseLocalStorageDb';
- const DB_VERSION = 1;
- const DB_OBJECTSTORE_NAME = 'firebaseLocalStorage';
- const DB_DATA_KEYPATH = 'fbase_key';
- /**
- * Promise wrapper for IDBRequest
- *
- * Unfortunately we can't cleanly extend Promise<T> since promises are not callable in ES6
- *
- */
- class DBPromise {
- constructor(request) {
- this.request = request;
- }
- toPromise() {
- return new Promise((resolve, reject) => {
- this.request.addEventListener('success', () => {
- resolve(this.request.result);
- });
- this.request.addEventListener('error', () => {
- reject(this.request.error);
- });
- });
- }
- }
- function getObjectStore(db, isReadWrite) {
- return db
- .transaction([DB_OBJECTSTORE_NAME], isReadWrite ? 'readwrite' : 'readonly')
- .objectStore(DB_OBJECTSTORE_NAME);
- }
- function _deleteDatabase() {
- const request = indexedDB.deleteDatabase(DB_NAME);
- return new DBPromise(request).toPromise();
- }
- function _openDatabase() {
- const request = indexedDB.open(DB_NAME, DB_VERSION);
- return new Promise((resolve, reject) => {
- request.addEventListener('error', () => {
- reject(request.error);
- });
- request.addEventListener('upgradeneeded', () => {
- const db = request.result;
- try {
- db.createObjectStore(DB_OBJECTSTORE_NAME, { keyPath: DB_DATA_KEYPATH });
- }
- catch (e) {
- reject(e);
- }
- });
- request.addEventListener('success', async () => {
- const db = request.result;
- // Strange bug that occurs in Firefox when multiple tabs are opened at the
- // same time. The only way to recover seems to be deleting the database
- // and re-initializing it.
- // https://github.com/firebase/firebase-js-sdk/issues/634
- if (!db.objectStoreNames.contains(DB_OBJECTSTORE_NAME)) {
- // Need to close the database or else you get a `blocked` event
- db.close();
- await _deleteDatabase();
- resolve(await _openDatabase());
- }
- else {
- resolve(db);
- }
- });
- });
- }
- async function _putObject(db, key, value) {
- const request = getObjectStore(db, true).put({
- [DB_DATA_KEYPATH]: key,
- value
- });
- return new DBPromise(request).toPromise();
- }
- async function getObject(db, key) {
- const request = getObjectStore(db, false).get(key);
- const data = await new DBPromise(request).toPromise();
- return data === undefined ? null : data.value;
- }
- function _deleteObject(db, key) {
- const request = getObjectStore(db, true).delete(key);
- return new DBPromise(request).toPromise();
- }
- const _POLLING_INTERVAL_MS = 800;
- const _TRANSACTION_RETRY_COUNT = 3;
- class IndexedDBLocalPersistence {
- constructor() {
- this.type = "LOCAL" /* PersistenceType.LOCAL */;
- this._shouldAllowMigration = true;
- this.listeners = {};
- this.localCache = {};
- // setTimeout return value is platform specific
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.pollTimer = null;
- this.pendingWrites = 0;
- this.receiver = null;
- this.sender = null;
- this.serviceWorkerReceiverAvailable = false;
- this.activeServiceWorker = null;
- // Fire & forget the service worker registration as it may never resolve
- this._workerInitializationPromise =
- this.initializeServiceWorkerMessaging().then(() => { }, () => { });
- }
- async _openDb() {
- if (this.db) {
- return this.db;
- }
- this.db = await _openDatabase();
- return this.db;
- }
- async _withRetries(op) {
- let numAttempts = 0;
- while (true) {
- try {
- const db = await this._openDb();
- return await op(db);
- }
- catch (e) {
- if (numAttempts++ > _TRANSACTION_RETRY_COUNT) {
- throw e;
- }
- if (this.db) {
- this.db.close();
- this.db = undefined;
- }
- // TODO: consider adding exponential backoff
- }
- }
- }
- /**
- * IndexedDB events do not propagate from the main window to the worker context. We rely on a
- * postMessage interface to send these events to the worker ourselves.
- */
- async initializeServiceWorkerMessaging() {
- return _isWorker() ? this.initializeReceiver() : this.initializeSender();
- }
- /**
- * As the worker we should listen to events from the main window.
- */
- async initializeReceiver() {
- this.receiver = Receiver._getInstance(_getWorkerGlobalScope());
- // Refresh from persistence if we receive a KeyChanged message.
- this.receiver._subscribe("keyChanged" /* _EventType.KEY_CHANGED */, async (_origin, data) => {
- const keys = await this._poll();
- return {
- keyProcessed: keys.includes(data.key)
- };
- });
- // Let the sender know that we are listening so they give us more timeout.
- this.receiver._subscribe("ping" /* _EventType.PING */, async (_origin, _data) => {
- return ["keyChanged" /* _EventType.KEY_CHANGED */];
- });
- }
- /**
- * As the main window, we should let the worker know when keys change (set and remove).
- *
- * @remarks
- * {@link https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/ready | ServiceWorkerContainer.ready}
- * may not resolve.
- */
- async initializeSender() {
- var _a, _b;
- // Check to see if there's an active service worker.
- this.activeServiceWorker = await _getActiveServiceWorker();
- if (!this.activeServiceWorker) {
- return;
- }
- this.sender = new Sender(this.activeServiceWorker);
- // Ping the service worker to check what events they can handle.
- const results = await this.sender._send("ping" /* _EventType.PING */, {}, 800 /* _TimeoutDuration.LONG_ACK */);
- if (!results) {
- return;
- }
- if (((_a = results[0]) === null || _a === void 0 ? void 0 : _a.fulfilled) &&
- ((_b = results[0]) === null || _b === void 0 ? void 0 : _b.value.includes("keyChanged" /* _EventType.KEY_CHANGED */))) {
- this.serviceWorkerReceiverAvailable = true;
- }
- }
- /**
- * Let the worker know about a changed key, the exact key doesn't technically matter since the
- * worker will just trigger a full sync anyway.
- *
- * @remarks
- * For now, we only support one service worker per page.
- *
- * @param key - Storage key which changed.
- */
- async notifyServiceWorker(key) {
- if (!this.sender ||
- !this.activeServiceWorker ||
- _getServiceWorkerController() !== this.activeServiceWorker) {
- return;
- }
- try {
- await this.sender._send("keyChanged" /* _EventType.KEY_CHANGED */, { key },
- // Use long timeout if receiver has previously responded to a ping from us.
- this.serviceWorkerReceiverAvailable
- ? 800 /* _TimeoutDuration.LONG_ACK */
- : 50 /* _TimeoutDuration.ACK */);
- }
- catch (_a) {
- // This is a best effort approach. Ignore errors.
- }
- }
- async _isAvailable() {
- try {
- if (!indexedDB) {
- return false;
- }
- const db = await _openDatabase();
- await _putObject(db, STORAGE_AVAILABLE_KEY, '1');
- await _deleteObject(db, STORAGE_AVAILABLE_KEY);
- return true;
- }
- catch (_a) { }
- return false;
- }
- async _withPendingWrite(write) {
- this.pendingWrites++;
- try {
- await write();
- }
- finally {
- this.pendingWrites--;
- }
- }
- async _set(key, value) {
- return this._withPendingWrite(async () => {
- await this._withRetries((db) => _putObject(db, key, value));
- this.localCache[key] = value;
- return this.notifyServiceWorker(key);
- });
- }
- async _get(key) {
- const obj = (await this._withRetries((db) => getObject(db, key)));
- this.localCache[key] = obj;
- return obj;
- }
- async _remove(key) {
- return this._withPendingWrite(async () => {
- await this._withRetries((db) => _deleteObject(db, key));
- delete this.localCache[key];
- return this.notifyServiceWorker(key);
- });
- }
- async _poll() {
- // TODO: check if we need to fallback if getAll is not supported
- const result = await this._withRetries((db) => {
- const getAllRequest = getObjectStore(db, false).getAll();
- return new DBPromise(getAllRequest).toPromise();
- });
- if (!result) {
- return [];
- }
- // If we have pending writes in progress abort, we'll get picked up on the next poll
- if (this.pendingWrites !== 0) {
- return [];
- }
- const keys = [];
- const keysInResult = new Set();
- for (const { fbase_key: key, value } of result) {
- keysInResult.add(key);
- if (JSON.stringify(this.localCache[key]) !== JSON.stringify(value)) {
- this.notifyListeners(key, value);
- keys.push(key);
- }
- }
- for (const localKey of Object.keys(this.localCache)) {
- if (this.localCache[localKey] && !keysInResult.has(localKey)) {
- // Deleted
- this.notifyListeners(localKey, null);
- keys.push(localKey);
- }
- }
- return keys;
- }
- notifyListeners(key, newValue) {
- this.localCache[key] = newValue;
- const listeners = this.listeners[key];
- if (listeners) {
- for (const listener of Array.from(listeners)) {
- listener(newValue);
- }
- }
- }
- startPolling() {
- this.stopPolling();
- this.pollTimer = setInterval(async () => this._poll(), _POLLING_INTERVAL_MS);
- }
- stopPolling() {
- if (this.pollTimer) {
- clearInterval(this.pollTimer);
- this.pollTimer = null;
- }
- }
- _addListener(key, listener) {
- if (Object.keys(this.listeners).length === 0) {
- this.startPolling();
- }
- if (!this.listeners[key]) {
- this.listeners[key] = new Set();
- // Populate the cache to avoid spuriously triggering on first poll.
- void this._get(key); // This can happen in the background async and we can return immediately.
- }
- this.listeners[key].add(listener);
- }
- _removeListener(key, listener) {
- if (this.listeners[key]) {
- this.listeners[key].delete(listener);
- if (this.listeners[key].size === 0) {
- delete this.listeners[key];
- }
- }
- if (Object.keys(this.listeners).length === 0) {
- this.stopPolling();
- }
- }
- }
- IndexedDBLocalPersistence.type = 'LOCAL';
- /**
- * An implementation of {@link Persistence} of type `LOCAL` using `indexedDB`
- * for the underlying storage.
- *
- * @public
- */
- const indexedDBLocalPersistence = IndexedDBLocalPersistence;
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function startSignInPhoneMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaSignIn:start" /* Endpoint.START_MFA_SIGN_IN */, _addTidIfNecessary(auth, request));
- }
- function finalizeSignInPhoneMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaSignIn:finalize" /* Endpoint.FINALIZE_MFA_SIGN_IN */, _addTidIfNecessary(auth, request));
- }
- function finalizeSignInTotpMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaSignIn:finalize" /* Endpoint.FINALIZE_MFA_SIGN_IN */, _addTidIfNecessary(auth, request));
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const _SOLVE_TIME_MS = 500;
- const _EXPIRATION_TIME_MS = 60000;
- const _WIDGET_ID_START = 1000000000000;
- class MockReCaptcha {
- constructor(auth) {
- this.auth = auth;
- this.counter = _WIDGET_ID_START;
- this._widgets = new Map();
- }
- render(container, parameters) {
- const id = this.counter;
- this._widgets.set(id, new MockWidget(container, this.auth.name, parameters || {}));
- this.counter++;
- return id;
- }
- reset(optWidgetId) {
- var _a;
- const id = optWidgetId || _WIDGET_ID_START;
- void ((_a = this._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.delete());
- this._widgets.delete(id);
- }
- getResponse(optWidgetId) {
- var _a;
- const id = optWidgetId || _WIDGET_ID_START;
- return ((_a = this._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.getResponse()) || '';
- }
- async execute(optWidgetId) {
- var _a;
- const id = optWidgetId || _WIDGET_ID_START;
- void ((_a = this._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.execute());
- return '';
- }
- }
- class MockWidget {
- constructor(containerOrId, appName, params) {
- this.params = params;
- this.timerId = null;
- this.deleted = false;
- this.responseToken = null;
- this.clickHandler = () => {
- this.execute();
- };
- const container = typeof containerOrId === 'string'
- ? document.getElementById(containerOrId)
- : containerOrId;
- _assert(container, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */, { appName });
- this.container = container;
- this.isVisible = this.params.size !== 'invisible';
- if (this.isVisible) {
- this.execute();
- }
- else {
- this.container.addEventListener('click', this.clickHandler);
- }
- }
- getResponse() {
- this.checkIfDeleted();
- return this.responseToken;
- }
- delete() {
- this.checkIfDeleted();
- this.deleted = true;
- if (this.timerId) {
- clearTimeout(this.timerId);
- this.timerId = null;
- }
- this.container.removeEventListener('click', this.clickHandler);
- }
- execute() {
- this.checkIfDeleted();
- if (this.timerId) {
- return;
- }
- this.timerId = window.setTimeout(() => {
- this.responseToken = generateRandomAlphaNumericString(50);
- const { callback, 'expired-callback': expiredCallback } = this.params;
- if (callback) {
- try {
- callback(this.responseToken);
- }
- catch (e) { }
- }
- this.timerId = window.setTimeout(() => {
- this.timerId = null;
- this.responseToken = null;
- if (expiredCallback) {
- try {
- expiredCallback();
- }
- catch (e) { }
- }
- if (this.isVisible) {
- this.execute();
- }
- }, _EXPIRATION_TIME_MS);
- }, _SOLVE_TIME_MS);
- }
- checkIfDeleted() {
- if (this.deleted) {
- throw new Error('reCAPTCHA mock was already deleted!');
- }
- }
- }
- function generateRandomAlphaNumericString(len) {
- const chars = [];
- const allowedChars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- for (let i = 0; i < len; i++) {
- chars.push(allowedChars.charAt(Math.floor(Math.random() * allowedChars.length)));
- }
- return chars.join('');
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // ReCaptcha will load using the same callback, so the callback function needs
- // to be kept around
- const _JSLOAD_CALLBACK = _generateCallbackName('rcb');
- const NETWORK_TIMEOUT_DELAY = new Delay(30000, 60000);
- const RECAPTCHA_BASE = 'https://www.google.com/recaptcha/api.js?';
- /**
- * Loader for the GReCaptcha library. There should only ever be one of this.
- */
- class ReCaptchaLoaderImpl {
- constructor() {
- var _a;
- this.hostLanguage = '';
- this.counter = 0;
- /**
- * Check for `render()` method. `window.grecaptcha` will exist if the Enterprise
- * version of the ReCAPTCHA script was loaded by someone else (e.g. App Check) but
- * `window.grecaptcha.render()` will not. Another load will add it.
- */
- this.librarySeparatelyLoaded = !!((_a = _window().grecaptcha) === null || _a === void 0 ? void 0 : _a.render);
- }
- load(auth, hl = '') {
- _assert(isHostLanguageValid(hl), auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- if (this.shouldResolveImmediately(hl) && isV2(_window().grecaptcha)) {
- return Promise.resolve(_window().grecaptcha);
- }
- return new Promise((resolve, reject) => {
- const networkTimeout = _window().setTimeout(() => {
- reject(_createError(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */));
- }, NETWORK_TIMEOUT_DELAY.get());
- _window()[_JSLOAD_CALLBACK] = () => {
- _window().clearTimeout(networkTimeout);
- delete _window()[_JSLOAD_CALLBACK];
- const recaptcha = _window().grecaptcha;
- if (!recaptcha || !isV2(recaptcha)) {
- reject(_createError(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */));
- return;
- }
- // Wrap the greptcha render function so that we know if the developer has
- // called it separately
- const render = recaptcha.render;
- recaptcha.render = (container, params) => {
- const widgetId = render(container, params);
- this.counter++;
- return widgetId;
- };
- this.hostLanguage = hl;
- resolve(recaptcha);
- };
- const url = `${RECAPTCHA_BASE}?${util.querystring({
- onload: _JSLOAD_CALLBACK,
- render: 'explicit',
- hl
- })}`;
- _loadJS(url).catch(() => {
- clearTimeout(networkTimeout);
- reject(_createError(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */));
- });
- });
- }
- clearedOneInstance() {
- this.counter--;
- }
- shouldResolveImmediately(hl) {
- var _a;
- // We can resolve immediately if:
- // • grecaptcha is already defined AND (
- // 1. the requested language codes are the same OR
- // 2. there exists already a ReCaptcha on the page
- // 3. the library was already loaded by the app
- // In cases (2) and (3), we _can't_ reload as it would break the recaptchas
- // that are already in the page
- return (!!((_a = _window().grecaptcha) === null || _a === void 0 ? void 0 : _a.render) &&
- (hl === this.hostLanguage ||
- this.counter > 0 ||
- this.librarySeparatelyLoaded));
- }
- }
- function isHostLanguageValid(hl) {
- return hl.length <= 6 && /^\s*[a-zA-Z0-9\-]*\s*$/.test(hl);
- }
- class MockReCaptchaLoaderImpl {
- async load(auth) {
- return new MockReCaptcha(auth);
- }
- clearedOneInstance() { }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const RECAPTCHA_VERIFIER_TYPE = 'recaptcha';
- const DEFAULT_PARAMS = {
- theme: 'light',
- type: 'image'
- };
- /**
- * An {@link https://www.google.com/recaptcha/ | reCAPTCHA}-based application verifier.
- *
- * @public
- */
- class RecaptchaVerifier {
- /**
- *
- * @param containerOrId - The reCAPTCHA container parameter.
- *
- * @remarks
- * This has different meaning depending on whether the reCAPTCHA is hidden or visible. For a
- * visible reCAPTCHA the container must be empty. If a string is used, it has to correspond to
- * an element ID. The corresponding element must also must be in the DOM at the time of
- * initialization.
- *
- * @param parameters - The optional reCAPTCHA parameters.
- *
- * @remarks
- * Check the reCAPTCHA docs for a comprehensive list. All parameters are accepted except for
- * the sitekey. Firebase Auth backend provisions a reCAPTCHA for each project and will
- * configure this upon rendering. For an invisible reCAPTCHA, a size key must have the value
- * 'invisible'.
- *
- * @param authExtern - The corresponding Firebase {@link Auth} instance.
- */
- constructor(containerOrId, parameters = Object.assign({}, DEFAULT_PARAMS), authExtern) {
- this.parameters = parameters;
- /**
- * The application verifier type.
- *
- * @remarks
- * For a reCAPTCHA verifier, this is 'recaptcha'.
- */
- this.type = RECAPTCHA_VERIFIER_TYPE;
- this.destroyed = false;
- this.widgetId = null;
- this.tokenChangeListeners = new Set();
- this.renderPromise = null;
- this.recaptcha = null;
- this.auth = _castAuth(authExtern);
- this.isInvisible = this.parameters.size === 'invisible';
- _assert(typeof document !== 'undefined', this.auth, "operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- const container = typeof containerOrId === 'string'
- ? document.getElementById(containerOrId)
- : containerOrId;
- _assert(container, this.auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- this.container = container;
- this.parameters.callback = this.makeTokenCallback(this.parameters.callback);
- this._recaptchaLoader = this.auth.settings.appVerificationDisabledForTesting
- ? new MockReCaptchaLoaderImpl()
- : new ReCaptchaLoaderImpl();
- this.validateStartingState();
- // TODO: Figure out if sdk version is needed
- }
- /**
- * Waits for the user to solve the reCAPTCHA and resolves with the reCAPTCHA token.
- *
- * @returns A Promise for the reCAPTCHA token.
- */
- async verify() {
- this.assertNotDestroyed();
- const id = await this.render();
- const recaptcha = this.getAssertedRecaptcha();
- const response = recaptcha.getResponse(id);
- if (response) {
- return response;
- }
- return new Promise(resolve => {
- const tokenChange = (token) => {
- if (!token) {
- return; // Ignore token expirations.
- }
- this.tokenChangeListeners.delete(tokenChange);
- resolve(token);
- };
- this.tokenChangeListeners.add(tokenChange);
- if (this.isInvisible) {
- recaptcha.execute(id);
- }
- });
- }
- /**
- * Renders the reCAPTCHA widget on the page.
- *
- * @returns A Promise that resolves with the reCAPTCHA widget ID.
- */
- render() {
- try {
- this.assertNotDestroyed();
- }
- catch (e) {
- // This method returns a promise. Since it's not async (we want to return the
- // _same_ promise if rendering is still occurring), the API surface should
- // reject with the error rather than just throw
- return Promise.reject(e);
- }
- if (this.renderPromise) {
- return this.renderPromise;
- }
- this.renderPromise = this.makeRenderPromise().catch(e => {
- this.renderPromise = null;
- throw e;
- });
- return this.renderPromise;
- }
- /** @internal */
- _reset() {
- this.assertNotDestroyed();
- if (this.widgetId !== null) {
- this.getAssertedRecaptcha().reset(this.widgetId);
- }
- }
- /**
- * Clears the reCAPTCHA widget from the page and destroys the instance.
- */
- clear() {
- this.assertNotDestroyed();
- this.destroyed = true;
- this._recaptchaLoader.clearedOneInstance();
- if (!this.isInvisible) {
- this.container.childNodes.forEach(node => {
- this.container.removeChild(node);
- });
- }
- }
- validateStartingState() {
- _assert(!this.parameters.sitekey, this.auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- _assert(this.isInvisible || !this.container.hasChildNodes(), this.auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- _assert(typeof document !== 'undefined', this.auth, "operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- }
- makeTokenCallback(existing) {
- return token => {
- this.tokenChangeListeners.forEach(listener => listener(token));
- if (typeof existing === 'function') {
- existing(token);
- }
- else if (typeof existing === 'string') {
- const globalFunc = _window()[existing];
- if (typeof globalFunc === 'function') {
- globalFunc(token);
- }
- }
- };
- }
- assertNotDestroyed() {
- _assert(!this.destroyed, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- async makeRenderPromise() {
- await this.init();
- if (!this.widgetId) {
- let container = this.container;
- if (!this.isInvisible) {
- const guaranteedEmpty = document.createElement('div');
- container.appendChild(guaranteedEmpty);
- container = guaranteedEmpty;
- }
- this.widgetId = this.getAssertedRecaptcha().render(container, this.parameters);
- }
- return this.widgetId;
- }
- async init() {
- _assert(_isHttpOrHttps() && !_isWorker(), this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- await domReady();
- this.recaptcha = await this._recaptchaLoader.load(this.auth, this.auth.languageCode || undefined);
- const siteKey = await getRecaptchaParams(this.auth);
- _assert(siteKey, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- this.parameters.sitekey = siteKey;
- }
- getAssertedRecaptcha() {
- _assert(this.recaptcha, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return this.recaptcha;
- }
- }
- function domReady() {
- let resolver = null;
- return new Promise(resolve => {
- if (document.readyState === 'complete') {
- resolve();
- return;
- }
- // Document not ready, wait for load before resolving.
- // Save resolver, so we can remove listener in case it was externally
- // cancelled.
- resolver = () => resolve();
- window.addEventListener('load', resolver);
- }).catch(e => {
- if (resolver) {
- window.removeEventListener('load', resolver);
- }
- throw e;
- });
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class ConfirmationResultImpl {
- constructor(verificationId, onConfirmation) {
- this.verificationId = verificationId;
- this.onConfirmation = onConfirmation;
- }
- confirm(verificationCode) {
- const authCredential = PhoneAuthCredential._fromVerification(this.verificationId, verificationCode);
- return this.onConfirmation(authCredential);
- }
- }
- /**
- * Asynchronously signs in using a phone number.
- *
- * @remarks
- * This method sends a code via SMS to the given
- * phone number, and returns a {@link ConfirmationResult}. After the user
- * provides the code sent to their phone, call {@link ConfirmationResult.confirm}
- * with the code to sign the user in.
- *
- * For abuse prevention, this method also requires a {@link ApplicationVerifier}.
- * This SDK includes a reCAPTCHA-based implementation, {@link RecaptchaVerifier}.
- * This function can work on other platforms that do not support the
- * {@link RecaptchaVerifier} (like React Native), but you need to use a
- * third-party {@link ApplicationVerifier} implementation.
- *
- * @example
- * ```javascript
- * // 'recaptcha-container' is the ID of an element in the DOM.
- * const applicationVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
- * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
- * // Obtain a verificationCode from the user.
- * const credential = await confirmationResult.confirm(verificationCode);
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
- * @param appVerifier - The {@link ApplicationVerifier}.
- *
- * @public
- */
- async function signInWithPhoneNumber(auth, phoneNumber, appVerifier) {
- const authInternal = _castAuth(auth);
- const verificationId = await _verifyPhoneNumber(authInternal, phoneNumber, util.getModularInstance(appVerifier));
- return new ConfirmationResultImpl(verificationId, cred => signInWithCredential(authInternal, cred));
- }
- /**
- * Links the user account with the given phone number.
- *
- * @param user - The user.
- * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
- * @param appVerifier - The {@link ApplicationVerifier}.
- *
- * @public
- */
- async function linkWithPhoneNumber(user, phoneNumber, appVerifier) {
- const userInternal = util.getModularInstance(user);
- await _assertLinkedStatus(false, userInternal, "phone" /* ProviderId.PHONE */);
- const verificationId = await _verifyPhoneNumber(userInternal.auth, phoneNumber, util.getModularInstance(appVerifier));
- return new ConfirmationResultImpl(verificationId, cred => linkWithCredential(userInternal, cred));
- }
- /**
- * Re-authenticates a user using a fresh phone credential.
- *
- * @remarks Use before operations such as {@link updatePassword} that require tokens from recent sign-in attempts.
- *
- * @param user - The user.
- * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
- * @param appVerifier - The {@link ApplicationVerifier}.
- *
- * @public
- */
- async function reauthenticateWithPhoneNumber(user, phoneNumber, appVerifier) {
- const userInternal = util.getModularInstance(user);
- const verificationId = await _verifyPhoneNumber(userInternal.auth, phoneNumber, util.getModularInstance(appVerifier));
- return new ConfirmationResultImpl(verificationId, cred => reauthenticateWithCredential(userInternal, cred));
- }
- /**
- * Returns a verification ID to be used in conjunction with the SMS code that is sent.
- *
- */
- async function _verifyPhoneNumber(auth, options, verifier) {
- var _a;
- const recaptchaToken = await verifier.verify();
- try {
- _assert(typeof recaptchaToken === 'string', auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- _assert(verifier.type === RECAPTCHA_VERIFIER_TYPE, auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- let phoneInfoOptions;
- if (typeof options === 'string') {
- phoneInfoOptions = {
- phoneNumber: options
- };
- }
- else {
- phoneInfoOptions = options;
- }
- if ('session' in phoneInfoOptions) {
- const session = phoneInfoOptions.session;
- if ('phoneNumber' in phoneInfoOptions) {
- _assert(session.type === "enroll" /* MultiFactorSessionType.ENROLL */, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const response = await startEnrollPhoneMfa(auth, {
- idToken: session.credential,
- phoneEnrollmentInfo: {
- phoneNumber: phoneInfoOptions.phoneNumber,
- recaptchaToken
- }
- });
- return response.phoneSessionInfo.sessionInfo;
- }
- else {
- _assert(session.type === "signin" /* MultiFactorSessionType.SIGN_IN */, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const mfaEnrollmentId = ((_a = phoneInfoOptions.multiFactorHint) === null || _a === void 0 ? void 0 : _a.uid) ||
- phoneInfoOptions.multiFactorUid;
- _assert(mfaEnrollmentId, auth, "missing-multi-factor-info" /* AuthErrorCode.MISSING_MFA_INFO */);
- const response = await startSignInPhoneMfa(auth, {
- mfaPendingCredential: session.credential,
- mfaEnrollmentId,
- phoneSignInInfo: {
- recaptchaToken
- }
- });
- return response.phoneResponseInfo.sessionInfo;
- }
- }
- else {
- const { sessionInfo } = await sendPhoneVerificationCode(auth, {
- phoneNumber: phoneInfoOptions.phoneNumber,
- recaptchaToken
- });
- return sessionInfo;
- }
- }
- finally {
- verifier._reset();
- }
- }
- /**
- * Updates the user's phone number.
- *
- * @example
- * ```
- * // 'recaptcha-container' is the ID of an element in the DOM.
- * const applicationVerifier = new RecaptchaVerifier('recaptcha-container');
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier);
- * // Obtain the verificationCode from the user.
- * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
- * await updatePhoneNumber(user, phoneCredential);
- * ```
- *
- * @param user - The user.
- * @param credential - A credential authenticating the new phone number.
- *
- * @public
- */
- async function updatePhoneNumber(user, credential) {
- await _link$1(util.getModularInstance(user), credential);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an {@link PhoneAuthCredential}.
- *
- * @example
- * ```javascript
- * // 'recaptcha-container' is the ID of an element in the DOM.
- * const applicationVerifier = new RecaptchaVerifier('recaptcha-container');
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier);
- * // Obtain the verificationCode from the user.
- * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
- * const userCredential = await signInWithCredential(auth, phoneCredential);
- * ```
- *
- * @public
- */
- class PhoneAuthProvider {
- /**
- * @param auth - The Firebase {@link Auth} instance in which sign-ins should occur.
- *
- */
- constructor(auth) {
- /** Always set to {@link ProviderId}.PHONE. */
- this.providerId = PhoneAuthProvider.PROVIDER_ID;
- this.auth = _castAuth(auth);
- }
- /**
- *
- * Starts a phone number authentication flow by sending a verification code to the given phone
- * number.
- *
- * @example
- * ```javascript
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = await provider.verifyPhoneNumber(phoneNumber, applicationVerifier);
- * // Obtain verificationCode from the user.
- * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
- * const userCredential = await signInWithCredential(auth, authCredential);
- * ```
- *
- * @example
- * An alternative flow is provided using the `signInWithPhoneNumber` method.
- * ```javascript
- * const confirmationResult = signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
- * // Obtain verificationCode from the user.
- * const userCredential = confirmationResult.confirm(verificationCode);
- * ```
- *
- * @param phoneInfoOptions - The user's {@link PhoneInfoOptions}. The phone number should be in
- * E.164 format (e.g. +16505550101).
- * @param applicationVerifier - For abuse prevention, this method also requires a
- * {@link ApplicationVerifier}. This SDK includes a reCAPTCHA-based implementation,
- * {@link RecaptchaVerifier}.
- *
- * @returns A Promise for a verification ID that can be passed to
- * {@link PhoneAuthProvider.credential} to identify this flow..
- */
- verifyPhoneNumber(phoneOptions, applicationVerifier) {
- return _verifyPhoneNumber(this.auth, phoneOptions, util.getModularInstance(applicationVerifier));
- }
- /**
- * Creates a phone auth credential, given the verification ID from
- * {@link PhoneAuthProvider.verifyPhoneNumber} and the code that was sent to the user's
- * mobile device.
- *
- * @example
- * ```javascript
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = provider.verifyPhoneNumber(phoneNumber, applicationVerifier);
- * // Obtain verificationCode from the user.
- * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
- * const userCredential = signInWithCredential(auth, authCredential);
- * ```
- *
- * @example
- * An alternative flow is provided using the `signInWithPhoneNumber` method.
- * ```javascript
- * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
- * // Obtain verificationCode from the user.
- * const userCredential = await confirmationResult.confirm(verificationCode);
- * ```
- *
- * @param verificationId - The verification ID returned from {@link PhoneAuthProvider.verifyPhoneNumber}.
- * @param verificationCode - The verification code sent to the user's mobile device.
- *
- * @returns The auth provider credential.
- */
- static credential(verificationId, verificationCode) {
- return PhoneAuthCredential._fromVerification(verificationId, verificationCode);
- }
- /**
- * Generates an {@link AuthCredential} from a {@link UserCredential}.
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- const credential = userCredential;
- return PhoneAuthProvider.credentialFromTaggedObject(credential);
- }
- /**
- * Returns an {@link AuthCredential} when passed an error.
- *
- * @remarks
- *
- * This method works for errors like
- * `auth/account-exists-with-different-credentials`. This is useful for
- * recovering when attempting to set a user's phone number but the number
- * in question is already tied to another account. For example, the following
- * code tries to update the current user's phone number, and if that
- * fails, links the user with the account associated with that number:
- *
- * ```js
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = await provider.verifyPhoneNumber(number, verifier);
- * try {
- * const code = ''; // Prompt the user for the verification code
- * await updatePhoneNumber(
- * auth.currentUser,
- * PhoneAuthProvider.credential(verificationId, code));
- * } catch (e) {
- * if ((e as FirebaseError)?.code === 'auth/account-exists-with-different-credential') {
- * const cred = PhoneAuthProvider.credentialFromError(e);
- * await linkWithCredential(auth.currentUser, cred);
- * }
- * }
- *
- * // At this point, auth.currentUser.phoneNumber === number.
- * ```
- *
- * @param error - The error to generate a credential from.
- */
- static credentialFromError(error) {
- return PhoneAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { phoneNumber, temporaryProof } = tokenResponse;
- if (phoneNumber && temporaryProof) {
- return PhoneAuthCredential._fromTokenResponse(phoneNumber, temporaryProof);
- }
- return null;
- }
- }
- /** Always set to {@link ProviderId}.PHONE. */
- PhoneAuthProvider.PROVIDER_ID = "phone" /* ProviderId.PHONE */;
- /** Always set to {@link SignInMethod}.PHONE. */
- PhoneAuthProvider.PHONE_SIGN_IN_METHOD = "phone" /* SignInMethod.PHONE */;
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Chooses a popup/redirect resolver to use. This prefers the override (which
- * is directly passed in), and falls back to the property set on the auth
- * object. If neither are available, this function errors w/ an argument error.
- */
- function _withDefaultResolver(auth, resolverOverride) {
- if (resolverOverride) {
- return _getInstance(resolverOverride);
- }
- _assert(auth._popupRedirectResolver, auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return auth._popupRedirectResolver;
- }
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class IdpCredential extends AuthCredential {
- constructor(params) {
- super("custom" /* ProviderId.CUSTOM */, "custom" /* ProviderId.CUSTOM */);
- this.params = params;
- }
- _getIdTokenResponse(auth) {
- return signInWithIdp(auth, this._buildIdpRequest());
- }
- _linkToIdToken(auth, idToken) {
- return signInWithIdp(auth, this._buildIdpRequest(idToken));
- }
- _getReauthenticationResolver(auth) {
- return signInWithIdp(auth, this._buildIdpRequest());
- }
- _buildIdpRequest(idToken) {
- const request = {
- requestUri: this.params.requestUri,
- sessionId: this.params.sessionId,
- postBody: this.params.postBody,
- tenantId: this.params.tenantId,
- pendingToken: this.params.pendingToken,
- returnSecureToken: true,
- returnIdpCredential: true
- };
- if (idToken) {
- request.idToken = idToken;
- }
- return request;
- }
- }
- function _signIn(params) {
- return _signInWithCredential(params.auth, new IdpCredential(params), params.bypassAuthState);
- }
- function _reauth(params) {
- const { auth, user } = params;
- _assert(user, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return _reauthenticate(user, new IdpCredential(params), params.bypassAuthState);
- }
- async function _link(params) {
- const { auth, user } = params;
- _assert(user, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return _link$1(user, new IdpCredential(params), params.bypassAuthState);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Popup event manager. Handles the popup's entire lifecycle; listens to auth
- * events
- */
- class AbstractPopupRedirectOperation {
- constructor(auth, filter, resolver, user, bypassAuthState = false) {
- this.auth = auth;
- this.resolver = resolver;
- this.user = user;
- this.bypassAuthState = bypassAuthState;
- this.pendingPromise = null;
- this.eventManager = null;
- this.filter = Array.isArray(filter) ? filter : [filter];
- }
- execute() {
- return new Promise(async (resolve, reject) => {
- this.pendingPromise = { resolve, reject };
- try {
- this.eventManager = await this.resolver._initialize(this.auth);
- await this.onExecution();
- this.eventManager.registerConsumer(this);
- }
- catch (e) {
- this.reject(e);
- }
- });
- }
- async onAuthEvent(event) {
- const { urlResponse, sessionId, postBody, tenantId, error, type } = event;
- if (error) {
- this.reject(error);
- return;
- }
- const params = {
- auth: this.auth,
- requestUri: urlResponse,
- sessionId: sessionId,
- tenantId: tenantId || undefined,
- postBody: postBody || undefined,
- user: this.user,
- bypassAuthState: this.bypassAuthState
- };
- try {
- this.resolve(await this.getIdpTask(type)(params));
- }
- catch (e) {
- this.reject(e);
- }
- }
- onError(error) {
- this.reject(error);
- }
- getIdpTask(type) {
- switch (type) {
- case "signInViaPopup" /* AuthEventType.SIGN_IN_VIA_POPUP */:
- case "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */:
- return _signIn;
- case "linkViaPopup" /* AuthEventType.LINK_VIA_POPUP */:
- case "linkViaRedirect" /* AuthEventType.LINK_VIA_REDIRECT */:
- return _link;
- case "reauthViaPopup" /* AuthEventType.REAUTH_VIA_POPUP */:
- case "reauthViaRedirect" /* AuthEventType.REAUTH_VIA_REDIRECT */:
- return _reauth;
- default:
- _fail(this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- }
- resolve(cred) {
- debugAssert(this.pendingPromise, 'Pending promise was never set');
- this.pendingPromise.resolve(cred);
- this.unregisterAndCleanUp();
- }
- reject(error) {
- debugAssert(this.pendingPromise, 'Pending promise was never set');
- this.pendingPromise.reject(error);
- this.unregisterAndCleanUp();
- }
- unregisterAndCleanUp() {
- if (this.eventManager) {
- this.eventManager.unregisterConsumer(this);
- }
- this.pendingPromise = null;
- this.cleanUp();
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const _POLL_WINDOW_CLOSE_TIMEOUT = new Delay(2000, 10000);
- /**
- * Authenticates a Firebase client using a popup-based OAuth authentication flow.
- *
- * @remarks
- * If succeeds, returns the signed in user along with the provider's credential. If sign in was
- * unsuccessful, returns an error object containing additional information about the error.
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new FacebookAuthProvider();
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- *
- * @public
- */
- async function signInWithPopup(auth, provider, resolver) {
- const authInternal = _castAuth(auth);
- _assertInstanceOf(auth, provider, FederatedAuthProvider);
- const resolverInternal = _withDefaultResolver(authInternal, resolver);
- const action = new PopupOperation(authInternal, "signInViaPopup" /* AuthEventType.SIGN_IN_VIA_POPUP */, provider, resolverInternal);
- return action.executeNotNull();
- }
- /**
- * Reauthenticates the current user with the specified {@link OAuthProvider} using a pop-up based
- * OAuth flow.
- *
- * @remarks
- * If the reauthentication is successful, the returned result will contain the user and the
- * provider's credential.
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new FacebookAuthProvider();
- * const result = await signInWithPopup(auth, provider);
- * // Reauthenticate using a popup.
- * await reauthenticateWithPopup(result.user, provider);
- * ```
- *
- * @param user - The user.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- async function reauthenticateWithPopup(user, provider, resolver) {
- const userInternal = util.getModularInstance(user);
- _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
- const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
- const action = new PopupOperation(userInternal.auth, "reauthViaPopup" /* AuthEventType.REAUTH_VIA_POPUP */, provider, resolverInternal, userInternal);
- return action.executeNotNull();
- }
- /**
- * Links the authenticated provider to the user account using a pop-up based OAuth flow.
- *
- * @remarks
- * If the linking is successful, the returned result will contain the user and the provider's credential.
- *
- *
- * @example
- * ```javascript
- * // Sign in using some other provider.
- * const result = await signInWithEmailAndPassword(auth, email, password);
- * // Link using a popup.
- * const provider = new FacebookAuthProvider();
- * await linkWithPopup(result.user, provider);
- * ```
- *
- * @param user - The user.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- async function linkWithPopup(user, provider, resolver) {
- const userInternal = util.getModularInstance(user);
- _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
- const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
- const action = new PopupOperation(userInternal.auth, "linkViaPopup" /* AuthEventType.LINK_VIA_POPUP */, provider, resolverInternal, userInternal);
- return action.executeNotNull();
- }
- /**
- * Popup event manager. Handles the popup's entire lifecycle; listens to auth
- * events
- *
- */
- class PopupOperation extends AbstractPopupRedirectOperation {
- constructor(auth, filter, provider, resolver, user) {
- super(auth, filter, resolver, user);
- this.provider = provider;
- this.authWindow = null;
- this.pollId = null;
- if (PopupOperation.currentPopupAction) {
- PopupOperation.currentPopupAction.cancel();
- }
- PopupOperation.currentPopupAction = this;
- }
- async executeNotNull() {
- const result = await this.execute();
- _assert(result, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return result;
- }
- async onExecution() {
- debugAssert(this.filter.length === 1, 'Popup operations only handle one event');
- const eventId = _generateEventId();
- this.authWindow = await this.resolver._openPopup(this.auth, this.provider, this.filter[0], // There's always one, see constructor
- eventId);
- this.authWindow.associatedEvent = eventId;
- // Check for web storage support and origin validation _after_ the popup is
- // loaded. These operations are slow (~1 second or so) Rather than
- // waiting on them before opening the window, optimistically open the popup
- // and check for storage support at the same time. If storage support is
- // not available, this will cause the whole thing to reject properly. It
- // will also close the popup, but since the promise has already rejected,
- // the popup closed by user poll will reject into the void.
- this.resolver._originValidation(this.auth).catch(e => {
- this.reject(e);
- });
- this.resolver._isIframeWebStorageSupported(this.auth, isSupported => {
- if (!isSupported) {
- this.reject(_createError(this.auth, "web-storage-unsupported" /* AuthErrorCode.WEB_STORAGE_UNSUPPORTED */));
- }
- });
- // Handle user closure. Notice this does *not* use await
- this.pollUserCancellation();
- }
- get eventId() {
- var _a;
- return ((_a = this.authWindow) === null || _a === void 0 ? void 0 : _a.associatedEvent) || null;
- }
- cancel() {
- this.reject(_createError(this.auth, "cancelled-popup-request" /* AuthErrorCode.EXPIRED_POPUP_REQUEST */));
- }
- cleanUp() {
- if (this.authWindow) {
- this.authWindow.close();
- }
- if (this.pollId) {
- window.clearTimeout(this.pollId);
- }
- this.authWindow = null;
- this.pollId = null;
- PopupOperation.currentPopupAction = null;
- }
- pollUserCancellation() {
- const poll = () => {
- var _a, _b;
- if ((_b = (_a = this.authWindow) === null || _a === void 0 ? void 0 : _a.window) === null || _b === void 0 ? void 0 : _b.closed) {
- // Make sure that there is sufficient time for whatever action to
- // complete. The window could have closed but the sign in network
- // call could still be in flight. This is specifically true for
- // Firefox or if the opener is in an iframe, in which case the oauth
- // helper closes the popup.
- this.pollId = window.setTimeout(() => {
- this.pollId = null;
- this.reject(_createError(this.auth, "popup-closed-by-user" /* AuthErrorCode.POPUP_CLOSED_BY_USER */));
- }, 8000 /* _Timeout.AUTH_EVENT */);
- return;
- }
- this.pollId = window.setTimeout(poll, _POLL_WINDOW_CLOSE_TIMEOUT.get());
- };
- poll();
- }
- }
- // Only one popup is ever shown at once. The lifecycle of the current popup
- // can be managed / cancelled by the constructor.
- PopupOperation.currentPopupAction = null;
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const PENDING_REDIRECT_KEY = 'pendingRedirect';
- // We only get one redirect outcome for any one auth, so just store it
- // in here.
- const redirectOutcomeMap = new Map();
- class RedirectAction extends AbstractPopupRedirectOperation {
- constructor(auth, resolver, bypassAuthState = false) {
- super(auth, [
- "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */,
- "linkViaRedirect" /* AuthEventType.LINK_VIA_REDIRECT */,
- "reauthViaRedirect" /* AuthEventType.REAUTH_VIA_REDIRECT */,
- "unknown" /* AuthEventType.UNKNOWN */
- ], resolver, undefined, bypassAuthState);
- this.eventId = null;
- }
- /**
- * Override the execute function; if we already have a redirect result, then
- * just return it.
- */
- async execute() {
- let readyOutcome = redirectOutcomeMap.get(this.auth._key());
- if (!readyOutcome) {
- try {
- const hasPendingRedirect = await _getAndClearPendingRedirectStatus(this.resolver, this.auth);
- const result = hasPendingRedirect ? await super.execute() : null;
- readyOutcome = () => Promise.resolve(result);
- }
- catch (e) {
- readyOutcome = () => Promise.reject(e);
- }
- redirectOutcomeMap.set(this.auth._key(), readyOutcome);
- }
- // If we're not bypassing auth state, the ready outcome should be set to
- // null.
- if (!this.bypassAuthState) {
- redirectOutcomeMap.set(this.auth._key(), () => Promise.resolve(null));
- }
- return readyOutcome();
- }
- async onAuthEvent(event) {
- if (event.type === "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */) {
- return super.onAuthEvent(event);
- }
- else if (event.type === "unknown" /* AuthEventType.UNKNOWN */) {
- // This is a sentinel value indicating there's no pending redirect
- this.resolve(null);
- return;
- }
- if (event.eventId) {
- const user = await this.auth._redirectUserForId(event.eventId);
- if (user) {
- this.user = user;
- return super.onAuthEvent(event);
- }
- else {
- this.resolve(null);
- }
- }
- }
- async onExecution() { }
- cleanUp() { }
- }
- async function _getAndClearPendingRedirectStatus(resolver, auth) {
- const key = pendingRedirectKey(auth);
- const persistence = resolverPersistence(resolver);
- if (!(await persistence._isAvailable())) {
- return false;
- }
- const hasPendingRedirect = (await persistence._get(key)) === 'true';
- await persistence._remove(key);
- return hasPendingRedirect;
- }
- async function _setPendingRedirectStatus(resolver, auth) {
- return resolverPersistence(resolver)._set(pendingRedirectKey(auth), 'true');
- }
- function _clearRedirectOutcomes() {
- redirectOutcomeMap.clear();
- }
- function _overrideRedirectResult(auth, result) {
- redirectOutcomeMap.set(auth._key(), result);
- }
- function resolverPersistence(resolver) {
- return _getInstance(resolver._redirectPersistence);
- }
- function pendingRedirectKey(auth) {
- return _persistenceKeyName(PENDING_REDIRECT_KEY, auth.config.apiKey, auth.name);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Authenticates a Firebase client using a full-page redirect flow.
- *
- * @remarks
- * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
- * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
- * | best practices} when using {@link signInWithRedirect}.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new FacebookAuthProvider();
- * // You can add additional scopes to the provider:
- * provider.addScope('user_birthday');
- * // Start a sign in process for an unauthenticated user.
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * }
- * // As this API can be used for sign-in, linking and reauthentication,
- * // check the operationType to determine what triggered this redirect
- * // operation.
- * const operationType = result.operationType;
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- function signInWithRedirect(auth, provider, resolver) {
- return _signInWithRedirect(auth, provider, resolver);
- }
- async function _signInWithRedirect(auth, provider, resolver) {
- const authInternal = _castAuth(auth);
- _assertInstanceOf(auth, provider, FederatedAuthProvider);
- // Wait for auth initialization to complete, this will process pending redirects and clear the
- // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
- // redirect and creating a PENDING_REDIRECT_KEY entry.
- await authInternal._initializationPromise;
- const resolverInternal = _withDefaultResolver(authInternal, resolver);
- await _setPendingRedirectStatus(resolverInternal, authInternal);
- return resolverInternal._openRedirect(authInternal, provider, "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */);
- }
- /**
- * Reauthenticates the current user with the specified {@link OAuthProvider} using a full-page redirect flow.
- * @remarks
- * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
- * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
- * | best practices} when using {@link reauthenticateWithRedirect}.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new FacebookAuthProvider();
- * const result = await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * // Reauthenticate using a redirect.
- * await reauthenticateWithRedirect(result.user, provider);
- * // This will again trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * ```
- *
- * @param user - The user.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- function reauthenticateWithRedirect(user, provider, resolver) {
- return _reauthenticateWithRedirect(user, provider, resolver);
- }
- async function _reauthenticateWithRedirect(user, provider, resolver) {
- const userInternal = util.getModularInstance(user);
- _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
- // Wait for auth initialization to complete, this will process pending redirects and clear the
- // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
- // redirect and creating a PENDING_REDIRECT_KEY entry.
- await userInternal.auth._initializationPromise;
- // Allow the resolver to error before persisting the redirect user
- const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
- await _setPendingRedirectStatus(resolverInternal, userInternal.auth);
- const eventId = await prepareUserForRedirect(userInternal);
- return resolverInternal._openRedirect(userInternal.auth, provider, "reauthViaRedirect" /* AuthEventType.REAUTH_VIA_REDIRECT */, eventId);
- }
- /**
- * Links the {@link OAuthProvider} to the user account using a full-page redirect flow.
- * @remarks
- * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
- * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
- * | best practices} when using {@link linkWithRedirect}.
- *
- * @example
- * ```javascript
- * // Sign in using some other provider.
- * const result = await signInWithEmailAndPassword(auth, email, password);
- * // Link using a redirect.
- * const provider = new FacebookAuthProvider();
- * await linkWithRedirect(result.user, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * ```
- *
- * @param user - The user.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- *
- * @public
- */
- function linkWithRedirect(user, provider, resolver) {
- return _linkWithRedirect(user, provider, resolver);
- }
- async function _linkWithRedirect(user, provider, resolver) {
- const userInternal = util.getModularInstance(user);
- _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
- // Wait for auth initialization to complete, this will process pending redirects and clear the
- // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
- // redirect and creating a PENDING_REDIRECT_KEY entry.
- await userInternal.auth._initializationPromise;
- // Allow the resolver to error before persisting the redirect user
- const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
- await _assertLinkedStatus(false, userInternal, provider.providerId);
- await _setPendingRedirectStatus(resolverInternal, userInternal.auth);
- const eventId = await prepareUserForRedirect(userInternal);
- return resolverInternal._openRedirect(userInternal.auth, provider, "linkViaRedirect" /* AuthEventType.LINK_VIA_REDIRECT */, eventId);
- }
- /**
- * Returns a {@link UserCredential} from the redirect-based sign-in flow.
- *
- * @remarks
- * If sign-in succeeded, returns the signed in user. If sign-in was unsuccessful, fails with an
- * error. If no redirect operation was called, returns `null`.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new FacebookAuthProvider();
- * // You can add additional scopes to the provider:
- * provider.addScope('user_birthday');
- * // Start a sign in process for an unauthenticated user.
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * }
- * // As this API can be used for sign-in, linking and reauthentication,
- * // check the operationType to determine what triggered this redirect
- * // operation.
- * const operationType = result.operationType;
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- async function getRedirectResult(auth, resolver) {
- await _castAuth(auth)._initializationPromise;
- return _getRedirectResult(auth, resolver, false);
- }
- async function _getRedirectResult(auth, resolverExtern, bypassAuthState = false) {
- const authInternal = _castAuth(auth);
- const resolver = _withDefaultResolver(authInternal, resolverExtern);
- const action = new RedirectAction(authInternal, resolver, bypassAuthState);
- const result = await action.execute();
- if (result && !bypassAuthState) {
- delete result.user._redirectEventId;
- await authInternal._persistUserIfCurrent(result.user);
- await authInternal._setRedirectUser(null, resolverExtern);
- }
- return result;
- }
- async function prepareUserForRedirect(user) {
- const eventId = _generateEventId(`${user.uid}:::`);
- user._redirectEventId = eventId;
- await user.auth._setRedirectUser(user);
- await user.auth._persistUserIfCurrent(user);
- return eventId;
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // The amount of time to store the UIDs of seen events; this is
- // set to 10 min by default
- const EVENT_DUPLICATION_CACHE_DURATION_MS = 10 * 60 * 1000;
- class AuthEventManager {
- constructor(auth) {
- this.auth = auth;
- this.cachedEventUids = new Set();
- this.consumers = new Set();
- this.queuedRedirectEvent = null;
- this.hasHandledPotentialRedirect = false;
- this.lastProcessedEventTime = Date.now();
- }
- registerConsumer(authEventConsumer) {
- this.consumers.add(authEventConsumer);
- if (this.queuedRedirectEvent &&
- this.isEventForConsumer(this.queuedRedirectEvent, authEventConsumer)) {
- this.sendToConsumer(this.queuedRedirectEvent, authEventConsumer);
- this.saveEventToCache(this.queuedRedirectEvent);
- this.queuedRedirectEvent = null;
- }
- }
- unregisterConsumer(authEventConsumer) {
- this.consumers.delete(authEventConsumer);
- }
- onEvent(event) {
- // Check if the event has already been handled
- if (this.hasEventBeenHandled(event)) {
- return false;
- }
- let handled = false;
- this.consumers.forEach(consumer => {
- if (this.isEventForConsumer(event, consumer)) {
- handled = true;
- this.sendToConsumer(event, consumer);
- this.saveEventToCache(event);
- }
- });
- if (this.hasHandledPotentialRedirect || !isRedirectEvent(event)) {
- // If we've already seen a redirect before, or this is a popup event,
- // bail now
- return handled;
- }
- this.hasHandledPotentialRedirect = true;
- // If the redirect wasn't handled, hang on to it
- if (!handled) {
- this.queuedRedirectEvent = event;
- handled = true;
- }
- return handled;
- }
- sendToConsumer(event, consumer) {
- var _a;
- if (event.error && !isNullRedirectEvent(event)) {
- const code = ((_a = event.error.code) === null || _a === void 0 ? void 0 : _a.split('auth/')[1]) ||
- "internal-error" /* AuthErrorCode.INTERNAL_ERROR */;
- consumer.onError(_createError(this.auth, code));
- }
- else {
- consumer.onAuthEvent(event);
- }
- }
- isEventForConsumer(event, consumer) {
- const eventIdMatches = consumer.eventId === null ||
- (!!event.eventId && event.eventId === consumer.eventId);
- return consumer.filter.includes(event.type) && eventIdMatches;
- }
- hasEventBeenHandled(event) {
- if (Date.now() - this.lastProcessedEventTime >=
- EVENT_DUPLICATION_CACHE_DURATION_MS) {
- this.cachedEventUids.clear();
- }
- return this.cachedEventUids.has(eventUid(event));
- }
- saveEventToCache(event) {
- this.cachedEventUids.add(eventUid(event));
- this.lastProcessedEventTime = Date.now();
- }
- }
- function eventUid(e) {
- return [e.type, e.eventId, e.sessionId, e.tenantId].filter(v => v).join('-');
- }
- function isNullRedirectEvent({ type, error }) {
- return (type === "unknown" /* AuthEventType.UNKNOWN */ &&
- (error === null || error === void 0 ? void 0 : error.code) === `auth/${"no-auth-event" /* AuthErrorCode.NO_AUTH_EVENT */}`);
- }
- function isRedirectEvent(event) {
- switch (event.type) {
- case "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */:
- case "linkViaRedirect" /* AuthEventType.LINK_VIA_REDIRECT */:
- case "reauthViaRedirect" /* AuthEventType.REAUTH_VIA_REDIRECT */:
- return true;
- case "unknown" /* AuthEventType.UNKNOWN */:
- return isNullRedirectEvent(event);
- default:
- return false;
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _getProjectConfig(auth, request = {}) {
- return _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v1/projects" /* Endpoint.GET_PROJECT_CONFIG */, request);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const IP_ADDRESS_REGEX = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
- const HTTP_REGEX = /^https?/;
- async function _validateOrigin(auth) {
- // Skip origin validation if we are in an emulated environment
- if (auth.config.emulator) {
- return;
- }
- const { authorizedDomains } = await _getProjectConfig(auth);
- for (const domain of authorizedDomains) {
- try {
- if (matchDomain(domain)) {
- return;
- }
- }
- catch (_a) {
- // Do nothing if there's a URL error; just continue searching
- }
- }
- // In the old SDK, this error also provides helpful messages.
- _fail(auth, "unauthorized-domain" /* AuthErrorCode.INVALID_ORIGIN */);
- }
- function matchDomain(expected) {
- const currentUrl = _getCurrentUrl();
- const { protocol, hostname } = new URL(currentUrl);
- if (expected.startsWith('chrome-extension://')) {
- const ceUrl = new URL(expected);
- if (ceUrl.hostname === '' && hostname === '') {
- // For some reason we're not parsing chrome URLs properly
- return (protocol === 'chrome-extension:' &&
- expected.replace('chrome-extension://', '') ===
- currentUrl.replace('chrome-extension://', ''));
- }
- return protocol === 'chrome-extension:' && ceUrl.hostname === hostname;
- }
- if (!HTTP_REGEX.test(protocol)) {
- return false;
- }
- if (IP_ADDRESS_REGEX.test(expected)) {
- // The domain has to be exactly equal to the pattern, as an IP domain will
- // only contain the IP, no extra character.
- return hostname === expected;
- }
- // Dots in pattern should be escaped.
- const escapedDomainPattern = expected.replace(/\./g, '\\.');
- // Non ip address domains.
- // domain.com = *.domain.com OR domain.com
- const re = new RegExp('^(.+\\.' + escapedDomainPattern + '|' + escapedDomainPattern + ')$', 'i');
- return re.test(hostname);
- }
- /**
- * @license
- * Copyright 2020 Google LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const NETWORK_TIMEOUT = new Delay(30000, 60000);
- /**
- * Reset unlaoded GApi modules. If gapi.load fails due to a network error,
- * it will stop working after a retrial. This is a hack to fix this issue.
- */
- function resetUnloadedGapiModules() {
- // Clear last failed gapi.load state to force next gapi.load to first
- // load the failed gapi.iframes module.
- // Get gapix.beacon context.
- const beacon = _window().___jsl;
- // Get current hint.
- if (beacon === null || beacon === void 0 ? void 0 : beacon.H) {
- // Get gapi hint.
- for (const hint of Object.keys(beacon.H)) {
- // Requested modules.
- beacon.H[hint].r = beacon.H[hint].r || [];
- // Loaded modules.
- beacon.H[hint].L = beacon.H[hint].L || [];
- // Set requested modules to a copy of the loaded modules.
- beacon.H[hint].r = [...beacon.H[hint].L];
- // Clear pending callbacks.
- if (beacon.CP) {
- for (let i = 0; i < beacon.CP.length; i++) {
- // Remove all failed pending callbacks.
- beacon.CP[i] = null;
- }
- }
- }
- }
- }
- function loadGapi(auth) {
- return new Promise((resolve, reject) => {
- var _a, _b, _c;
- // Function to run when gapi.load is ready.
- function loadGapiIframe() {
- // The developer may have tried to previously run gapi.load and failed.
- // Run this to fix that.
- resetUnloadedGapiModules();
- gapi.load('gapi.iframes', {
- callback: () => {
- resolve(gapi.iframes.getContext());
- },
- ontimeout: () => {
- // The above reset may be sufficient, but having this reset after
- // failure ensures that if the developer calls gapi.load after the
- // connection is re-established and before another attempt to embed
- // the iframe, it would work and would not be broken because of our
- // failed attempt.
- // Timeout when gapi.iframes.Iframe not loaded.
- resetUnloadedGapiModules();
- reject(_createError(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */));
- },
- timeout: NETWORK_TIMEOUT.get()
- });
- }
- if ((_b = (_a = _window().gapi) === null || _a === void 0 ? void 0 : _a.iframes) === null || _b === void 0 ? void 0 : _b.Iframe) {
- // If gapi.iframes.Iframe available, resolve.
- resolve(gapi.iframes.getContext());
- }
- else if (!!((_c = _window().gapi) === null || _c === void 0 ? void 0 : _c.load)) {
- // Gapi loader ready, load gapi.iframes.
- loadGapiIframe();
- }
- else {
- // Create a new iframe callback when this is called so as not to overwrite
- // any previous defined callback. This happens if this method is called
- // multiple times in parallel and could result in the later callback
- // overwriting the previous one. This would end up with a iframe
- // timeout.
- const cbName = _generateCallbackName('iframefcb');
- // GApi loader not available, dynamically load platform.js.
- _window()[cbName] = () => {
- // GApi loader should be ready.
- if (!!gapi.load) {
- loadGapiIframe();
- }
- else {
- // Gapi loader failed, throw error.
- reject(_createError(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */));
- }
- };
- // Load GApi loader.
- return _loadJS(`https://apis.google.com/js/api.js?onload=${cbName}`)
- .catch(e => reject(e));
- }
- }).catch(error => {
- // Reset cached promise to allow for retrial.
- cachedGApiLoader = null;
- throw error;
- });
- }
- let cachedGApiLoader = null;
- function _loadGapi(auth) {
- cachedGApiLoader = cachedGApiLoader || loadGapi(auth);
- return cachedGApiLoader;
- }
- /**
- * @license
- * Copyright 2020 Google LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const PING_TIMEOUT = new Delay(5000, 15000);
- const IFRAME_PATH = '__/auth/iframe';
- const EMULATED_IFRAME_PATH = 'emulator/auth/iframe';
- const IFRAME_ATTRIBUTES = {
- style: {
- position: 'absolute',
- top: '-100px',
- width: '1px',
- height: '1px'
- },
- 'aria-hidden': 'true',
- tabindex: '-1'
- };
- // Map from apiHost to endpoint ID for passing into iframe. In current SDK, apiHost can be set to
- // anything (not from a list of endpoints with IDs as in legacy), so this is the closest we can get.
- const EID_FROM_APIHOST = new Map([
- ["identitytoolkit.googleapis.com" /* DefaultConfig.API_HOST */, 'p'],
- ['staging-identitytoolkit.sandbox.googleapis.com', 's'],
- ['test-identitytoolkit.sandbox.googleapis.com', 't'] // test
- ]);
- function getIframeUrl(auth) {
- const config = auth.config;
- _assert(config.authDomain, auth, "auth-domain-config-required" /* AuthErrorCode.MISSING_AUTH_DOMAIN */);
- const url = config.emulator
- ? _emulatorUrl(config, EMULATED_IFRAME_PATH)
- : `https://${auth.config.authDomain}/${IFRAME_PATH}`;
- const params = {
- apiKey: config.apiKey,
- appName: auth.name,
- v: app.SDK_VERSION
- };
- const eid = EID_FROM_APIHOST.get(auth.config.apiHost);
- if (eid) {
- params.eid = eid;
- }
- const frameworks = auth._getFrameworks();
- if (frameworks.length) {
- params.fw = frameworks.join(',');
- }
- return `${url}?${util.querystring(params).slice(1)}`;
- }
- async function _openIframe(auth) {
- const context = await _loadGapi(auth);
- const gapi = _window().gapi;
- _assert(gapi, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return context.open({
- where: document.body,
- url: getIframeUrl(auth),
- messageHandlersFilter: gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER,
- attributes: IFRAME_ATTRIBUTES,
- dontclear: true
- }, (iframe) => new Promise(async (resolve, reject) => {
- await iframe.restyle({
- // Prevent iframe from closing on mouse out.
- setHideOnLeave: false
- });
- const networkError = _createError(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */);
- // Confirm iframe is correctly loaded.
- // To fallback on failure, set a timeout.
- const networkErrorTimer = _window().setTimeout(() => {
- reject(networkError);
- }, PING_TIMEOUT.get());
- // Clear timer and resolve pending iframe ready promise.
- function clearTimerAndResolve() {
- _window().clearTimeout(networkErrorTimer);
- resolve(iframe);
- }
- // This returns an IThenable. However the reject part does not call
- // when the iframe is not loaded.
- iframe.ping(clearTimerAndResolve).then(clearTimerAndResolve, () => {
- reject(networkError);
- });
- }));
- }
- /**
- * @license
- * Copyright 2020 Google LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const BASE_POPUP_OPTIONS = {
- location: 'yes',
- resizable: 'yes',
- statusbar: 'yes',
- toolbar: 'no'
- };
- const DEFAULT_WIDTH = 500;
- const DEFAULT_HEIGHT = 600;
- const TARGET_BLANK = '_blank';
- const FIREFOX_EMPTY_URL = 'http://localhost';
- class AuthPopup {
- constructor(window) {
- this.window = window;
- this.associatedEvent = null;
- }
- close() {
- if (this.window) {
- try {
- this.window.close();
- }
- catch (e) { }
- }
- }
- }
- function _open(auth, url, name, width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT) {
- const top = Math.max((window.screen.availHeight - height) / 2, 0).toString();
- const left = Math.max((window.screen.availWidth - width) / 2, 0).toString();
- let target = '';
- const options = Object.assign(Object.assign({}, BASE_POPUP_OPTIONS), { width: width.toString(), height: height.toString(), top,
- left });
- // Chrome iOS 7 and 8 is returning an undefined popup win when target is
- // specified, even though the popup is not necessarily blocked.
- const ua = util.getUA().toLowerCase();
- if (name) {
- target = _isChromeIOS(ua) ? TARGET_BLANK : name;
- }
- if (_isFirefox(ua)) {
- // Firefox complains when invalid URLs are popped out. Hacky way to bypass.
- url = url || FIREFOX_EMPTY_URL;
- // Firefox disables by default scrolling on popup windows, which can create
- // issues when the user has many Google accounts, for instance.
- options.scrollbars = 'yes';
- }
- const optionsString = Object.entries(options).reduce((accum, [key, value]) => `${accum}${key}=${value},`, '');
- if (_isIOSStandalone(ua) && target !== '_self') {
- openAsNewWindowIOS(url || '', target);
- return new AuthPopup(null);
- }
- // about:blank getting sanitized causing browsers like IE/Edge to display
- // brief error message before redirecting to handler.
- const newWin = window.open(url || '', target, optionsString);
- _assert(newWin, auth, "popup-blocked" /* AuthErrorCode.POPUP_BLOCKED */);
- // Flaky on IE edge, encapsulate with a try and catch.
- try {
- newWin.focus();
- }
- catch (e) { }
- return new AuthPopup(newWin);
- }
- function openAsNewWindowIOS(url, target) {
- const el = document.createElement('a');
- el.href = url;
- el.target = target;
- const click = document.createEvent('MouseEvent');
- click.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 1, null);
- el.dispatchEvent(click);
- }
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * URL for Authentication widget which will initiate the OAuth handshake
- *
- * @internal
- */
- const WIDGET_PATH = '__/auth/handler';
- /**
- * URL for emulated environment
- *
- * @internal
- */
- const EMULATOR_WIDGET_PATH = 'emulator/auth/handler';
- /**
- * Fragment name for the App Check token that gets passed to the widget
- *
- * @internal
- */
- const FIREBASE_APP_CHECK_FRAGMENT_ID = encodeURIComponent('fac');
- async function _getRedirectUrl(auth, provider, authType, redirectUrl, eventId, additionalParams) {
- _assert(auth.config.authDomain, auth, "auth-domain-config-required" /* AuthErrorCode.MISSING_AUTH_DOMAIN */);
- _assert(auth.config.apiKey, auth, "invalid-api-key" /* AuthErrorCode.INVALID_API_KEY */);
- const params = {
- apiKey: auth.config.apiKey,
- appName: auth.name,
- authType,
- redirectUrl,
- v: app.SDK_VERSION,
- eventId
- };
- if (provider instanceof FederatedAuthProvider) {
- provider.setDefaultLanguage(auth.languageCode);
- params.providerId = provider.providerId || '';
- if (!util.isEmpty(provider.getCustomParameters())) {
- params.customParameters = JSON.stringify(provider.getCustomParameters());
- }
- // TODO set additionalParams from the provider as well?
- for (const [key, value] of Object.entries(additionalParams || {})) {
- params[key] = value;
- }
- }
- if (provider instanceof BaseOAuthProvider) {
- const scopes = provider.getScopes().filter(scope => scope !== '');
- if (scopes.length > 0) {
- params.scopes = scopes.join(',');
- }
- }
- if (auth.tenantId) {
- params.tid = auth.tenantId;
- }
- // TODO: maybe set eid as endipointId
- // TODO: maybe set fw as Frameworks.join(",")
- const paramsDict = params;
- for (const key of Object.keys(paramsDict)) {
- if (paramsDict[key] === undefined) {
- delete paramsDict[key];
- }
- }
- // Sets the App Check token to pass to the widget
- const appCheckToken = await auth._getAppCheckToken();
- const appCheckTokenFragment = appCheckToken
- ? `#${FIREBASE_APP_CHECK_FRAGMENT_ID}=${encodeURIComponent(appCheckToken)}`
- : '';
- // Start at index 1 to skip the leading '&' in the query string
- return `${getHandlerBase(auth)}?${util.querystring(paramsDict).slice(1)}${appCheckTokenFragment}`;
- }
- function getHandlerBase({ config }) {
- if (!config.emulator) {
- return `https://${config.authDomain}/${WIDGET_PATH}`;
- }
- return _emulatorUrl(config, EMULATOR_WIDGET_PATH);
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * The special web storage event
- *
- */
- const WEB_STORAGE_SUPPORT_KEY = 'webStorageSupport';
- class BrowserPopupRedirectResolver {
- constructor() {
- this.eventManagers = {};
- this.iframes = {};
- this.originValidationPromises = {};
- this._redirectPersistence = browserSessionPersistence;
- this._completeRedirectFn = _getRedirectResult;
- this._overrideRedirectResult = _overrideRedirectResult;
- }
- // Wrapping in async even though we don't await anywhere in order
- // to make sure errors are raised as promise rejections
- async _openPopup(auth, provider, authType, eventId) {
- var _a;
- debugAssert((_a = this.eventManagers[auth._key()]) === null || _a === void 0 ? void 0 : _a.manager, '_initialize() not called before _openPopup()');
- const url = await _getRedirectUrl(auth, provider, authType, _getCurrentUrl(), eventId);
- return _open(auth, url, _generateEventId());
- }
- async _openRedirect(auth, provider, authType, eventId) {
- await this._originValidation(auth);
- const url = await _getRedirectUrl(auth, provider, authType, _getCurrentUrl(), eventId);
- _setWindowLocation(url);
- return new Promise(() => { });
- }
- _initialize(auth) {
- const key = auth._key();
- if (this.eventManagers[key]) {
- const { manager, promise } = this.eventManagers[key];
- if (manager) {
- return Promise.resolve(manager);
- }
- else {
- debugAssert(promise, 'If manager is not set, promise should be');
- return promise;
- }
- }
- const promise = this.initAndGetManager(auth);
- this.eventManagers[key] = { promise };
- // If the promise is rejected, the key should be removed so that the
- // operation can be retried later.
- promise.catch(() => {
- delete this.eventManagers[key];
- });
- return promise;
- }
- async initAndGetManager(auth) {
- const iframe = await _openIframe(auth);
- const manager = new AuthEventManager(auth);
- iframe.register('authEvent', (iframeEvent) => {
- _assert(iframeEvent === null || iframeEvent === void 0 ? void 0 : iframeEvent.authEvent, auth, "invalid-auth-event" /* AuthErrorCode.INVALID_AUTH_EVENT */);
- // TODO: Consider splitting redirect and popup events earlier on
- const handled = manager.onEvent(iframeEvent.authEvent);
- return { status: handled ? "ACK" /* GapiOutcome.ACK */ : "ERROR" /* GapiOutcome.ERROR */ };
- }, gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER);
- this.eventManagers[auth._key()] = { manager };
- this.iframes[auth._key()] = iframe;
- return manager;
- }
- _isIframeWebStorageSupported(auth, cb) {
- const iframe = this.iframes[auth._key()];
- iframe.send(WEB_STORAGE_SUPPORT_KEY, { type: WEB_STORAGE_SUPPORT_KEY }, result => {
- var _a;
- const isSupported = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a[WEB_STORAGE_SUPPORT_KEY];
- if (isSupported !== undefined) {
- cb(!!isSupported);
- }
- _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }, gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER);
- }
- _originValidation(auth) {
- const key = auth._key();
- if (!this.originValidationPromises[key]) {
- this.originValidationPromises[key] = _validateOrigin(auth);
- }
- return this.originValidationPromises[key];
- }
- get _shouldInitProactively() {
- // Mobile browsers and Safari need to optimistically initialize
- return _isMobileBrowser() || _isSafari() || _isIOS();
- }
- }
- /**
- * An implementation of {@link PopupRedirectResolver} suitable for browser
- * based applications.
- *
- * @public
- */
- const browserPopupRedirectResolver = BrowserPopupRedirectResolver;
- class MultiFactorAssertionImpl {
- constructor(factorId) {
- this.factorId = factorId;
- }
- _process(auth, session, displayName) {
- switch (session.type) {
- case "enroll" /* MultiFactorSessionType.ENROLL */:
- return this._finalizeEnroll(auth, session.credential, displayName);
- case "signin" /* MultiFactorSessionType.SIGN_IN */:
- return this._finalizeSignIn(auth, session.credential);
- default:
- return debugFail('unexpected MultiFactorSessionType');
- }
- }
- }
- /**
- * {@inheritdoc PhoneMultiFactorAssertion}
- *
- * @public
- */
- class PhoneMultiFactorAssertionImpl extends MultiFactorAssertionImpl {
- constructor(credential) {
- super("phone" /* FactorId.PHONE */);
- this.credential = credential;
- }
- /** @internal */
- static _fromCredential(credential) {
- return new PhoneMultiFactorAssertionImpl(credential);
- }
- /** @internal */
- _finalizeEnroll(auth, idToken, displayName) {
- return finalizeEnrollPhoneMfa(auth, {
- idToken,
- displayName,
- phoneVerificationInfo: this.credential._makeVerificationRequest()
- });
- }
- /** @internal */
- _finalizeSignIn(auth, mfaPendingCredential) {
- return finalizeSignInPhoneMfa(auth, {
- mfaPendingCredential,
- phoneVerificationInfo: this.credential._makeVerificationRequest()
- });
- }
- }
- /**
- * Provider for generating a {@link PhoneMultiFactorAssertion}.
- *
- * @public
- */
- class PhoneMultiFactorGenerator {
- constructor() { }
- /**
- * Provides a {@link PhoneMultiFactorAssertion} to confirm ownership of the phone second factor.
- *
- * @param phoneAuthCredential - A credential provided by {@link PhoneAuthProvider.credential}.
- * @returns A {@link PhoneMultiFactorAssertion} which can be used with
- * {@link MultiFactorResolver.resolveSignIn}
- */
- static assertion(credential) {
- return PhoneMultiFactorAssertionImpl._fromCredential(credential);
- }
- }
- /**
- * The identifier of the phone second factor: `phone`.
- */
- PhoneMultiFactorGenerator.FACTOR_ID = 'phone';
- /**
- * Provider for generating a {@link TotpMultiFactorAssertion}.
- *
- * @public
- */
- class TotpMultiFactorGenerator {
- /**
- * Provides a {@link TotpMultiFactorAssertion} to confirm ownership of
- * the TOTP (time-based one-time password) second factor.
- * This assertion is used to complete enrollment in TOTP second factor.
- *
- * @param secret A {@link TotpSecret} containing the shared secret key and other TOTP parameters.
- * @param oneTimePassword One-time password from TOTP App.
- * @returns A {@link TotpMultiFactorAssertion} which can be used with
- * {@link MultiFactorUser.enroll}.
- */
- static assertionForEnrollment(secret, oneTimePassword) {
- return TotpMultiFactorAssertionImpl._fromSecret(secret, oneTimePassword);
- }
- /**
- * Provides a {@link TotpMultiFactorAssertion} to confirm ownership of the TOTP second factor.
- * This assertion is used to complete signIn with TOTP as the second factor.
- *
- * @param enrollmentId identifies the enrolled TOTP second factor.
- * @param oneTimePassword One-time password from TOTP App.
- * @returns A {@link TotpMultiFactorAssertion} which can be used with
- * {@link MultiFactorResolver.resolveSignIn}.
- */
- static assertionForSignIn(enrollmentId, oneTimePassword) {
- return TotpMultiFactorAssertionImpl._fromEnrollmentId(enrollmentId, oneTimePassword);
- }
- /**
- * Returns a promise to {@link TotpSecret} which contains the TOTP shared secret key and other parameters.
- * Creates a TOTP secret as part of enrolling a TOTP second factor.
- * Used for generating a QR code URL or inputting into a TOTP app.
- * This method uses the auth instance corresponding to the user in the multiFactorSession.
- *
- * @param session The {@link MultiFactorSession} that the user is part of.
- * @returns A promise to {@link TotpSecret}.
- */
- static async generateSecret(session) {
- const mfaSession = session;
- _assert(typeof mfaSession.auth !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const response = await startEnrollTotpMfa(mfaSession.auth, {
- idToken: mfaSession.credential,
- totpEnrollmentInfo: {}
- });
- return TotpSecret._fromStartTotpMfaEnrollmentResponse(response, mfaSession.auth);
- }
- }
- /**
- * The identifier of the TOTP second factor: `totp`.
- */
- TotpMultiFactorGenerator.FACTOR_ID = "totp" /* FactorId.TOTP */;
- class TotpMultiFactorAssertionImpl extends MultiFactorAssertionImpl {
- constructor(otp, enrollmentId, secret) {
- super("totp" /* FactorId.TOTP */);
- this.otp = otp;
- this.enrollmentId = enrollmentId;
- this.secret = secret;
- }
- /** @internal */
- static _fromSecret(secret, otp) {
- return new TotpMultiFactorAssertionImpl(otp, undefined, secret);
- }
- /** @internal */
- static _fromEnrollmentId(enrollmentId, otp) {
- return new TotpMultiFactorAssertionImpl(otp, enrollmentId);
- }
- /** @internal */
- async _finalizeEnroll(auth, idToken, displayName) {
- _assert(typeof this.secret !== 'undefined', auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return finalizeEnrollTotpMfa(auth, {
- idToken,
- displayName,
- totpVerificationInfo: this.secret._makeTotpVerificationInfo(this.otp)
- });
- }
- /** @internal */
- async _finalizeSignIn(auth, mfaPendingCredential) {
- _assert(this.enrollmentId !== undefined && this.otp !== undefined, auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- const totpVerificationInfo = { verificationCode: this.otp };
- return finalizeSignInTotpMfa(auth, {
- mfaPendingCredential,
- mfaEnrollmentId: this.enrollmentId,
- totpVerificationInfo
- });
- }
- }
- /**
- * Provider for generating a {@link TotpMultiFactorAssertion}.
- *
- * Stores the shared secret key and other parameters to generate time-based OTPs.
- * Implements methods to retrieve the shared secret key and generate a QR code URL.
- * @public
- */
- class TotpSecret {
- // The public members are declared outside the constructor so the docs can be generated.
- constructor(secretKey, hashingAlgorithm, codeLength, codeIntervalSeconds, enrollmentCompletionDeadline, sessionInfo, auth) {
- this.sessionInfo = sessionInfo;
- this.auth = auth;
- this.secretKey = secretKey;
- this.hashingAlgorithm = hashingAlgorithm;
- this.codeLength = codeLength;
- this.codeIntervalSeconds = codeIntervalSeconds;
- this.enrollmentCompletionDeadline = enrollmentCompletionDeadline;
- }
- /** @internal */
- static _fromStartTotpMfaEnrollmentResponse(response, auth) {
- return new TotpSecret(response.totpSessionInfo.sharedSecretKey, response.totpSessionInfo.hashingAlgorithm, response.totpSessionInfo.verificationCodeLength, response.totpSessionInfo.periodSec, new Date(response.totpSessionInfo.finalizeEnrollmentTime).toUTCString(), response.totpSessionInfo.sessionInfo, auth);
- }
- /** @internal */
- _makeTotpVerificationInfo(otp) {
- return { sessionInfo: this.sessionInfo, verificationCode: otp };
- }
- /**
- * Returns a QR code URL as described in
- * https://github.com/google/google-authenticator/wiki/Key-Uri-Format
- * This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator.
- * If the optional parameters are unspecified, an accountName of <userEmail> and issuer of <firebaseAppName> are used.
- *
- * @param accountName the name of the account/app along with a user identifier.
- * @param issuer issuer of the TOTP (likely the app name).
- * @returns A QR code URL string.
- */
- generateQrCodeUrl(accountName, issuer) {
- var _a;
- let useDefaults = false;
- if (_isEmptyString(accountName) || _isEmptyString(issuer)) {
- useDefaults = true;
- }
- if (useDefaults) {
- if (_isEmptyString(accountName)) {
- accountName = ((_a = this.auth.currentUser) === null || _a === void 0 ? void 0 : _a.email) || 'unknownuser';
- }
- if (_isEmptyString(issuer)) {
- issuer = this.auth.name;
- }
- }
- return `otpauth://totp/${issuer}:${accountName}?secret=${this.secretKey}&issuer=${issuer}&algorithm=${this.hashingAlgorithm}&digits=${this.codeLength}`;
- }
- }
- /** @internal */
- function _isEmptyString(input) {
- return typeof input === 'undefined' || (input === null || input === void 0 ? void 0 : input.length) === 0;
- }
- var name = "@firebase/auth";
- var version = "0.23.2";
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class AuthInterop {
- constructor(auth) {
- this.auth = auth;
- this.internalListeners = new Map();
- }
- getUid() {
- var _a;
- this.assertAuthConfigured();
- return ((_a = this.auth.currentUser) === null || _a === void 0 ? void 0 : _a.uid) || null;
- }
- async getToken(forceRefresh) {
- this.assertAuthConfigured();
- await this.auth._initializationPromise;
- if (!this.auth.currentUser) {
- return null;
- }
- const accessToken = await this.auth.currentUser.getIdToken(forceRefresh);
- return { accessToken };
- }
- addAuthTokenListener(listener) {
- this.assertAuthConfigured();
- if (this.internalListeners.has(listener)) {
- return;
- }
- const unsubscribe = this.auth.onIdTokenChanged(user => {
- listener((user === null || user === void 0 ? void 0 : user.stsTokenManager.accessToken) || null);
- });
- this.internalListeners.set(listener, unsubscribe);
- this.updateProactiveRefresh();
- }
- removeAuthTokenListener(listener) {
- this.assertAuthConfigured();
- const unsubscribe = this.internalListeners.get(listener);
- if (!unsubscribe) {
- return;
- }
- this.internalListeners.delete(listener);
- unsubscribe();
- this.updateProactiveRefresh();
- }
- assertAuthConfigured() {
- _assert(this.auth._initializationPromise, "dependent-sdk-initialized-before-auth" /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */);
- }
- updateProactiveRefresh() {
- if (this.internalListeners.size > 0) {
- this.auth._startProactiveRefresh();
- }
- else {
- this.auth._stopProactiveRefresh();
- }
- }
- }
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function getVersionForPlatform(clientPlatform) {
- switch (clientPlatform) {
- case "Node" /* ClientPlatform.NODE */:
- return 'node';
- case "ReactNative" /* ClientPlatform.REACT_NATIVE */:
- return 'rn';
- case "Worker" /* ClientPlatform.WORKER */:
- return 'webworker';
- case "Cordova" /* ClientPlatform.CORDOVA */:
- return 'cordova';
- default:
- return undefined;
- }
- }
- /** @internal */
- function registerAuth(clientPlatform) {
- app._registerComponent(new component.Component("auth" /* _ComponentName.AUTH */, (container, { options: deps }) => {
- const app = container.getProvider('app').getImmediate();
- const heartbeatServiceProvider = container.getProvider('heartbeat');
- const appCheckServiceProvider = container.getProvider('app-check-internal');
- const { apiKey, authDomain } = app.options;
- _assert(apiKey && !apiKey.includes(':'), "invalid-api-key" /* AuthErrorCode.INVALID_API_KEY */, { appName: app.name });
- const config = {
- apiKey,
- authDomain,
- clientPlatform,
- apiHost: "identitytoolkit.googleapis.com" /* DefaultConfig.API_HOST */,
- tokenApiHost: "securetoken.googleapis.com" /* DefaultConfig.TOKEN_API_HOST */,
- apiScheme: "https" /* DefaultConfig.API_SCHEME */,
- sdkClientVersion: _getClientVersion(clientPlatform)
- };
- const authInstance = new AuthImpl(app, heartbeatServiceProvider, appCheckServiceProvider, config);
- _initializeAuthInstance(authInstance, deps);
- return authInstance;
- }, "PUBLIC" /* ComponentType.PUBLIC */)
- /**
- * Auth can only be initialized by explicitly calling getAuth() or initializeAuth()
- * For why we do this, See go/firebase-next-auth-init
- */
- .setInstantiationMode("EXPLICIT" /* InstantiationMode.EXPLICIT */)
- /**
- * Because all firebase products that depend on auth depend on auth-internal directly,
- * we need to initialize auth-internal after auth is initialized to make it available to other firebase products.
- */
- .setInstanceCreatedCallback((container, _instanceIdentifier, _instance) => {
- const authInternalProvider = container.getProvider("auth-internal" /* _ComponentName.AUTH_INTERNAL */);
- authInternalProvider.initialize();
- }));
- app._registerComponent(new component.Component("auth-internal" /* _ComponentName.AUTH_INTERNAL */, container => {
- const auth = _castAuth(container.getProvider("auth" /* _ComponentName.AUTH */).getImmediate());
- return (auth => new AuthInterop(auth))(auth);
- }, "PRIVATE" /* ComponentType.PRIVATE */).setInstantiationMode("EXPLICIT" /* InstantiationMode.EXPLICIT */));
- app.registerVersion(name, version, getVersionForPlatform(clientPlatform));
- // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
- app.registerVersion(name, version, 'cjs2017');
- }
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DEFAULT_ID_TOKEN_MAX_AGE = 5 * 60;
- const authIdTokenMaxAge = util.getExperimentalSetting('authIdTokenMaxAge') || DEFAULT_ID_TOKEN_MAX_AGE;
- let lastPostedIdToken = null;
- const mintCookieFactory = (url) => async (user) => {
- const idTokenResult = user && (await user.getIdTokenResult());
- const idTokenAge = idTokenResult &&
- (new Date().getTime() - Date.parse(idTokenResult.issuedAtTime)) / 1000;
- if (idTokenAge && idTokenAge > authIdTokenMaxAge) {
- return;
- }
- // Specifically trip null => undefined when logged out, to delete any existing cookie
- const idToken = idTokenResult === null || idTokenResult === void 0 ? void 0 : idTokenResult.token;
- if (lastPostedIdToken === idToken) {
- return;
- }
- lastPostedIdToken = idToken;
- await fetch(url, {
- method: idToken ? 'POST' : 'DELETE',
- headers: idToken
- ? {
- 'Authorization': `Bearer ${idToken}`
- }
- : {}
- });
- };
- /**
- * Returns the Auth instance associated with the provided {@link @firebase/app#FirebaseApp}.
- * If no instance exists, initializes an Auth instance with platform-specific default dependencies.
- *
- * @param app - The Firebase App.
- *
- * @public
- */
- function getAuth(app$1 = app.getApp()) {
- const provider = app._getProvider(app$1, 'auth');
- if (provider.isInitialized()) {
- return provider.getImmediate();
- }
- const auth = initializeAuth(app$1, {
- popupRedirectResolver: browserPopupRedirectResolver,
- persistence: [
- indexedDBLocalPersistence,
- browserLocalPersistence,
- browserSessionPersistence
- ]
- });
- const authTokenSyncUrl = util.getExperimentalSetting('authTokenSyncURL');
- if (authTokenSyncUrl) {
- const mintCookie = mintCookieFactory(authTokenSyncUrl);
- beforeAuthStateChanged(auth, mintCookie, () => mintCookie(auth.currentUser));
- onIdTokenChanged(auth, user => mintCookie(user));
- }
- const authEmulatorHost = util.getDefaultEmulatorHost('auth');
- if (authEmulatorHost) {
- connectAuthEmulator(auth, `http://${authEmulatorHost}`);
- }
- return auth;
- }
- registerAuth("Browser" /* ClientPlatform.BROWSER */);
- exports.AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY;
- exports.ActionCodeOperation = ActionCodeOperation;
- exports.ActionCodeURL = ActionCodeURL;
- exports.AuthCredential = AuthCredential;
- exports.AuthEventManager = AuthEventManager;
- exports.AuthImpl = AuthImpl;
- exports.AuthPopup = AuthPopup;
- exports.EmailAuthCredential = EmailAuthCredential;
- exports.EmailAuthProvider = EmailAuthProvider;
- exports.FacebookAuthProvider = FacebookAuthProvider;
- exports.FactorId = FactorId;
- exports.FetchProvider = FetchProvider;
- exports.GithubAuthProvider = GithubAuthProvider;
- exports.GoogleAuthProvider = GoogleAuthProvider;
- exports.OAuthCredential = OAuthCredential;
- exports.OAuthProvider = OAuthProvider;
- exports.OperationType = OperationType;
- exports.PhoneAuthCredential = PhoneAuthCredential;
- exports.PhoneAuthProvider = PhoneAuthProvider;
- exports.PhoneMultiFactorGenerator = PhoneMultiFactorGenerator;
- exports.ProviderId = ProviderId;
- exports.RecaptchaVerifier = RecaptchaVerifier;
- exports.SAMLAuthCredential = SAMLAuthCredential;
- exports.SAMLAuthProvider = SAMLAuthProvider;
- exports.SignInMethod = SignInMethod;
- exports.TotpMultiFactorGenerator = TotpMultiFactorGenerator;
- exports.TotpSecret = TotpSecret;
- exports.TwitterAuthProvider = TwitterAuthProvider;
- exports.UserImpl = UserImpl;
- exports._assert = _assert;
- exports._castAuth = _castAuth;
- exports._clearRedirectOutcomes = _clearRedirectOutcomes;
- exports._createError = _createError;
- exports._fail = _fail;
- exports._generateEventId = _generateEventId;
- exports._getClientVersion = _getClientVersion;
- exports._getInstance = _getInstance;
- exports._getProjectConfig = _getProjectConfig;
- exports._getRedirectResult = _getRedirectResult;
- exports._getRedirectUrl = _getRedirectUrl;
- exports._isAndroid = _isAndroid;
- exports._isIOS = _isIOS;
- exports._isIOS7Or8 = _isIOS7Or8;
- exports._overrideRedirectResult = _overrideRedirectResult;
- exports._persistenceKeyName = _persistenceKeyName;
- exports.applyActionCode = applyActionCode;
- exports.beforeAuthStateChanged = beforeAuthStateChanged;
- exports.browserLocalPersistence = browserLocalPersistence;
- exports.browserPopupRedirectResolver = browserPopupRedirectResolver;
- exports.browserSessionPersistence = browserSessionPersistence;
- exports.checkActionCode = checkActionCode;
- exports.confirmPasswordReset = confirmPasswordReset;
- exports.connectAuthEmulator = connectAuthEmulator;
- exports.createUserWithEmailAndPassword = createUserWithEmailAndPassword;
- exports.debugAssert = debugAssert;
- exports.debugErrorMap = debugErrorMap;
- exports.deleteUser = deleteUser;
- exports.fetchSignInMethodsForEmail = fetchSignInMethodsForEmail;
- exports.getAdditionalUserInfo = getAdditionalUserInfo;
- exports.getAuth = getAuth;
- exports.getIdToken = getIdToken;
- exports.getIdTokenResult = getIdTokenResult;
- exports.getMultiFactorResolver = getMultiFactorResolver;
- exports.getRedirectResult = getRedirectResult;
- exports.inMemoryPersistence = inMemoryPersistence;
- exports.indexedDBLocalPersistence = indexedDBLocalPersistence;
- exports.initializeAuth = initializeAuth;
- exports.initializeRecaptchaConfig = initializeRecaptchaConfig;
- exports.isSignInWithEmailLink = isSignInWithEmailLink;
- exports.linkWithCredential = linkWithCredential;
- exports.linkWithPhoneNumber = linkWithPhoneNumber;
- exports.linkWithPopup = linkWithPopup;
- exports.linkWithRedirect = linkWithRedirect;
- exports.multiFactor = multiFactor;
- exports.onAuthStateChanged = onAuthStateChanged;
- exports.onIdTokenChanged = onIdTokenChanged;
- exports.parseActionCodeURL = parseActionCodeURL;
- exports.prodErrorMap = prodErrorMap;
- exports.reauthenticateWithCredential = reauthenticateWithCredential;
- exports.reauthenticateWithPhoneNumber = reauthenticateWithPhoneNumber;
- exports.reauthenticateWithPopup = reauthenticateWithPopup;
- exports.reauthenticateWithRedirect = reauthenticateWithRedirect;
- exports.reload = reload;
- exports.sendEmailVerification = sendEmailVerification;
- exports.sendPasswordResetEmail = sendPasswordResetEmail;
- exports.sendSignInLinkToEmail = sendSignInLinkToEmail;
- exports.setPersistence = setPersistence;
- exports.signInAnonymously = signInAnonymously;
- exports.signInWithCredential = signInWithCredential;
- exports.signInWithCustomToken = signInWithCustomToken;
- exports.signInWithEmailAndPassword = signInWithEmailAndPassword;
- exports.signInWithEmailLink = signInWithEmailLink;
- exports.signInWithPhoneNumber = signInWithPhoneNumber;
- exports.signInWithPopup = signInWithPopup;
- exports.signInWithRedirect = signInWithRedirect;
- exports.signOut = signOut;
- exports.unlink = unlink;
- exports.updateCurrentUser = updateCurrentUser;
- exports.updateEmail = updateEmail;
- exports.updatePassword = updatePassword;
- exports.updatePhoneNumber = updatePhoneNumber;
- exports.updateProfile = updateProfile;
- exports.useDeviceLanguage = useDeviceLanguage;
- exports.verifyBeforeUpdateEmail = verifyBeforeUpdateEmail;
- exports.verifyPasswordResetCode = verifyPasswordResetCode;
- //# sourceMappingURL=index-5ca0aadd.js.map
|