Skip to content
Open
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
13 changes: 12 additions & 1 deletion .github/workflows/scripts/functions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import * as assert from 'assert';
import * as functions from 'firebase-functions';
import * as functionsv2 from 'firebase-functions/v2';
import { beforeUserCreated } from 'firebase-functions/v2/identity';

// Only reject the dedicated Auth e2e address so other tests are unaffected.
export const rejectBlockedAuthUser = beforeUserCreated((event) => {
if (event.data?.email === 'blocked-by-function@example.com') {
throw new functionsv2.https.HttpsError(
'permission-denied',
'Registration blocked by the e2e test function.',
);
}
});


// For example app.
Expand Down Expand Up @@ -221,4 +232,4 @@ export const testStreamResponse = functions.https.onCall(async (request, respons

// Fallback for non-streaming clients
return Promise.all(allFruits);
});
});
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@ Marwan Salim Ba Matraf <marwans12@hotmail.com>
kfurue <pulpits.37-shims@icloud.com>
Max Wojczuk <developer@mwojczuk.xyz>
Julian Pscheid <julian@pscheid.com>
Kanako Nakamura <kanako.n0419@gmail.com>
Artem Shevchenko <art.shevchen@gmail.com>
5 changes: 2 additions & 3 deletions docs/auth/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ Situation | Android | Apple | Web | Windows
----------|---------|-------|-----|--------
Wrong email or password, with email enumeration protection enabled | `invalid-credential` | `invalid-credential` | `invalid-credential` | `unknown-error`
Error without a more specific code | `unknown` | `unknown` or `internal-error` | `unknown` or `internal-error` | `unknown-error`
A blocking function rejected the operation | `blocking-function-error-response` | `blocking-cloud-function-returned-error` | `internal-error` | `unknown-error`
A blocking function rejected the operation | `blocking-cloud-function-returned-error` | `blocking-cloud-function-returned-error` | `internal-error` | `unknown-error`
Password does not meet the password policy | `unknown` | `password-does-not-meet-requirements` | `password-does-not-meet-requirements` | `unknown-error`
SMS quota exceeded | `too-many-requests` | `quota-exceeded` | `quota-exceeded` | Not supported
No user signed in | `no-current-user` | `no-current-user` | `no-current-user` | `no-signed-in-user`
Expand Down Expand Up @@ -286,8 +286,7 @@ Code | Description | Platforms

Code | Description | Platforms
-----|-------------|----------
`blocking-function-error-response` | A blocking function (such as `beforeUserCreated` or `beforeUserSignedIn`) rejected the operation. `message` contains the error returned by the function. | Android
`blocking-cloud-function-returned-error` | A blocking function rejected the operation. `message` contains the error returned by the function. | Apple
`blocking-cloud-function-returned-error` | A blocking function (such as `beforeUserCreated` or `beforeUserSignedIn`) rejected the operation. `message` contains the error returned by the function. | Android, Apple

### Email actions and links

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,39 @@ void main() {
}
});

test(
'normalizes the error when a blocking function rejects registration',
() async {
// Matches rejectBlockedAuthUser in the Functions emulator fixtures.
await expectLater(
FirebaseAuth.instance.createUserWithEmailAndPassword(
email: 'blocked-by-function@example.com',
password: testPassword,
),
throwsA(
isA<FirebaseAuthException>()
.having(
(e) => e.code,
'code',
'blocking-cloud-function-returned-error',
)
.having(
(e) => e.message,
'message',
contains(
'Registration blocked by the e2e test function.',
),
),
),
);
expect(FirebaseAuth.instance.currentUser, isNull);
},
// This regression covers the shared Android and Apple error code.
skip:
kIsWeb ||
(!Platform.isAndroid && !Platform.isIOS && !Platform.isMacOS),
);

test('fails if creating a user with an invalid email', () async {
await ensureSignedIn(testEmail);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,18 @@ FirebaseException platformExceptionToFirebaseAuthException(
// Check for custom error codes that are not returned in the normal errors by Firebase SDKs
// The error code is only returned in a String on Android
String? _getCustomCode(Map? additionalData, String? message) {
final listOfRecognizedCode = [
const recognizedCodes = {
// This code happens when using Enumerate Email protection
'INVALID_LOGIN_CREDENTIALS',
// This code happens when using using pre-auth functions
'BLOCKING_FUNCTION_ERROR_RESPONSE',
];

for (final recognizedCode in listOfRecognizedCode) {
if (additionalData?['message'] == recognizedCode ||
(message?.contains(recognizedCode) ?? false)) {
return recognizedCode.toLowerCase().replaceAll('_', '-');
'INVALID_LOGIN_CREDENTIALS': 'invalid-login-credentials',
// Use the same error code as on Apple platforms for blocking function errors.
'BLOCKING_FUNCTION_ERROR_RESPONSE':
'blocking-cloud-function-returned-error',
};

for (final entry in recognizedCodes.entries) {
if (additionalData?['message'] == entry.key ||
(message?.contains(entry.key) ?? false)) {
return entry.value;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void main() {
);

test(
'should catch a [PlatformException] and throw a [FirebaseException] with the correct message',
'normalizes blocking function errors and preserves the JSON message',
() async {
PlatformException platformException = PlatformException(
code: 'UNKNOWN',
Expand All @@ -55,7 +55,7 @@ void main() {
.having(
(e) => e.code,
'code',
'blocking-function-error-response',
'blocking-cloud-function-returned-error',
)
.having(
(e) => e.message,
Expand Down Expand Up @@ -90,6 +90,34 @@ void main() {
});

group('platformExceptionToFirebaseAuthException()', () {
test('normalizes a blocking function error from pigeon details', () {
PlatformException platformException = PlatformException(
code: 'UNKNOWN',
details: {'message': 'BLOCKING_FUNCTION_ERROR_RESPONSE'},
);

FirebaseAuthException result =
platformExceptionToFirebaseAuthException(platformException)
as FirebaseAuthException;

expect(result.code, equals('blocking-cloud-function-returned-error'));
expect(result.message, isNull);
});

test('preserves the invalid login credentials error code', () {
PlatformException platformException = PlatformException(
code: 'UNKNOWN',
message:
'An internal error has occurred. [ INVALID_LOGIN_CREDENTIALS ]',
);

FirebaseAuthException result =
platformExceptionToFirebaseAuthException(platformException)
as FirebaseAuthException;

expect(result.code, equals('invalid-login-credentials'));
});

test('handles non-Map pigeon details', () {
PlatformException platformException = PlatformException(
code: 'ERROR_INTERNAL_ERROR',
Expand Down
Loading