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(auth): expose the missing MultiFactor classes through the universal package #9194

Merged
merged 2 commits into from Jul 26, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -14,8 +14,8 @@ import 'package:flutter/foundation.dart';
export 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'
show
FirebaseAuthException,
FirebaseAuthMultiFactorException,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is now exposed directly from the universal package

MultiFactorInfo,
MultiFactorSession,
PhoneMultiFactorInfo,
IdTokenResult,
UserMetadata,
Expand Down
81 changes: 62 additions & 19 deletions packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart
Expand Up @@ -492,10 +492,16 @@ class FirebaseAuth extends FirebasePluginPlatform {
/// - Thrown if the credential is a [PhoneAuthProvider.credential] and the
/// verification ID of the credential is not valid.id.
Future<UserCredential> signInWithCredential(AuthCredential credential) async {
return UserCredential._(
this,
await _delegate.signInWithCredential(credential),
);
try {
return UserCredential._(
this,
await _delegate.signInWithCredential(credential),
);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(this, e);
} catch (e) {
rethrow;
}
}

/// Tries to sign in a user with a given custom token.
Expand All @@ -519,7 +525,14 @@ class FirebaseAuth extends FirebasePluginPlatform {
/// - **invalid-custom-token**:
/// - Thrown if the custom token format is incorrect.
Future<UserCredential> signInWithCustomToken(String token) async {
return UserCredential._(this, await _delegate.signInWithCustomToken(token));
try {
return UserCredential._(
this, await _delegate.signInWithCustomToken(token));
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(this, e);
} catch (e) {
rethrow;
}
}

/// Attempts to sign in a user with the given email address and password.
Expand All @@ -545,10 +558,16 @@ class FirebaseAuth extends FirebasePluginPlatform {
required String email,
required String password,
}) async {
return UserCredential._(
this,
await _delegate.signInWithEmailAndPassword(email, password),
);
try {
return UserCredential._(
this,
await _delegate.signInWithEmailAndPassword(email, password),
);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(this, e);
} catch (e) {
rethrow;
}
}

/// Signs in using an email address and email sign-in link.
Expand All @@ -570,10 +589,16 @@ class FirebaseAuth extends FirebasePluginPlatform {
required String email,
required String emailLink,
}) async {
return UserCredential._(
this,
await _delegate.signInWithEmailLink(email, emailLink),
);
try {
return UserCredential._(
this,
await _delegate.signInWithEmailLink(email, emailLink),
);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(this, e);
} catch (e) {
rethrow;
}
}

