Skip to content

Commit 3487b91

Browse files
committed
feat(oauth): added signIn and link for oauth
1 parent 90a2589 commit 3487b91

File tree

7 files changed

+128
-31
lines changed

7 files changed

+128
-31
lines changed

packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java

+42-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import com.facebook.react.bridge.WritableArray;
3131
import com.facebook.react.bridge.WritableMap;
3232
import com.google.android.gms.tasks.OnCompleteListener;
33+
import com.google.android.gms.tasks.OnFailureListener;
34+
import com.google.android.gms.tasks.OnSuccessListener;
35+
import com.google.android.gms.tasks.Task;
3336
import com.google.firebase.FirebaseApp;
3437
import com.google.firebase.FirebaseException;
3538
import com.google.firebase.FirebaseNetworkException;
@@ -203,7 +206,6 @@ public void addIdTokenListener(final String appName) {
203206

204207
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
205208
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
206-
207209
if (!mIdTokenListeners.containsKey(appName)) {
208210
FirebaseAuth.IdTokenListener newIdTokenListener =
209211
firebaseAuth1 -> {
@@ -838,6 +840,45 @@ private void signInWithCredential(
838840
});
839841
}
840842
}
843+
@ReactMethod
844+
public void signInWithProvider(String appName, String providerId, @Nullable String email, Promise promise){
845+
OAuthProvider.Builder provider = OAuthProvider.newBuilder(providerId);
846+
if(email != null){
847+
provider.addCustomParameter("login_hint", email);
848+
}
849+
Activity activity = getCurrentActivity();
850+
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
851+
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
852+
853+
OnSuccessListener onSuccess = new OnSuccessListener<AuthResult>(){
854+
@Override
855+
public void onSuccess(AuthResult authResult) {
856+
Log.d(TAG, "signInWithProvider:onComplete:success");
857+
promiseWithAuthResult(authResult, promise);
858+
}
859+
};
860+
861+
OnFailureListener onFailure = new OnFailureListener(){
862+
@Override
863+
public void onFailure(@NonNull Exception e) {
864+
Log.w(TAG, "signInWithProvider:onComplete:failure", e);
865+
promiseRejectAuthException(promise, e);
866+
}
867+
};
868+
869+
870+
Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
871+
if(pendingResultTask != null){
872+
pendingResultTask
873+
.addOnSuccessListener(onSuccess)
874+
.addOnFailureListener(onFailure);
875+
} else {
876+
firebaseAuth
877+
.startActivityForSignInWithProvider(activity, provider.build())
878+
.addOnSuccessListener(onSuccess)
879+
.addOnFailureListener(onFailure);
880+
}
881+
}
841882

842883
/**
843884
* signInWithPhoneNumber

packages/auth/e2e/auth.e2e.js

+10-12
Original file line numberDiff line numberDiff line change
@@ -912,12 +912,11 @@ describe('auth()', function () {
912912
});
913913

914914
describe('signInWithPopup', function () {
915-
it('should throw an unsupported error', function () {
916-
(() => {
917-
firebase.auth().signInWithPopup();
918-
}).should.throw(
919-
'firebase.auth().signInWithPopup() is unsupported by the native Firebase SDKs.',
920-
);
915+
it('should trigger the oauth flow', async function () {
916+
await (async () => {
917+
const provider = new firebase.auth.OAuthProvider('oidc.react.com');
918+
await firebase.auth().signInWithPopup(provider);
919+
}).should.not.throw();
921920
});
922921
});
923922

@@ -1025,12 +1024,11 @@ describe('auth()', function () {
10251024
});
10261025

10271026
describe('signInWithRedirect()', function () {
1028-
it('should throw an unsupported error', function () {
1029-
(() => {
1030-
firebase.auth().signInWithRedirect();
1031-
}).should.throw(
1032-
'firebase.auth().signInWithRedirect() is unsupported by the native Firebase SDKs.',
1033-
);
1027+
it('should trigger the oauth flow', async function () {
1028+
await (async () => {
1029+
const provider = new firebase.auth.OAuthProvider('oidc.react.com');
1030+
await firebase.auth().signInWithRedirect(provider);
1031+
}).should.not.throw();
10341032
});
10351033
});
10361034

packages/auth/e2e/provider.e2e.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,7 @@ describe('auth() -> Providers', function () {
149149
describe('OAuthProvider', function () {
150150
describe('constructor', function () {
151151
it('should throw an unsupported error', function () {
152-
(() => new firebase.auth.OAuthProvider()).should.throw(
153-
'`new OAuthProvider()` is not supported on the native Firebase SDKs.',
154-
);
152+
(() => new firebase.auth.OAuthProvider('oidc.react.com')).should.not.throw();
155153
});
156154
});
157155

packages/auth/lib/User.js

+20-6
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,29 @@ export default class User {
310310
);
311311
}
312312

313-
linkWithPopup() {
314-
throw new Error(
315-
'firebase.auth.User.linkWithPopup() is unsupported by the native Firebase SDKs.',
313+
async linkWithPopup(provider) {
314+
const credentials = await this.native.linkWithProvider(
315+
provider.providerId,
316+
provider.customParameters?.login_hint,
317+
);
318+
319+
return this.native.linkWithCredential(
320+
provider.providerId,
321+
credentials.token,
322+
credentials.secret,
316323
);
317324
}
318325

319-
linkWithRedirect() {
320-
throw new Error(
321-
'firebase.auth.User.linkWithRedirect() is unsupported by the native Firebase SDKs.',
326+
async linkWithRedirect(provider) {
327+
const credentials = await this.native.linkWithProvider(
328+
provider.providerId,
329+
provider.customParameters?.login_hint,
330+
);
331+
332+
return this.native.linkWithCredential(
333+
provider.providerId,
334+
credentials.token,
335+
credentials.secret,
322336
);
323337
}
324338

packages/auth/lib/index.d.ts

+40
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,46 @@ export namespace FirebaseAuthTypes {
11981198
*/
11991199
linkWithCredential(credential: AuthCredential): Promise<UserCredential>;
12001200

