Skip to content

Commit 7e23065

Browse files
committed
Redirect strategy
1 parent 4aa4e24 commit 7e23065

File tree

3 files changed

+175
-33
lines changed

3 files changed

+175
-33
lines changed

packages-exp/auth-exp/demo/src/index.js

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
createUserWithEmailAndPassword,
3232
EmailAuthProvider,
3333
fetchSignInMethodsForEmail,
34-
getMultiFactorResolver,
3534
indexedDBLocalPersistence,
3635
initializeAuth,
3736
inMemoryPersistence,
@@ -54,10 +53,15 @@ import {
5453
updatePassword,
5554
updateProfile,
5655
verifyPasswordResetCode,
56+
getMultiFactorResolver,
5757
OAuthProvider,
5858
signInWithPopup,
5959
linkWithPopup,
6060
reauthenticateWithPopup,
61+
signInWithRedirect,
62+
linkWithRedirect,
63+
reauthenticateWithRedirect,
64+
getRedirectResult,
6165
browserPopupRedirectResolver
6266
} from '@firebase/auth-exp';
6367

@@ -1239,12 +1243,16 @@ function signInWithPopupRedirect(provider) {
12391243
const glob = {
12401244
signInWithPopup,
12411245
linkWithPopup,
1242-
reauthenticateWithPopup
1243-
};
1246+
reauthenticateWithPopup,
1247+
signInWithRedirect,
1248+
linkWithRedirect,
1249+
reauthenticateWithRedirect
1250+
}
12441251
let action = $('input[name=popup-redirect-action]:checked').val();
12451252
let type = $('input[name=popup-redirect-type]:checked').val();
12461253
let method = null;
12471254
let inst = null;
1255+
12481256
if (action == 'link' || action == 'reauthenticate') {
12491257
if (!activeUser()) {
12501258
alertError('No user logged in.');
@@ -1309,13 +1317,12 @@ function signInWithPopupRedirect(provider) {
13091317
onAuthError
13101318
);
13111319
} else {
1312-
alertNotImplemented();
1313-
// try {
1314-
// inst[method](provider).catch(onAuthError);
1315-
// } catch (error) {
1316-
// console.log('Error while calling ' + method);
1317-
// console.error(error);
1318-
// }
1320+
try {
1321+
glob[method](inst, provider, browserPopupRedirectResolver).catch(onAuthError);
1322+
} catch (error) {
1323+
console.log('Error while calling ' + method);
1324+
console.error(error);
1325+
}
13191326
}
13201327
}
13211328

