Google Provider
GoogleProvider is a prebuilt OAuth2Provider subclass targeting Google's OAuth 2.0 endpoints. It uses PKCE and requests access_type: offline so a refresh token is always returned, enabling silent session renewal.
Package: authyra_flutter
Constructor
GoogleProvider({
required String clientId,
String? clientSecret,
String? redirectUri,
List<String> scopes = const ['openid', 'email', 'profile'],
})
| Parameter | Default | Description |
|---|---|---|
clientId | required | OAuth 2.0 client ID from Google Cloud Console |
clientSecret | null | Only for confidential clients (backend/desktop with stored secret). Omit for mobile PKCE flows. |
redirectUri | com.googleusercontent.apps.<clientId>:/oauth2redirect | Override if your app uses a different URI scheme |
scopes | ['openid', 'email', 'profile'] | Additional scopes extend these defaults |
The provider ID is 'google'.
Setup
1. Create a Google OAuth 2.0 client
Go to Google Cloud Console → APIs & Services → Credentials and create an OAuth 2.0 Client ID:
- For Android: choose Android, enter your package name and SHA-1 signing certificate fingerprint.
- For iOS / macOS: choose iOS, enter your bundle ID.
- For Web / desktop: choose Web application.
2. Add the provider
import 'package:app_links/app_links.dart';
import 'package:authyra_flutter/authyra_flutter.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final googleProvider = GoogleProvider(
clientId: 'YOUR_GOOGLE_CLIENT_ID',
// redirectUri defaults to com.googleusercontent.apps.YOUR_CLIENT_ID:/oauth2redirect
);
// Register before Authyra.initialize
OAuth2CallbackHandler.registerProvider(
'com.googleusercontent.apps.YOUR_CLIENT_ID',
googleProvider,
);
AppLinks().uriLinkStream.listen(OAuth2CallbackHandler.handleCallback);
await Authyra.initialize(
client: AuthyraClient(
providers: [googleProvider],
storage: SecureAuthStorage(),
config: const AuthConfig(autoRefresh: true),
),
);
runApp(const MyApp());
}
3. Platform deep-link config
Android — android/app/src/main/AndroidManifest.xml:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="com.googleusercontent.apps.YOUR_CLIENT_ID" />
</intent-filter>
iOS — ios/Runner/Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.YOUR_CLIENT_ID</string>
</array>
</dict>
</array>
Sign in
try {
final user = await Authyra.instance.signIn('google');
print('Hello, ${user.name}!');
} on AuthenticationCancelledException {
// User closed the browser — no error to show
} on AuthenticationFailedException catch (e) {
print('Google sign-in failed: $e');
}
User fields
AuthUser field | Google claim | Notes |
|---|---|---|
id | sub | Stable Google User ID |
email | email | |
name | name | Full display name |
avatarUrl | picture | Profile photo URL |
metadata['email_verified'] | email_verified | |
metadata['given_name'] | given_name | |
metadata['family_name'] | family_name | |
metadata['locale'] | locale | |
metadata['hd'] | hd | Hosted domain — Google Workspace accounts only |
Scopes
The default scopes (openid, email, profile) cover the common case. Add scopes at construction for additional access:
GoogleProvider(
clientId: 'YOUR_CLIENT_ID',
scopes: [
'openid',
'email',
'profile',
'https://www.googleapis.com/auth/calendar.readonly',
],
)
Token refresh
GoogleProvider sets supportsRefresh: true. The provider requests access_type: offline and prompt: consent on every sign-in, ensuring Google returns a refresh token. When the access token expires, AuthyraClient refreshes it automatically if AuthConfig.autoRefresh is true.
To force a token refresh manually:
await Authyra.instance.refreshSession();
Token revocation (sign-out)
GoogleProvider overrides signOut to call Google's revocation endpoint (https://oauth2.googleapis.com/revoke) with the current access token, revoking the Google session server-side before clearing the local session.
await Authyra.instance.signOut();
Troubleshooting
Callback never arrives
- Confirm the scheme in
AndroidManifest.xml/Info.plistexactly matchescom.googleusercontent.apps.<clientId>. - Confirm
OAuth2CallbackHandler.registerProvideris called with the same scheme string. - On Android, verify
app_linksdependency and that your activity haslaunchMode="singleTask".
"redirect_uri_mismatch" error from Google
The redirect URI sent to Google does not match what is registered in Cloud Console. The default is com.googleusercontent.apps.<clientId>:/oauth2redirect — if you override redirectUri, register the same URI in the Cloud Console.
No refresh token returned
Google only returns a refresh token when access_type=offline and prompt=consent. Both are set by default. If the user has previously authorized your app and prompt=consent is removed, no refresh token is returned for subsequent logins.
See also
- Flutter Setup → — deep-link wiring in detail
- OAuth2Provider → — base class, custom providers
- Full Flutter App Example →