1201+
/**
1202+
* Link the user with a 3rd party provider.
1203+
*
1204+
* #### Example
1205+
*
1206+
* ```js
1207+
* const oauthProvider = new firebase.auth.OAuthProvider('oidc.react.com')
1208+
* const authCredentials = await firebase.auth().currentUser.linkWithPopup(oauthProvider);
1209+
* ```
1210+
*
1211+
* @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user.
1212+
* @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method.
1213+
* @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User.
1214+
* @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users.
1215+
* @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider.
1216+
* @throws on iOS {@link auth.NativeFirebaseAuthError}, on Android {@link auth.NativeFirebaseError}
1217+
* @param provider A created {@link auth.AuthProvider}.
1218+
*/
1219+
linkWithPopup(provider: Provider): Promise<AuthCredential>;
1220+
1221+
/**
1222+
* Link the user with a 3rd party provider.
1223+
*
1224+
* #### Example
1225+
*
1226+
* ```js
1227+
* const oauthProvider = new firebase.auth.OAuthProvider('oidc.react.com')
1228+
* const authCredentials = await firebase.auth().currentUser.linkWithPopup(oauthProvider);
1229+
* ```
1230+
*
1231+
* @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user.
1232+
* @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method.
1233+
* @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User.
1234+
* @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users.
1235+
* @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider.
1236+
* @throws on iOS {@link auth.NativeFirebaseAuthError}, on Android {@link auth.NativeFirebaseError}
1237+
* @param provider A created {@link auth.AuthProvider}.
1238+
*/
1239+
linkWithRedirect(provider: Provider): Promise<AuthCredential>;
1240+
12011241
/**
12021242
* Re-authenticate a user with a third-party authentication provider.
12031243
*

packages/auth/lib/index.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -360,16 +360,16 @@ class FirebaseAuthModule extends FirebaseModule {
360360
throw new Error('firebase.auth().setPersistence() is unsupported by the native Firebase SDKs.');
361361
}
362362

363-
signInWithPopup() {
364-
throw new Error(
365-
'firebase.auth().signInWithPopup() is unsupported by the native Firebase SDKs.',
366-
);
363+
signInWithPopup(provider) {
364+
return this.native
365+
.signInWithProvider(provider.providerId, provider.customParameters?.login_hint)
366+
.then(userCredential => this._setUserCredential(userCredential));
367367
}
368368

369369
signInWithRedirect() {
370-
throw new Error(
371-
'firebase.auth().signInWithRedirect() is unsupported by the native Firebase SDKs.',
372-
);
370+
return this.native
371+
.signInWithProvider(provider.providerId, provider.customParameters?.login_hint)
372+
.then(userCredential => this._setUserCredential(userCredential));
373373
}
374374

375375
// firebase issue - https://github.com/invertase/react-native-firebase/pull/655#issuecomment-349904680

packages/auth/lib/providers/OAuthProvider.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@
1818
const providerId = 'oauth';
1919

2020
export default class OAuthProvider {
21-
constructor() {
22-
throw new Error('`new OAuthProvider()` is not supported on the native Firebase SDKs.');
21+
constructor(providerId) {
22+
this.providerId = providerId;
23+
}
24+
25+
customParameters = {};
26+
27+
setCustomParameters(customParameters) {
28+
this.customParameters = customParameters;
2329
}
2430

2531
static get PROVIDER_ID() {

0 commit comments

Comments
 (0)