extension_google_sign_in_as_googleapis_auth 3.0.0
extension_google_sign_in_as_googleapis_auth: ^3.0.0 copied to clipboard
A bridge package between google_sign_in and googleapis_auth, to create Authenticated Clients from google_sign_in user credentials.
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
// #docregion Import
import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';
// #enddocregion Import
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/people/v1.dart';
// #docregion CreateAPIClient
import 'package:googleapis_auth/googleapis_auth.dart' as auth show AuthClient;
// #enddocregion CreateAPIClient
/// The scopes used by this example.
const List<String> scopes = <String>[PeopleServiceApi.contactsReadonlyScope];
void main() {
runApp(
const MaterialApp(
title: 'Google Sign In + googleapis',
home: SignInDemo(),
),
);
}
/// The main widget of this demo.
class SignInDemo extends StatefulWidget {
/// Creates the main widget of this demo.
const SignInDemo({super.key});
@override
State createState() => SignInDemoState();
}
/// The state of the main widget.
class SignInDemoState extends State<SignInDemo> {
late Future<void> _signInInitialized;
GoogleSignInAccount? _currentUser;
GoogleSignInClientAuthorization? _authorization;
String _contactText = '';
@override
void initState() {
super.initState();
final GoogleSignIn signIn = GoogleSignIn.instance;
_signInInitialized = signIn.initialize(
// Add your client IDs here as necessary for your supported platforms.
);
signIn.authenticationEvents.listen((GoogleSignInAuthenticationEvent event) {
if (!mounted) {
return;
}
setState(() {
switch (event) {
case GoogleSignInAuthenticationEventSignIn():
_currentUser = event.user;
case GoogleSignInAuthenticationEventSignOut():
_currentUser = null;
_authorization = null;
}
});
if (_currentUser != null) {
_checkAuthorization();
}
}).onError((Object error) {
debugPrint(error.toString());
});
_signInInitialized.then((void value) {
signIn.attemptLightweightAuthentication();
});
}
void _updateAuthorization(GoogleSignInClientAuthorization? authorization) {
if (!mounted) {
return;
}
setState(() {
_authorization = authorization;
});
if (authorization != null) {
unawaited(_handleGetContact(authorization));
}
}
Future<void> _checkAuthorization() async {
_updateAuthorization(
await _currentUser?.authorizationClient.authorizationForScopes(scopes));
}
Future<void> _requestAuthorization() async {
_updateAuthorization(await _currentUser?.authorizationClient
.authorizeScopes(<String>[PeopleServiceApi.contactsReadonlyScope]));
}
Future<void> _handleGetContact(
GoogleSignInClientAuthorization authorization) async {
if (!mounted) {
return;
}
setState(() {
_contactText = 'Loading contact info...';
});
// #docregion CreateAPIClient
// Retrieve an [auth.AuthClient] from a GoogleSignInClientAuthorization.
final auth.AuthClient client = authorization.authClient(scopes: scopes);
// Prepare a People Service authenticated client.
final PeopleServiceApi peopleApi = PeopleServiceApi(client);
// Retrieve a list of connected contacts' names.
final ListConnectionsResponse response =
await peopleApi.people.connections.list(
'people/me',
personFields: 'names',
);
// #enddocregion CreateAPIClient
final String? firstNamedContactName =
_pickFirstNamedContact(response.connections);
if (mounted) {
setState(() {
if (firstNamedContactName != null) {
_contactText = 'I see you know $firstNamedContactName!';
} else {
_contactText = 'No contacts to display.';
}
});
}
}
String? _pickFirstNamedContact(List<Person>? connections) {
return connections
?.firstWhere(
(Person person) => person.names != null,
)
.names
?.firstWhere(
(Name name) => name.displayName != null,
)
.displayName;
}
Future<void> _handleSignIn() async {
try {
await GoogleSignIn.instance.authenticate();
} catch (error) {
debugPrint(error.toString());
}
}
// Call disconnect rather than signOut to more fully reset the example app.
Future<void> _handleSignOut() => GoogleSignIn.instance.disconnect();
Widget _buildBody() {
return FutureBuilder<void>(
future: _signInInitialized,
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
final GoogleSignInAccount? user = _currentUser;
final GoogleSignInClientAuthorization? authorization = _authorization;
final List<Widget> children;
if (snapshot.hasError) {
children = <Widget>[
const Text('Error initializing sign in.'),
];
} else if (snapshot.connectionState == ConnectionState.done) {
children = <Widget>[
if (user != null) ...<Widget>[
ListTile(
leading: GoogleUserCircleAvatar(
identity: user,
),
title: Text(user.displayName ?? ''),
subtitle: Text(user.email),
),
const Text('Signed in successfully.'),
if (authorization != null) ...<Widget>[
Text(_contactText),
ElevatedButton(
onPressed: () => _handleGetContact(authorization),
child: const Text('REFRESH'),
),
] else ...<Widget>[
ElevatedButton(
onPressed: _requestAuthorization,
child: const Text('LOAD CONTACTS'),
),
],
ElevatedButton(
onPressed: _handleSignOut,
child: const Text('SIGN OUT'),
),
] else ...<Widget>[
const Text('You are not currently signed in.'),
ElevatedButton(
onPressed: _handleSignIn,
child: const Text('SIGN IN'),
),
],
];
} else {
children = <Widget>[
const CircularProgressIndicator(),
];
}
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: children,
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Sign In + googleapis'),
),
body: ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: _buildBody(),
));
}
}