Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(authentication): provide the auto-retrieved SMS verification code #272

Merged
merged 6 commits into from
Dec 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/spotty-tigers-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@capacitor-firebase/authentication": minor
---

feat(android): provide the auto-retrieved SMS verification code
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

96 changes: 91 additions & 5 deletions packages/authentication/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,9 @@ const useEmulator = async () => {
* [`useAppLanguage()`](#useapplanguage)
* [`useEmulator(...)`](#useemulator)
* [`addListener('authStateChange', ...)`](#addlistenerauthstatechange)
* [`addListener('phoneVerificationCompleted', ...)`](#addlistenerphoneverificationcompleted)
* [`addListener('phoneVerificationFailed', ...)`](#addlistenerphoneverificationfailed)
* [`addListener('phoneCodeSent', ...)`](#addlistenerphonecodesent)
* [`removeAllListeners()`](#removealllisteners)
* [Interfaces](#interfaces)
* [Type Aliases](#type-aliases)
Expand Down Expand Up @@ -1293,6 +1296,68 @@ Listen for the user's sign-in state changes.
--------------------


### addListener('phoneVerificationCompleted', ...)

```typescript
addListener(eventName: 'phoneVerificationCompleted', listenerFunc: PhoneVerificationCompletedListener) => Promise<PluginListenerHandle> & PluginListenerHandle
```

Listen for a completed phone verification.

Only available for Android.

| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------------------- |
| **`eventName`** | <code>'phoneVerificationCompleted'</code> |
| **`listenerFunc`** | <code><a href="#phoneverificationcompletedlistener">PhoneVerificationCompletedListener</a></code> |

**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt; & <a href="#pluginlistenerhandle">PluginListenerHandle</a></code>

**Since:** 1.3.0

--------------------


### addListener('phoneVerificationFailed', ...)

```typescript
addListener(eventName: 'phoneVerificationFailed', listenerFunc: PhoneVerificationFailedListener) => Promise<PluginListenerHandle> & PluginListenerHandle
```

Listen for a failed phone verification.

| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------------- |
| **`eventName`** | <code>'phoneVerificationFailed'</code> |
| **`listenerFunc`** | <code><a href="#phoneverificationfailedlistener">PhoneVerificationFailedListener</a></code> |

**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt; & <a href="#pluginlistenerhandle">PluginListenerHandle</a></code>

**Since:** 1.3.0

--------------------


### addListener('phoneCodeSent', ...)

```typescript
addListener(eventName: 'phoneCodeSent', listenerFunc: PhoneCodeSentListener) => Promise<PluginListenerHandle> & PluginListenerHandle
```

Listen for a phone verification code.

| Param | Type |
| ------------------ | ----------------------------------------------------------------------- |
| **`eventName`** | <code>'phoneCodeSent'</code> |
| **`listenerFunc`** | <code><a href="#phonecodesentlistener">PhoneCodeSentListener</a></code> |

**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt; & <a href="#pluginlistenerhandle">PluginListenerHandle</a></code>

**Since:** 1.3.0

--------------------


### removeAllListeners()

```typescript
Expand Down Expand Up @@ -1544,11 +1609,11 @@ bundle identifiers.

#### SignInWithPhoneNumberOptions

| Prop | Type | Description | Since |
| ---------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| **`phoneNumber`** | <code>string</code> | The phone number to be verified. | 0.1.0 |
| **`verificationId`** | <code>string</code> | The verification ID which will be returned when `signInWithPhoneNumber` is called for the first time. The `verificationCode` must also be provided. | 0.1.0 |
| **`verificationCode`** | <code>string</code> | The verification code from the SMS message. The `verificationId` must also be provided. | 0.1.0 |
| Prop | Type | Description | Since |
| ---------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| **`phoneNumber`** | <code>string</code> | The phone number to be verified. Cannot be used in combination with `verificationId` and `verificationCode`. Use the `phoneVerificationCompleted` listener to be notified when the verification is completed. Use the `phoneVerificationFailed` listener to be notified when the verification is failed. Use the `phoneCodeSent` listener to get the verification id. | 0.1.0 |
| **`verificationId`** | <code>string</code> | The verification ID received from the `phoneCodeSent` listener. The `verificationCode` must also be provided. | 0.1.0 |
| **`verificationCode`** | <code>string</code> | The verification code either received from the `phoneCodeSent` listener or entered by the user. The `verificationId` must also be provided. | 0.1.0 |


#### UnlinkResult
Expand Down Expand Up @@ -1621,6 +1686,27 @@ Callback to receive the user's sign-in state change notifications.
<code>(change: <a href="#authstatechange">AuthStateChange</a>): void</code>


#### PhoneVerificationCompletedListener

Callback to receive the verification code sent to the user's phone number.

<code>(event: { verificationCode: string; }): void</code>


#### PhoneVerificationFailedListener

Callback to receive notifications of failed phone verification.

<code>(event: { message: string; }): void</code>


#### PhoneCodeSentListener

Callback to receive the verification ID.

<code>(event: { verificationId: string; }): void</code>


### Enums


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,18 @@ public void handleFailedLink(final PluginCall call, String message, Exception ex
call.reject(message, exception);
}

public void handlePhoneVerificationCompleted(String smsCode) {
plugin.handlePhoneVerificationCompleted(smsCode);
}

public void handlePhoneVerificationFailed(Exception exception) {
plugin.handlePhoneVerificationFailed(exception);
}

public void handlePhoneCodeSent(String verificationId) {
plugin.handlePhoneCodeSent(verificationId);
}

public FirebaseAuth getFirebaseAuthInstance() {
return firebaseAuthInstance;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.ActivityCallback;
import com.getcapacitor.annotation.CapacitorPlugin;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.ActionCodeSettings;
import com.google.firebase.auth.FirebaseUser;
import io.capawesome.capacitorjs.plugins.firebase.authentication.handlers.FacebookAuthProviderHandler;
Expand All @@ -16,6 +17,9 @@
public class FirebaseAuthenticationPlugin extends Plugin {

public static final String TAG = "FirebaseAuthentication";
public static final String PHONE_VERIFICATION_COMPLETED_EVENT = "phoneVerificationCompleted";
public static final String PHONE_VERIFICATION_FAILED_EVENT = "phoneVerificationFailed";
public static final String PHONE_CODE_SENT_EVENT = "phoneCodeSent";
public static final String ERROR_PROVIDER_ID_MISSING = "providerId must be provided.";
public static final String ERROR_NO_USER_SIGNED_IN = "No user is signed in.";
public static final String ERROR_OOB_CODE_MISSING = "oobCode must be provided.";
Expand Down Expand Up @@ -591,6 +595,24 @@ public void useEmulator(PluginCall call) {
}
}

public void handlePhoneVerificationCompleted(String smsCode) {
JSObject result = new JSObject();
result.put("verificationCode", smsCode);
notifyListeners(PHONE_VERIFICATION_COMPLETED_EVENT, result, true);
}

public void handlePhoneVerificationFailed(Exception exception) {
JSObject result = new JSObject();
result.put("message", exception.getLocalizedMessage());
notifyListeners(PHONE_VERIFICATION_FAILED_EVENT, result, true);
}

public void handlePhoneCodeSent(String verificationId) {
JSObject result = new JSObject();
result.put("verificationId", verificationId);
notifyListeners(PHONE_CODE_SENT_EVENT, result, true);
}

@Override
public void startActivityForResult(PluginCall call, Intent intent, String callbackName) {
super.startActivityForResult(call, intent, callbackName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ private PhoneAuthProvider.OnVerificationStateChangedCallbacks createCallbacks(fi
return new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
String smsCode = credential.getSmsCode();
pluginImplementation.handlePhoneVerificationCompleted(smsCode);
/**
* @deprecated This code was replaced by event listener.
*
* Caution: The call must be resolved earlier.
*/
if (isLink) {
pluginImplementation.handleSuccessfulLink(call, credential, null, null, null);
} else {
Expand All @@ -76,6 +83,12 @@ public void onVerificationCompleted(PhoneAuthCredential credential) {

@Override
public void onVerificationFailed(FirebaseException exception) {
pluginImplementation.handlePhoneVerificationFailed(exception);
/**
* @deprecated This code was replaced by event listener.
*
* Caution: The call must be resolved earlier.
*/
if (isLink) {
pluginImplementation.handleFailedLink(call, null, exception);
} else {
Expand All @@ -85,6 +98,12 @@ public void onVerificationFailed(FirebaseException exception) {

@Override
public void onCodeSent(@NonNull String verificationId, @NonNull PhoneAuthProvider.ForceResendingToken token) {
pluginImplementation.handlePhoneCodeSent(verificationId);
/**
* @deprecated This code was replaced by event listener.
*
* Caution: The call must be resolved earlier.
*/
JSObject result = FirebaseAuthenticationHelper.createSignInResult(null, null, null, null, null, null);
result.put("verificationId", verificationId);
call.resolve(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,14 @@ public typealias AuthStateChangedObserver = () -> Void
savedCall.reject(errorMessage, nil, error)
}

func handlePhoneVerificationFailed(_ error: Error) {
plugin.handlePhoneVerificationFailed(error)
}

func handlePhoneCodeSent(_ verificationId: String) {
plugin.handlePhoneCodeSent(verificationId)
}

func getPlugin() -> FirebaseAuthenticationPlugin {
return self.plugin
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class FirebaseAuthenticationPlugin: CAPPlugin {
"signInAnonymously cannot be used in combination with skipNativeAuth."
public let errorDeviceUnsupported = "Device is not supported. At least iOS 13 is required."
public let authStateChangeEvent = "authStateChange"
public let phoneVerificationFailedEvent = "phoneVerificationFailed"
public let phoneCodeSentEvent = "phoneCodeSent"
private var implementation: FirebaseAuthentication?

override public func load() {
Expand Down Expand Up @@ -429,6 +431,18 @@ public class FirebaseAuthenticationPlugin: CAPPlugin {
notifyListeners(authStateChangeEvent, data: result, retainUntilConsumed: true)
}

@objc func handlePhoneVerificationFailed(_ error: Error) {
var result = JSObject()
result["message"] = error.localizedDescription
notifyListeners(phoneVerificationFailedEvent, data: result, retainUntilConsumed: true)
}

@objc func handlePhoneCodeSent(_ verificationId: String) {
var result = JSObject()
result["verificationId"] = verificationId
notifyListeners(phoneCodeSentEvent, data: result, retainUntilConsumed: true)
}

private func firebaseAuthenticationConfig() -> FirebaseAuthenticationConfig {
var config = FirebaseAuthenticationConfig()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ class PhoneAuthProviderHandler: NSObject {
}
PhoneAuthProvider.provider()
.verifyPhoneNumber(phoneNumber, uiDelegate: nil) { verificationID, error in
/**
* @deprecated This code was replaced by event listener.
*
* Caution: The call must be resolved earlier.
*/
if let error = error {
self.pluginImplementation.handlePhoneVerificationFailed(error)
if isLink == true {
self.pluginImplementation.handleFailedLink(message: nil, error: error)
} else {
Expand All @@ -50,6 +56,7 @@ class PhoneAuthProviderHandler: NSObject {
return
}

self.pluginImplementation.handlePhoneCodeSent(verificationID ?? "")
var result = FirebaseAuthenticationHelper.createSignInResult(credential: nil, user: nil, idToken: nil, nonce: nil, accessToken: nil, additionalUserInfo: nil)
result["verificationId"] = verificationID
call.resolve(result)
Expand Down
Loading