Skip to content

Commit

Permalink
feat(oauth): added signIn and link for oauth
Browse files Browse the repository at this point in the history
  • Loading branch information
Aetherall committed Apr 3, 2023
1 parent 90a2589 commit 3487b91
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseException;
import com.google.firebase.FirebaseNetworkException;
Expand Down Expand Up @@ -203,7 +206,6 @@ public void addIdTokenListener(final String appName) {

FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);

if (!mIdTokenListeners.containsKey(appName)) {
FirebaseAuth.IdTokenListener newIdTokenListener =
firebaseAuth1 -> {
Expand Down Expand Up @@ -838,6 +840,45 @@ private void signInWithCredential(
});
}
}
@ReactMethod
public void signInWithProvider(String appName, String providerId, @Nullable String email, Promise promise){
OAuthProvider.Builder provider = OAuthProvider.newBuilder(providerId);
if(email != null){
provider.addCustomParameter("login_hint", email);
}
Activity activity = getCurrentActivity();
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);

OnSuccessListener onSuccess = new OnSuccessListener<AuthResult>(){
@Override
public void onSuccess(AuthResult authResult) {
Log.d(TAG, "signInWithProvider:onComplete:success");
promiseWithAuthResult(authResult, promise);
}
};

OnFailureListener onFailure = new OnFailureListener(){
@Override
public void onFailure(@NonNull Exception e) {
Log.w(TAG, "signInWithProvider:onComplete:failure", e);
promiseRejectAuthException(promise, e);
}
};


Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
if(pendingResultTask != null){
pendingResultTask
.addOnSuccessListener(onSuccess)
.addOnFailureListener(onFailure);
} else {
firebaseAuth
.startActivityForSignInWithProvider(activity, provider.build())
.addOnSuccessListener(onSuccess)
.addOnFailureListener(onFailure);
}
}

/**
* signInWithPhoneNumber
Expand Down
22 changes: 10 additions & 12 deletions packages/auth/e2e/auth.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -912,12 +912,11 @@ describe('auth()', function () {
});

describe('signInWithPopup', function () {
it('should throw an unsupported error', function () {
(() => {
firebase.auth().signInWithPopup();
}).should.throw(
'firebase.auth().signInWithPopup() is unsupported by the native Firebase SDKs.',
);
it('should trigger the oauth flow', async function () {
await (async () => {
const provider = new firebase.auth.OAuthProvider('oidc.react.com');
await firebase.auth().signInWithPopup(provider);
}).should.not.throw();
});
});

Expand Down Expand Up @@ -1025,12 +1024,11 @@ describe('auth()', function () {
});

describe('signInWithRedirect()', function () {
it('should throw an unsupported error', function () {
(() => {
firebase.auth().signInWithRedirect();
}).should.throw(
'firebase.auth().signInWithRedirect() is unsupported by the native Firebase SDKs.',
);
it('should trigger the oauth flow', async function () {
await (async () => {
const provider = new firebase.auth.OAuthProvider('oidc.react.com');
await firebase.auth().signInWithRedirect(provider);
}).should.not.throw();
});
});

Expand Down
4 changes: 1 addition & 3 deletions packages/auth/e2e/provider.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,7 @@ describe('auth() -> Providers', function () {
describe('OAuthProvider', function () {
describe('constructor', function () {
it('should throw an unsupported error', function () {
(() => new firebase.auth.OAuthProvider()).should.throw(
'`new OAuthProvider()` is not supported on the native Firebase SDKs.',
);
(() => new firebase.auth.OAuthProvider('oidc.react.com')).should.not.throw();
});
});

Expand Down
26 changes: 20 additions & 6 deletions packages/auth/lib/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,29 @@ export default class User {
);
}

linkWithPopup() {
throw new Error(
'firebase.auth.User.linkWithPopup() is unsupported by the native Firebase SDKs.',
async linkWithPopup(provider) {
const credentials = await this.native.linkWithProvider(
provider.providerId,
provider.customParameters?.login_hint,
);

return this.native.linkWithCredential(
provider.providerId,
credentials.token,
credentials.secret,
);
}

linkWithRedirect() {
throw new Error(
'firebase.auth.User.linkWithRedirect() is unsupported by the native Firebase SDKs.',
async linkWithRedirect(provider) {
const credentials = await this.native.linkWithProvider(
provider.providerId,
provider.customParameters?.login_hint,
);

return this.native.linkWithCredential(
provider.providerId,
credentials.token,
credentials.secret,
);
}

Expand Down
40 changes: 40 additions & 0 deletions packages/auth/lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,46 @@ export namespace FirebaseAuthTypes {
*/
linkWithCredential(credential: AuthCredential): Promise<UserCredential>;

/**
* Link the user with a 3rd party provider.
*
* #### Example
*
* ```js
* const oauthProvider = new firebase.auth.OAuthProvider('oidc.react.com')
* const authCredentials = await firebase.auth().currentUser.linkWithPopup(oauthProvider);
* ```
*
* @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.
* @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.
* @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.
* @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users.
* @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.
* @throws on iOS {@link auth.NativeFirebaseAuthError}, on Android {@link auth.NativeFirebaseError}
* @param provider A created {@link auth.AuthProvider}.
*/
linkWithPopup(provider: Provider): Promise<AuthCredential>;

/**
* Link the user with a 3rd party provider.
*
* #### Example
*
* ```js
* const oauthProvider = new firebase.auth.OAuthProvider('oidc.react.com')
* const authCredentials = await firebase.auth().currentUser.linkWithPopup(oauthProvider);
* ```
*
* @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.
* @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.
* @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.
* @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users.
* @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.
* @throws on iOS {@link auth.NativeFirebaseAuthError}, on Android {@link auth.NativeFirebaseError}
* @param provider A created {@link auth.AuthProvider}.
*/
linkWithRedirect(provider: Provider): Promise<AuthCredential>;

/**
* Re-authenticate a user with a third-party authentication provider.
*
Expand Down
14 changes: 7 additions & 7 deletions packages/auth/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,16 +360,16 @@ class FirebaseAuthModule extends FirebaseModule {
throw new Error('firebase.auth().setPersistence() is unsupported by the native Firebase SDKs.');
}

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

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

// firebase issue - https://github.com/invertase/react-native-firebase/pull/655#issuecomment-349904680
Expand Down
10 changes: 8 additions & 2 deletions packages/auth/lib/providers/OAuthProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@
const providerId = 'oauth';

export default class OAuthProvider {
constructor() {
throw new Error('`new OAuthProvider()` is not supported on the native Firebase SDKs.');
constructor(providerId) {
this.providerId = providerId;
}

customParameters = {};

setCustomParameters(customParameters) {
this.customParameters = customParameters;
}

static get PROVIDER_ID() {
Expand Down

0 comments on commit 3487b91

Please sign in to comment.