/// Signs in with an AuthProvider using native authentication flow.
Expand All @@ -584,10 +609,16 @@ class FirebaseAuth extends FirebasePluginPlatform {
Future<UserCredential> signInWithAuthProvider(
AuthProvider provider,
) async {
return UserCredential._(
this,
await _delegate.signInWithAuthProvider(provider),
);
try {
return UserCredential._(
this,
await _delegate.signInWithAuthProvider(provider),
);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(this, e);
} catch (e) {
rethrow;
}
}

/// Starts a sign-in flow for a phone number.
Expand Down Expand Up @@ -624,15 +655,27 @@ class FirebaseAuth extends FirebasePluginPlatform {
///
/// This method is only available on web based platforms.
Future<UserCredential> signInWithPopup(AuthProvider provider) async {
return UserCredential._(this, await _delegate.signInWithPopup(provider));
try {
return UserCredential._(this, await _delegate.signInWithPopup(provider));
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(this, e);
} catch (e) {
rethrow;
}
}

/// Authenticates a Firebase client using a full-page redirect flow.
///
/// To handle the results and errors for this operation, refer to
/// [getRedirectResult].
Future<void> signInWithRedirect(AuthProvider provider) {
return _delegate.signInWithRedirect(provider);
try {
return _delegate.signInWithRedirect(provider);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(this, e);
} catch (e) {
rethrow;
}
}

/// Signs out the current user.
Expand Down
67 changes: 63 additions & 4 deletions packages/firebase_auth/firebase_auth/lib/src/multi_factor.dart
Expand Up @@ -17,10 +17,10 @@ class MultiFactor {
///
/// [displayName] can be used to provide a display name for the second factor.
Future<void> enroll(
MultiFactorAssertionPlatform assertion, {
MultiFactorAssertion assertion, {
String? displayName,
}) async {
return _delegate.enroll(assertion, displayName: displayName);
return _delegate.enroll(assertion._delegate, displayName: displayName);
}

/// Unenrolls a second factor from this user.
Expand All @@ -45,9 +45,68 @@ class MultiFactor {
class PhoneMultiFactorGenerator {
/// Transforms a PhoneAuthCredential into a [MultiFactorAssertion]
/// which can be used to confirm ownership of a phone second factor.
static MultiFactorAssertionPlatform getAssertion(
static MultiFactorAssertion getAssertion(
PhoneAuthCredential credential,
) {
return PhoneMultiFactorGeneratorPlatform.instance.getAssertion(credential);
final assertion =
PhoneMultiFactorGeneratorPlatform.instance.getAssertion(credential);
return MultiFactorAssertion._(assertion);
}
}

/// Represents an assertion that the Firebase Authentication server
/// can use to authenticate a user as part of a multi-factor flow.
class MultiFactorAssertion {
final MultiFactorAssertionPlatform _delegate;

MultiFactorAssertion._(this._delegate) {
MultiFactorAssertionPlatform.verifyExtends(_delegate);
}
}

/// Utility class that contains methods to resolve second factor
/// requirements on users that have opted into two-factor authentication.
class MultiFactorResolver {
final FirebaseAuth _auth;
final MultiFactorResolverPlatform _delegate;

MultiFactorResolver._(this._auth, this._delegate) {
MultiFactorResolverPlatform.verifyExtends(_delegate);
}

/// List of [MultiFactorInfo] which represents the available
/// second factors that can be used to complete the sign-in for the current session.
List<MultiFactorInfo> get hints => _delegate.hints;

/// A MultiFactorSession, an opaque session identifier for the current sign-in flow.
MultiFactorSession get session => _delegate.session;

/// Completes sign in with a second factor using an MultiFactorAssertion which
/// confirms that the user has successfully completed the second factor challenge.
Future<UserCredential> resolveSignIn(
MultiFactorAssertion assertion,
) async {
final credential = await _delegate.resolveSignIn(assertion._delegate);
return UserCredential._(_auth, credential);
}
}

/// MultiFactor exception related to Firebase Authentication. Check the error code
/// and message for more details.
class FirebaseAuthMultiFactorException extends FirebaseAuthException {
final FirebaseAuth _auth;
final FirebaseAuthMultiFactorExceptionPlatform _delegate;

FirebaseAuthMultiFactorException._(this._auth, this._delegate)
: super(
code: _delegate.code,
message: _delegate.message,
email: _delegate.email,
credential: _delegate.credential,
phoneNumber: _delegate.phoneNumber,
tenantId: _delegate.tenantId,
);

MultiFactorResolver get resolver =>
MultiFactorResolver._(_auth, _delegate.resolver);
}
Expand Up @@ -8,11 +8,11 @@ import 'package:meta/meta.dart';

/// MultiFactor exception related to Firebase Authentication. Check the error code
/// and message for more details.
class FirebaseAuthMultiFactorException extends FirebaseAuthException
class FirebaseAuthMultiFactorExceptionPlatform extends FirebaseAuthException
implements Exception {
// ignore: public_member_api_docs
@protected
FirebaseAuthMultiFactorException({
FirebaseAuthMultiFactorExceptionPlatform({
String? message,
required String code,
String? email,
Expand Down
Expand Up @@ -74,7 +74,7 @@ FirebaseException platformExceptionToFirebaseAuthException(
);
}

FirebaseAuthMultiFactorException parseMultiFactorError(
FirebaseAuthMultiFactorExceptionPlatform parseMultiFactorError(
Map<String, Object?> details) {
final code = details['code'] as String?;
final message = details['message'] as String?;
Expand Down Expand Up @@ -124,7 +124,7 @@ FirebaseAuthMultiFactorException parseMultiFactorError(
auth,
);

return FirebaseAuthMultiFactorException(
return FirebaseAuthMultiFactorExceptionPlatform(
code: code ?? 'Unknown',
message: message,
resolver: multiFactorResolver,
Expand Down
Expand Up @@ -56,20 +56,39 @@ class MultiFactorSession {
final String id;
}

/// {@template .multiFactorAssertion}
/// Represents an assertion that the Firebase Authentication server
/// can use to authenticate a user as part of a multi-factor flow.
class MultiFactorAssertionPlatform {}
/// {@endtemplate}
class MultiFactorAssertionPlatform extends PlatformInterface {
/// {@macro .multiFactorAssertion}
MultiFactorAssertionPlatform() : super(token: _token);

static final Object _token = Object();

/// Ensures that any delegate class has extended a [MultiFactorResolverPlatform].
static void verifyExtends(MultiFactorAssertionPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
}
}

/// {@macro .platformInterfaceMultiFactorResolverPlatform}
/// {@template .platformInterfaceMultiFactorResolverPlatform}
/// Utility class that contains methods to resolve second factor
/// requirements on users that have opted into two-factor authentication.
/// {@endtemplate}
class MultiFactorResolverPlatform {
class MultiFactorResolverPlatform extends PlatformInterface {
/// {@macro .platformInterfaceMultiFactorResolverPlatform}
const MultiFactorResolverPlatform(
MultiFactorResolverPlatform(
this.hints,
this.session,
);
) : super(token: _token);

static final Object _token = Object();

/// Ensures that any delegate class has extended a [MultiFactorResolverPlatform].
static void verifyExtends(MultiFactorResolverPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
}

/// List of [MultiFactorInfo] which represents the available
/// second factors that can be used to complete the sign-in for the current session.
Expand Down
Expand Up @@ -50,7 +50,7 @@ FirebaseAuthException getFirebaseAuthException(
firebaseError as auth_interop.MultiFactorError,
);

return FirebaseAuthMultiFactorException(
return FirebaseAuthMultiFactorExceptionPlatform(
code: code,
message: message,
email: firebaseError.email,
Expand Down