@@ -1333,24 +1340,23 @@ function onAuthUserCredentialSuccess(result) {
13331340
* Displays redirect result.
13341341
*/
13351342
function onGetRedirectResult() {
1336-
alertNotImplemented();
1337-
// auth.getRedirectResult().then(function(response) {
1338-
// log('Redirect results:');
1339-
// if (response.credential) {
1340-
// log('Credential:');
1341-
// log(response.credential);
1342-
// } else {
1343-
// log('No credential');
1344-
// }
1345-
// if (response.user) {
1346-
// log('User\'s id:');
1347-
// log(response.user.uid);
1348-
// } else {
1349-
// log('No user');
1350-
// }
1351-
// logAdditionalUserInfo(response);
1352-
// console.log(response);
1353-
// }, onAuthError);
1343+
getRedirectResult(auth, browserPopupRedirectResolver).then(function(response) {
1344+
log('Redirect results:');
1345+
if (response.credential) {
1346+
log('Credential:');
1347+
log(response.credential);
1348+
} else {
1349+
log('No credential');
1350+
}
1351+
if (response.user) {
1352+
log('User\'s id:');
1353+
log(response.user.uid);
1354+
} else {
1355+
log('No user');
1356+
}
1357+
logAdditionalUserInfo(response);
1358+
console.log(response);
1359+
}, onAuthError);
13541360
}
13551361

13561362
/**
@@ -1775,11 +1781,10 @@ function initApp() {
17751781
}
17761782

17771783
// We check for redirect result to refresh user's data.
1778-
// TODO: redirect result
1779-
// auth.getRedirectResult().then(function(response) {
1780-
// refreshUserData();
1781-
// logAdditionalUserInfo(response);
1782-
// }, onAuthError);
1784+
getRedirectResult(auth, browserPopupRedirectResolver).then(function(response) {
1785+
refreshUserData();
1786+
logAdditionalUserInfo(response);
1787+
}, onAuthError);
17831788

17841789
// Bootstrap tooltips.
17851790
$('[data-toggle="tooltip"]').tooltip();
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import * as externs from '@firebase/auth-types-exp';
19+
20+
import { Auth } from '../../model/auth';
21+
import { AuthEvent, AuthEventType, PopupRedirectResolver } from '../../model/popup_redirect';
22+
import { User, UserCredential } from '../../model/user';
23+
import { _assertLinkedStatus } from '../user/link_unlink';
24+
import { _generateEventId } from '../util/event_id';
25+
import { _getInstance } from '../util/instantiator';
26+
import { AbstractPopupRedirectOperation } from './abstract_popup_redirect_operation';
27+
28+
export async function signInWithRedirect(
29+
authExtern: externs.Auth,
30+
provider: externs.AuthProvider,
31+
resolverExtern: externs.PopupRedirectResolver
32+
): Promise<never> {
33+
const auth = authExtern as Auth;
34+
const resolver: PopupRedirectResolver = _getInstance(resolverExtern);
35+
36+
return resolver._openRedirect(auth, provider, AuthEventType.SIGN_IN_VIA_REDIRECT);
37+
}
38+
39+
export async function reauthenticateWithRedirect(
40+
userExtern: externs.User,
41+
provider: externs.AuthProvider,
42+
resolverExtern: externs.PopupRedirectResolver
43+
): Promise<never> {
44+
const user = userExtern as User;
45+
const resolver: PopupRedirectResolver = _getInstance(resolverExtern);
46+
47+
const eventId = _generateEventId(`${user.uid}:::`);
48+
user._redirectEventId = eventId;
49+
await user.auth._setRedirectUser(user);
50+
51+
return resolver._openRedirect(user.auth, provider, AuthEventType.REAUTH_VIA_REDIRECT, eventId);
52+
}
53+
54+
export async function linkWithRedirect(
55+
userExtern: externs.User,
56+
provider: externs.AuthProvider,
57+
resolverExtern: externs.PopupRedirectResolver
58+
): Promise<never> {
59+
const user = userExtern as User;
60+
const resolver: PopupRedirectResolver = _getInstance(resolverExtern);
61+
62+
await _assertLinkedStatus(false, user, provider.providerId);
63+
64+
const eventId = _generateEventId(`${user.uid}:::`);
65+
user._redirectEventId = eventId;
66+
await user.auth._setRedirectUser(user);
67+
68+
return resolver._openRedirect(user.auth, provider, AuthEventType.LINK_VIA_REDIRECT, eventId);
69+
}
70+
71+
export async function getRedirectResult(authExtern: externs.Auth, resolverExtern: externs.PopupRedirectResolver): Promise<UserCredential> {
72+
const auth = authExtern as Auth;
73+
const resolver: PopupRedirectResolver = _getInstance(resolverExtern);
74+
const action = new RedirectAction(auth, resolver);
75+
return action.execute();
76+
}
77+
78+
79+
// We only get one redirect outcome for any one auth, so just store it
80+
// in here.
81+
const redirectOutcomeMap: Map<Auth, Promise<UserCredential>> = new Map();
82+
83+
class RedirectAction extends AbstractPopupRedirectOperation {
84+
eventId = null;
85+
86+
constructor(auth: Auth, resolver: PopupRedirectResolver) {
87+
super(auth, [
88+
AuthEventType.SIGN_IN_VIA_REDIRECT,
89+
AuthEventType.LINK_VIA_REDIRECT,
90+
AuthEventType.REAUTH_VIA_REDIRECT,
91+
],
92+
resolver);
93+
}
94+
95+
/**
96+
* Override the execute function; if we already have a redirect result, then
97+
* just return it.
98+
*/
99+
async execute(): Promise<UserCredential> {
100+
let readyOutcome = redirectOutcomeMap.get(this.auth);
101+
if (!readyOutcome) {
102+
readyOutcome = super.execute();
103+
redirectOutcomeMap.set(this.auth, readyOutcome);
104+
}
105+
106+
return readyOutcome;
107+
}
108+
109+
async onAuthEvent(event: AuthEvent): Promise<void> {
110+
if (event.type === AuthEventType.SIGN_IN_VIA_REDIRECT) {
111+
return super.onAuthEvent(event);
112+
}
113+
114+
if (event.eventId) {
115+
const user = this.auth._redirectUserForId(event.eventId);
116+
// TODO(samgho): What if user is null?
117+
if (user) {
118+
this.user = user;
119+
return super.onAuthEvent(event);
120+
}
121+
}
122+
}
123+
124+
async onExecution(): Promise<void> {
125+
}
126+
127+
cleanUp(): void {
128+
129+
}
130+
}

packages-exp/auth-exp/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ export {
102102
linkWithPopup,
103103
reauthenticateWithPopup
104104
} from './core/strategies/popup';
105+
export {
106+
signInWithRedirect,
107+
linkWithRedirect,
108+
reauthenticateWithRedirect,
109+
getRedirectResult
110+
} from './core/strategies/redirect';
105111

106112
// core
107113
export { ActionCodeURL, parseActionCodeURL } from './core/action_code_url';
@@ -128,4 +134,5 @@ export { PhoneMultiFactorGenerator } from './mfa/assertions/phone';
128134
export { getMultiFactorResolver } from './mfa/mfa_resolver';
129135
export { multiFactor } from './mfa/mfa_user';
130136

137+
// TODO(samhorlbeck): This should be exported as a single const
131138
export { browserPopupRedirectResolver } from './platform_browser/popup_redirect';

0 commit comments

Comments
 (0)