Skip to content

Commit 22af3d1

Browse files
feat:0.1.2 add apple and credential sign in
1 parent 52c91fa commit 22af3d1

17 files changed

+278
-18
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 0.1.2
2+
3+
- feat: add sign in with apple support
4+
- feat: add sign in with credential support for other identity providers
5+
- docs: documentation updates
6+
17
# 0.1.1
28

39
- feat: add `isSubmitting()` extension to `BuildContext`. To determine if an authentication request is currently active

README.md

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ Pre-lit Firebase authentication. It provides a set of convenient utilities and w
1111

1212
- **Multiple platform support**
1313
- Works on mobile and web. No changes needed
14-
- Windows, macOS and Linux to be added soon
14+
- Windows, macOS and Linux to be added in the future
1515
- **Multiple authentication providers**
16-
- Enable third party providers (Google)
17-
- More to be added soon
16+
- Package supported: Google and Apple
17+
- Please see Authentication Providers[Authentication Providers](#authentication-providers) for other sign-in providers
1818
- **Services and state managed for you**
1919
- Easily interact with Firebase from anywhere in your app
2020
- Monitor the auth state and react to changes
@@ -123,6 +123,15 @@ class MyApp extends StatelessWidget {
123123
emailAndPassword: true, // enabled by default
124124
google: true,
125125
anonymous: true,
126+
apple: AppleAuthProvider(
127+
// required for web-based authentication flows (Android)
128+
webAuthenticationOptions: WebAuthenticationOptions(
129+
clientId: 'com.aboutyou.dart_packages.sign_in_with_apple.example', // example clientId
130+
redirectUri: Uri.parse(
131+
'https://flutter-sign-in-with-apple-example.glitch.me/callbacks/sign_in_with_apple', // example redirectUri
132+
),
133+
),
134+
),
126135
),
127136
child: MaterialApp(
128137
title: 'Material App',
@@ -230,6 +239,22 @@ context.getSignedInUser()
230239
}
231240
```
232241

242+
## Authentication Providers
243+
For the time being, Lit Firebase auth will only directly provide Google and Apple sign in.
244+
245+
**NOTE:** Apple requires Apple sign in to be a sign-in option if any other third-party sign-in option is used.
246+
247+
Other identity providers (Facebook, Github, etc.) will need to be implemented seperately. After successful third party sign in, you can sign in to Firebase by making use of the `signInWithCredential` method available on `BuildContext`.
248+
249+
For example:
250+
251+
```dart
252+
Widget build(BuildContext context) {
253+
AuthCredential credential = // get credential for identity provider (Facebook, Github, etc.)
254+
context.signInWithCredential(credential);
255+
}
256+
```
257+
233258
## Decoration and theming
234259
The UI can be as customizable as you need. But for simple usage it's fairly straight forward.
235260

example/lib/main.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ class MyApp extends StatelessWidget {
1212
emailAndPassword: true, // enabled by default
1313
google: true,
1414
anonymous: true,
15+
// apple: AppleAuthProvider(
16+
// // required for web-based authentication flows
17+
// webAuthenticationOptions: WebAuthenticationOptions(
18+
// clientId: 'com.aboutyou.dart_packages.sign_in_with_apple.example',
19+
// redirectUri: Uri.parse(
20+
// 'https://flutter-sign-in-with-apple-example.glitch.me/callbacks/sign_in_with_apple',
21+
// ),
22+
// ),
23+
// ),
1524
),
1625
child: MaterialApp(
1726
title: 'Material App',
@@ -33,9 +42,6 @@ class SplashScreen extends StatelessWidget {
3342

3443
@override
3544
Widget build(BuildContext context) {
36-
// LitAuth.custom(
37-
// child: CustomSignInWidget(),
38-
// );
3945
return Scaffold(
4046
body: Center(
4147
child: SingleChildScrollView(
@@ -130,6 +136,11 @@ class CustomSignInWidget extends StatelessWidget {
130136
},
131137
child: Text('Anony Sign In'),
132138
),
139+
SignInWithAppleButton(
140+
onPressed: () {
141+
context.signInWithApple();
142+
},
143+
),
133144
],
134145
),
135146
),

example/pubspec.lock

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ packages:
211211
path: ".."
212212
relative: true
213213
source: path
214-
version: "0.1.1"
214+
version: "0.1.2"
215215
matcher:
216216
dependency: transitive
217217
description:
@@ -268,6 +268,13 @@ packages:
268268
url: "https://pub.dartlang.org"
269269
source: hosted
270270
version: "2.1.3"
271+
sign_in_with_apple:
272+
dependency: transitive
273+
description:
274+
name: sign_in_with_apple
275+
url: "https://pub.dartlang.org"
276+
source: hosted
277+
version: "2.5.2"
271278
sky_engine:
272279
dependency: transitive
273280
description: flutter

lib/lit_firebase_auth.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
export 'package:sign_in_with_apple/sign_in_with_apple.dart';
2+
13
export 'src/domain/auth/auth_providers.dart';
24
export 'src/domain/auth/i_auth_facade.dart';
35
export 'src/infrastructure/firebase_auth_facade.dart';

lib/src/application/auth/sign_in_handler/sign_in_handler_state_notifier.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,27 @@ class SignInHandlerStateNotifier extends StateNotifier<SignInHandlerState>
6767
}
6868
}
6969

70+
Future<void> signInWithApple() async {
71+
if (_authProviders.apple == null) {
72+
throw AuthProviderNotEnabled('Apple');
73+
}
74+
state = state.copyWith(
75+
isSubmitting: true,
76+
authFailureOrSuccessOption: none(),
77+
);
78+
79+
final auth = await _authFacade.signInWithApple(
80+
webAuthenticationOptions: _authProviders.apple.webAuthenticationOptions,
81+
);
82+
83+
if (mounted) {
84+
state = state.copyWith(
85+
isSubmitting: false,
86+
authFailureOrSuccessOption: some(auth),
87+
);
88+
}
89+
}
90+
7091
Future<void> signInWithCredential(AuthCredential credential) async {
7192
state = state.copyWith(
7293
isSubmitting: true,

lib/src/domain/auth/auth_providers.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:freezed_annotation/freezed_annotation.dart';
2+
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
23

34
part 'auth_providers.freezed.dart';
45

@@ -8,12 +9,26 @@ part 'auth_providers.freezed.dart';
89
///
910
/// [emailAndPassword] defaults to enabled. The rest are disabled by default.
1011
///
11-
/// You will receive an [AuthProviderNotEnabled] exception a you try to use
12+
/// You will receive an [AuthProviderNotEnabled] exception if you try to use
1213
/// an authentication provider that is not enabled here.
1314
abstract class AuthProviders with _$AuthProviders {
1415
const factory AuthProviders({
1516
@Default(true) bool emailAndPassword,
1617
@Default(false) bool anonymous,
1718
@Default(false) bool google,
19+
AppleAuthProvider apple,
1820
}) = _AuthProviders;
1921
}
22+
23+
abstract class AuthProvider {}
24+
25+
class AppleAuthProvider extends AuthProvider {
26+
/// Parameters required for web-based authentication flows
27+
///
28+
/// As described in https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/incorporating_sign_in_with_apple_into_other_platforms
29+
final WebAuthenticationOptions webAuthenticationOptions;
30+
31+
AppleAuthProvider({
32+
this.webAuthenticationOptions,
33+
});
34+
}

lib/src/domain/auth/auth_providers.freezed.dart

Lines changed: 34 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/domain/auth/i_auth_facade.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:firebase_auth/firebase_auth.dart';
22
import 'package:flutter/foundation.dart';
3+
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
34

45
import 'auth.dart';
56
import 'user.dart';
@@ -19,6 +20,9 @@ abstract class AuthFacade {
1920
@required Password password,
2021
});
2122
Future<Auth> signInWithGoogle();
23+
Future<Auth> signInWithApple({
24+
@required WebAuthenticationOptions webAuthenticationOptions,
25+
});
2226
Future<Auth> signInWithCredential(AuthCredential credential);
2327
Future<Auth> signInAnonymously();
2428
Future<void> signOut();

lib/src/infrastructure/firebase_auth_facade.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
44
import 'package:flutter/widgets.dart';
55
import 'package:google_sign_in/google_sign_in.dart';
66
import 'package:meta/meta.dart';
7+
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
78

89
import '../domain/auth/auth.dart';
910
import '../domain/auth/auth_failure.dart';
@@ -240,6 +241,35 @@ class FirebaseAuthFacade implements AuthFacade {
240241
}
241242
}
242243

244+
@override
245+
Future<Auth> signInWithApple({
246+
WebAuthenticationOptions webAuthenticationOptions,
247+
}) async {
248+
try {
249+
final appleUser = await SignInWithApple.getAppleIDCredential(
250+
scopes: [
251+
AppleIDAuthorizationScopes.email,
252+
AppleIDAuthorizationScopes.fullName,
253+
],
254+
webAuthenticationOptions: webAuthenticationOptions,
255+
);
256+
const oAuthProvider = OAuthProvider(providerId: 'apple.com');
257+
final authCredential = oAuthProvider.getCredential(
258+
idToken: appleUser.identityToken,
259+
accessToken: appleUser.authorizationCode,
260+
);
261+
await _firebaseAuth.signInWithCredential(authCredential);
262+
return const Auth.success();
263+
} on SignInWithAppleAuthorizationException catch (e) {
264+
if (e.code == AuthorizationErrorCode.canceled) {
265+
return const Auth.failure(AuthFailure.cancelledByUser());
266+
}
267+
return const Auth.failure(AuthFailure.serverError());
268+
} catch (e) {
269+
return const Auth.failure(AuthFailure.serverError());
270+
}
271+
}
272+
243273
@override
244274
Future<Auth> signInAnonymously() async {
245275
try {

0 commit comments

Comments
 (0)