Skip to content

Instantly share code, notes, and snippets.

@micimize
Created April 6, 2020 15:47
Show Gist options
  • Save micimize/062c0288a492c14d60936adc4a07b7a7 to your computer and use it in GitHub Desktop.
Save micimize/062c0288a492c14d60936adc4a07b7a7 to your computer and use it in GitHub Desktop.
Some `graphql_flutter` auth code for use with `google_sign_in`
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