Created
April 6, 2020 15:47
-
-
Save micimize/062c0288a492c14d60936adc4a07b7a7 to your computer and use it in GitHub Desktop.
Some `graphql_flutter` auth code for use with `google_sign_in`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter/services.dart' show Clipboard, ClipboardData; | |
import 'package:google_sign_in/google_sign_in.dart'; | |
import 'package:graphql_flutter/graphql_flutter.dart' show AuthLink; | |
/// Our `google_sign_in` client | |
GoogleSignIn _googleSignIn = GoogleSignIn( | |
scopes: <String>['email', 'profile'], | |
); | |
/// Our global app user singleton | |
GoogleSignInAccount _currentUser; | |
/// callback the client uses to give us notifications | |
final _onUserChange = _googleSignIn.onCurrentUserChanged.listen; | |
bool get isAuthenticated => _currentUser != null; | |
/// token when we're logged in | |
Future<String> get _token async { | |
final auth = await _googleSignIn.currentUser?.authentication; | |
return auth?.idToken; | |
} | |
/// graphql_flutter link | |
final googleSignInLink = AuthLink(getToken: () async { | |
final token = await _token; | |
return 'Bearer $token'; | |
}); | |
/// Wrap a widget tree with a login screen | |
class AuthenticationProvider extends StatefulWidget { | |
AuthenticationProvider({@required this.child}); | |
final Widget child; | |
@override | |
_AuthenticationProviderState createState() => _AuthenticationProviderState(); | |
/// wrap all given routes with authentication | |
static Map<String, WidgetBuilder> forRoutes( | |
Map<String, WidgetBuilder> routes) { | |
return routes.map((key, builder) { | |
return MapEntry( | |
key, | |
(BuildContext context) => AuthenticationProvider( | |
child: builder(context), | |
), | |
); | |
}); | |
} | |
} | |
class _AuthenticationProviderState extends State<AuthenticationProvider> { | |
@override | |
void initState() { | |
super.initState(); | |
_onUserChange((GoogleSignInAccount account) { | |
setState(() { | |
_currentUser = account; | |
}); | |
}); | |
_googleSignIn.signInSilently(suppressErrors: true); | |
} | |
void _handleSignIn() async { | |
try { | |
await _googleSignIn.signIn(); | |
} catch (error) { | |
print(error); | |
} | |
} | |
Widget get signInPage => Scaffold( | |
appBar: AppBar( | |
title: const Text('Google Sign In'), | |
), | |
body: ConstrainedBox( | |
constraints: const BoxConstraints.expand(), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.spaceAround, | |
children: <Widget>[ | |
const Text("You are not currently signed in."), | |
RaisedButton( | |
onPressed: _handleSignIn, | |
child: const Text('SIGN IN'), | |
), | |
], | |
), | |
)); | |
@override | |
Widget build(BuildContext context) { | |
return isAuthenticated ? widget.child : signInPage; | |
} | |
} | |
/// Simple sign out button | |
class SignOut extends StatelessWidget { | |
SignOut(); | |
void _handleSignOut() async { | |
try { | |
await _googleSignIn.signOut(); | |
} catch (error) { | |
print(error); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return RaisedButton( | |
onPressed: _handleSignOut, | |
child: const Text('SIGN OUT'), | |
); | |
} | |
} | |
/// Utility for debugging authenticated operations by copying the token to the clipboard | |
class CopyHeader extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return RaisedButton( | |
onPressed: () async { | |
final auth = await _googleSignIn.currentUser.authentication; | |
return Clipboard.setData(ClipboardData( | |
text: auth.idToken, | |
)); | |
}, | |
child: const Text('COPY TOKEN'), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment