1
+ // [SNIPPET_REGISTRY disabled]
2
+ // [SNIPPETS_SEPARATION enabled]
3
+
4
+ const { SAMLAuthProvider
} = require ( ".pnpm/@[email protected] _@[email protected] /node_modules/@firebase/auth/dist/cordova/src" ) ;
5
+
6
+ function signInWithTenants ( ) {
7
+ // [START multitenant_set_tenant]
8
+ const { getAuth } = require ( "firebase/auth" ) ;
9
+ const auth = getAuth ( ) ;
10
+ const tenantId = "TENANT_ID1" ;
11
+ auth . tenantId = tenantId ;
12
+ // [END multitenant_set_tenant]
13
+ }
14
+
15
+ function switchTenantSingleAuthInstance ( auth ) {
16
+ // [START multitenant_switch_tenant]
17
+ // One Auth instance
18
+ // Switch to tenant1
19
+ auth . tenantId = "TENANT_ID1" ;
20
+ // Switch to tenant2
21
+ auth . tenantId = "TENANT_ID2" ;
22
+ // Switch back to project level IdPs
23
+ auth . tenantId = null ;
24
+ // [END multitenant_switch_tenant]
25
+ }
26
+
27
+ function switchTenantMultiAuthInstance ( firebaseConfig1 , firebaseConfig2 ) {
28
+ // [START multitenant_switch_tenant_multiinstance]
29
+ // Multiple Auth instances
30
+ const { initializeApp } = require ( "firebase/app" ) ;
31
+ const { getAuth } = require ( "firebase/auth" ) ;
32
+ const firebaseApp1 = initializeApp ( firebaseConfig1 , 'app1_for_tenantId1' ) ;
33
+ const firebaseApp2 = initializeApp ( firebaseConfig2 , 'app2_for_tenantId2' ) ;
34
+
35
+ const auth1 = getAuth ( firebaseApp1 ) ;
36
+ const auth2 = getAuth ( firebaseApp2 ) ;
37
+
38
+ auth1 . tenantId = "TENANT_ID1" ;
39
+ auth2 . tenantId = "TENANT_ID2" ;
40
+ // [END multitenant_switch_tenant_multiinstance]
41
+ }
42
+
43
+ function passwordSignInWithTenantDemo ( auth , email , password ) {
44
+ // [START multitenant_signin_password_demo]
45
+ const { signInWithEmailAndPassword, onAuthStateChanged } = require ( "firebase/auth" ) ;
46
+ // Switch to TENANT_ID1
47
+ auth . tenantId = 'TENANT_ID1' ;
48
+
49
+ // Sign in with tenant
50
+ signInWithEmailAndPassword ( auth , email , password )
51
+ . then ( ( userCredential ) => {
52
+ // User is signed in.
53
+ const user = userCredential . user ;
54
+ // user.tenantId is set to 'TENANT_ID1'.
55
+ // Switch to 'TENANT_ID2'.
56
+ auth . tenantId = 'TENANT_ID2' ;
57
+ // auth.currentUser still points to the user.
58
+ // auth.currentUser.tenantId is 'TENANT_ID1'.
59
+ } ) ;
60
+
61
+ // You could also get the current user from Auth state observer.
62
+ onAuthStateChanged ( auth , ( user ) => {
63
+ if ( user ) {
64
+ // User is signed in.
65
+ // user.tenantId is set to 'TENANT_ID1'.
66
+ } else {
67
+ // No user is signed in.
68
+ }
69
+ } ) ;
70
+ // [END multitenant_signin_password_demo]
71
+ }
72
+
73
+ function signUpWithTenant ( auth , email , password ) {
74
+ // [START multitenant_signup_password]
75
+ const { createUserWithEmailAndPassword } = require ( "firebase/auth" ) ;
76
+ auth . tenantId = 'TENANT_ID' ;
77
+
78
+ createUserWithEmailAndPassword ( auth , email , password )
79
+ . then ( ( userCredential ) => {
80
+ // User is signed in.
81
+ // userCredential.user.tenantId is 'TENANT_ID'.
82
+ } ) . catch ( ( error ) => {
83
+ // Handle / display error.
84
+ // ...
85
+ } ) ;
86
+ // [END multitenant_signup_password]
87
+ }
88
+
89
+
90
+ function passwordSignInWithTenant ( auth , email , password ) {
91
+ // [START multitenant_signin_password]
92
+ const { signInWithEmailAndPassword } = require ( "firebase/auth" ) ;
93
+ auth . tenantId = 'TENANT_ID' ;
94
+
95
+ signInWithEmailAndPassword ( auth , email , password )
96
+ . then ( ( userCredential ) => {
97
+ // User is signed in.
98
+ // userCredential.user.tenantId is 'TENANT_ID'.
99
+ } ) . catch ( ( error ) => {
100
+ // Handle / display error.
101
+ // ...
102
+ } ) ;
103
+ // [END multitenant_signin_password]
104
+ }
105
+
106
+ function samlSignInPopupTenant ( auth , provider ) {
107
+ // [START multitenant_signin_saml_popup]
108
+ const { signInWithPopup } = require ( "firebase/auth" ) ;
109
+ // Switch to TENANT_ID1.
110
+ auth . tenantId = 'TENANT_ID1' ;
111
+
112
+ // Sign-in with popup.
113
+ signInWithPopup ( auth , provider )
114
+ . then ( ( userCredential ) => {
115
+ // User is signed in.
116
+ const user = userCredential . user ;
117
+ // user.tenantId is set to 'TENANT_ID1'.
118
+ // Provider data available from the result.user.getIdToken()
119
+ // or from result.user.providerData
120
+ } )
121
+ . catch ( ( error ) => {
122
+ // Handle / display error.
123
+ // ...
124
+ } ) ;
125
+ // [END multitenant_signin_saml_popup]
126
+ }
127
+
128
+ function samlSignInRedirectTenant ( auth , provider ) {
129
+ // [START multitenant_signin_saml_redirect]
130
+ const { signInWithRedirect, getRedirectResult } = require ( "firebase/auth" ) ;
131
+ // Switch to TENANT_ID1.
132
+ auth . tenantId = 'TENANT_ID1' ;
133
+
134
+ // Sign-in with redirect.
135
+ signInWithRedirect ( auth , provider ) ;
136
+
137
+ // After the user completes sign-in and returns to the app, you can get
138
+ // the sign-in result by calling getRedirectResult. However, if they sign out
139
+ // and sign in again with an IdP, no tenant is used.
140
+ getRedirectResult ( auth )
141
+ . then ( ( result ) => {
142
+ // User is signed in.
143
+ // The tenant ID available in result.user.tenantId.
144
+ // Provider data available from the result.user.getIdToken()
145
+ // or from result.user.providerData
146
+ } )
147
+ . catch ( ( error ) => {
148
+ // Handle / display error.
149
+ // ...
150
+ } ) ;
151
+ // [END multitenant_signin_saml_redirect]
152
+ }
153
+
154
+ function sendSignInLinkToEmailTenant ( auth , email , actionCodeSettings ) {
155
+ // [START multitenant_send_emaillink]
156
+ const { sendSignInLinkToEmail } = require ( "firebase/auth" ) ;
157
+ // Switch to TENANT_ID1
158
+ auth . tenantId = 'TENANT_ID1' ;
159
+
160
+ sendSignInLinkToEmail ( auth , email , actionCodeSettings )
161
+ . then ( ( ) => {
162
+ // The link was successfully sent. Inform the user.
163
+ // Save the email locally so you don't need to ask the user for it again
164
+ // if they open the link on the same device.
165
+ window . localStorage . setItem ( 'emailForSignIn' , email ) ;
166
+ } )
167
+ . catch ( ( error ) => {
168
+ // Handle / display error.
169
+ // ...
170
+ } ) ;
171
+ // [END multitenant_send_emaillink]
172
+ }
173
+
174
+ function signInWithEmailLinkTenant ( auth ) {
175
+ // [START multitenant_signin_emaillink]
176
+ const { isSignInWithEmailLink, parseActionCodeURL, signInWithEmailLink } = require ( "firebase/auth" ) ;
177
+ if ( isSignInWithEmailLink ( auth , window . location . href ) ) {
178
+ const actionCodeUrl = parseActionCodeURL ( window . location . href ) ;
179
+ if ( actionCodeUrl . tenantId ) {
180
+ auth . tenantId = actionCodeUrl . tenantId ;
181
+ }
182
+ let email = window . localStorage . getItem ( 'emailForSignIn' ) ;
183
+ if ( ! email ) {
184
+ // User opened the link on a different device. To prevent session fixation
185
+ // attacks, ask the user to provide the associated email again. For example:
186
+ email = window . prompt ( 'Please provide your email for confirmation' ) ;
187
+ }
188
+ // The client SDK will parse the code from the link for you.
189
+ signInWithEmailLink ( auth , email , window . location . href )
190
+ . then ( ( result ) => {
191
+ // User is signed in.
192
+ // tenant ID available in result.user.tenantId.
193
+ // Clear email from storage.
194
+ window . localStorage . removeItem ( 'emailForSignIn' ) ;
195
+ } ) ;
196
+ }
197
+ // [END multitenant_signin_emaillink]
198
+ }
199
+
200
+ // Same as the code in auth/ since this is the admin SDK.
201
+ function createCustomTokenTenant ( admin , uid ) {
202
+ // [START multitenant_create_custom_token]
203
+ // Ensure you're using a tenant-aware auth instance
204
+ const tenantManager = admin . auth ( ) . tenantManager ( ) ;
205
+ const tenantAuth = tenantManager . authForTenant ( 'TENANT_ID1' ) ;
206
+
207
+ // Create a custom token in the usual manner
208
+ tenantAuth . createCustomToken ( uid )
209
+ . then ( ( customToken ) => {
210
+ // Send token back to client
211
+ } )
212
+ . catch ( ( error ) => {
213
+ console . log ( 'Error creating custom token:' , error ) ;
214
+ } ) ;
215
+ // [END multitenant_create_custom_token]
216
+ }
217
+
218
+ function signInWithCustomTokenTenant ( auth , token ) {
219
+ // [START multitenant_signin_custom_token]
220
+ const { signInWithCustomToken } = require ( "firebase/auth" ) ;
221
+ auth . tenantId = 'TENANT_ID1' ;
222
+
223
+ signInWithCustomToken ( auth , token )
224
+ . catch ( ( error ) => {
225
+ // Handle / display error.
226
+ // ...
227
+ } ) ;
228
+ // [END multitenant_signin_custom_token]
229
+ }
230
+
231
+ function linkAccountTenant ( auth , provider , email , password ) {
232
+ // [START multitenant_account_linking]
233
+ const { signInWithPopup, EmailAuthProvider, linkWithCredential, SAMLAuthProvider, signInWithCredential } = require ( "firebase/auth" ) ;
234
+ // Switch to TENANT_ID1
235
+ auth . tenantId = 'TENANT_ID1' ;
236
+
237
+ // Sign-in with popup
238
+ signInWithPopup ( auth , provider )
239
+ . then ( ( userCredential ) => {
240
+ // Existing user with e.g. SAML provider.
241
+ const prevUser = userCredential . user ;
242
+ const emailCredential =
243
+ EmailAuthProvider . credential ( email , password ) ;
244
+ return linkWithCredential ( prevUser , emailCredential )
245
+ . then ( ( linkResult ) => {
246
+ // Sign in with the newly linked credential
247
+ const linkCredential = SAMLAuthProvider . credentialFromResult ( linkResult ) ;
248
+ return signInWithCredential ( auth , linkCredential ) ;
249
+ } )
250
+ . then ( ( signInResult ) => {
251
+ // Handle sign in of merged user
252
+ // ...
253
+ } ) ;
254
+ } )
255
+ . catch ( ( error ) => {
256
+ // Handle / display error.
257
+ // ...
258
+ } ) ;
259
+ // [END multitenant_account_linking]
260
+ }
261
+
262
+ function accountExistsPopupTenant ( auth , samlProvider , googleProvider , goToApp ) {
263
+ // [START multitenant_account_exists_popup]
264
+ const { signInWithPopup, fetchSignInMethodsForEmail, linkWithCredential } = require ( "firebase/auth" ) ;
265
+ // Step 1.
266
+ // User tries to sign in to the SAML provider in that tenant.
267
+ auth . tenantId = 'TENANT_ID' ;
268
+ signInWithPopup ( auth , samlProvider )
269
+ . catch ( ( error ) => {
270
+ // An error happened.
271
+ if ( error . code === 'auth/account-exists-with-different-credential' ) {
272
+ // Step 2.
273
+ // User's email already exists.
274
+ // The pending SAML credential.
275
+ const pendingCred = error . credential ;
276
+ // The credential's tenantId if needed: error.tenantId
277
+ // The provider account's email address.
278
+ const email = error . email ;
279
+ // Get sign-in methods for this email.
280
+ fetchSignInMethodsForEmail ( email , auth )
281
+ . then ( ( methods ) => {
282
+ // Step 3.
283
+ // Ask the user to sign in with existing Google account.
284
+ if ( methods [ 0 ] == 'google.com' ) {
285
+ signInWithPopup ( auth , googleProvider )
286
+ . then ( ( result ) => {
287
+ // Step 4
288
+ // Link the SAML AuthCredential to the existing user.
289
+ linkWithCredential ( result . user , pendingCred )
290
+ . then ( ( linkResult ) => {
291
+ // SAML account successfully linked to the existing
292
+ // user.
293
+ goToApp ( ) ;
294
+ } ) ;
295
+ } ) ;
296
+ }
297
+ } ) ;
298
+ }
299
+ } ) ;
300
+ // [END multitenant_account_exists_popup]
301
+ }
302
+
303
+ function accountExistsRedirectTenant ( auth , samlProvider , googleProvider , goToApp ) {
304
+ // [START multitenant_account_exists_redirect]
305
+ const { signInWithRedirect, getRedirectResult, fetchSignInMethodsForEmail, linkWithCredential } = require ( "firebase/auth" ) ;
306
+ // Step 1.
307
+ // User tries to sign in to SAML provider.
308
+ auth . tenantId = 'TENANT_ID' ;
309
+ signInWithRedirect ( auth , samlProvider ) ;
310
+ var pendingCred ;
311
+ // Redirect back from SAML IDP. auth.tenantId is null after redirecting.
312
+ getRedirectResult ( auth ) . catch ( ( error ) => {
313
+ if ( error . code === 'auth/account-exists-with-different-credential' ) {
314
+ // Step 2.
315
+ // User's email already exists.
316
+ const tenantId = error . tenantId ;
317
+ // The pending SAML credential.
318
+ pendingCred = error . credential ;
319
+ // The provider account's email address.
320
+ const email = error . email ;
321
+ // Need to set the tenant ID again as the page was reloaded and the
322
+ // previous setting was reset.
323
+ auth . tenantId = tenantId ;
324
+ // Get sign-in methods for this email.
325
+ fetchSignInMethodsForEmail ( auth , email )
326
+ . then ( ( methods ) => {
327
+ // Step 3.
328
+ // Ask the user to sign in with existing Google account.
329
+ if ( methods [ 0 ] == 'google.com' ) {
330
+ signInWithRedirect ( auth , googleProvider ) ;
331
+ }
332
+ } ) ;
333
+ }
334
+ } ) ;
335
+
336
+ // Redirect back from Google. auth.tenantId is null after redirecting.
337
+ getRedirectResult ( auth ) . then ( ( result ) => {
338
+ // Step 4
339
+ // Link the SAML AuthCredential to the existing user.
340
+ // result.user.tenantId is 'TENANT_ID'.
341
+ linkWithCredential ( result . user , pendingCred )
342
+ . then ( ( linkResult ) => {
343
+ // SAML account successfully linked to the existing
344
+ // user.
345
+ goToApp ( ) ;
346
+ } ) ;
347
+ } ) ;
348
+ // [END multitenant_account_exists_redirect]
349
+ }
0 commit comments