mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
docs: update Flutter docs/ guides/ examples to reflect the new Skip nonce checks option for Google login (#18697)
* update example google sign in app * update flutter google sign in example * update flutter auth blog post to add skip nonce check content * update google sign in guide to include skip nonce check content * minor update on the code sample for google auth guide * delete unused code from code sample * minor update of the blog writing * blog article refactor * minor format fix * Update apps/docs/pages/guides/auth/social-login/auth-google.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/docs/pages/guides/auth/social-login/auth-google.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/docs/pages/guides/auth/social-login/auth-google.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/www/_blog/2023-07-18-flutter-authentication.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/www/_blog/2023-07-18-flutter-authentication.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/www/_blog/2023-07-18-flutter-authentication.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/www/_blog/2023-07-18-flutter-authentication.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * fix typo --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com>
This commit is contained in:
1 parent
677cec3a70
commit
1a0d92ba41
12 files changed
+250
-520
No files matched your search
@@ -234,130 +234,66 @@ Before you can use Sign in with Google, you need to obtain a [Google Cloud Platf
|
||||
|
||||
## Using Native Sign in with Google in Flutter
|
||||
|
||||
Native Google sign in with Supabase is done through [flutter_appauth](https://pub.dev/packages/flutter_appauth) package for iOS and [google_sign_in](https://pub.dev/packages/google_sign_in) package for Android.
|
||||
Native Google sign in with Supabase is done through the [google_sign_in](https://pub.dev/packages/google_sign_in) package for iOS and Android. Follow the instructions on the [google_sign_in](https://pub.dev/packages/google_sign_in) package for plugin specific settings.
|
||||
|
||||
When the user provides consent, Google issues an identity token (commonly abbreviated as ID token) that is then sent to your project's Supabase Auth server. When valid, a new user session is started by issuing an access and refresh token from Supabase Auth.
|
||||
|
||||
If you are building a Flutter app, you can use the [google_sign_in](https://pub.dev/packages/google_sign_in) package for Android and [flutter_appauth](https://pub.dev/packages/flutter_appauth) package for iOS to sign a user into your Supabase project:
|
||||
Follow the code sample below to implement native Google sign in with Supabase in your Flutter app.
|
||||
|
||||
```dart
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter_appauth/flutter_appauth.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:google_sign_in/google_sign_in.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
|
||||
/// Function to generate a random 16 character string.
|
||||
String _generateRandomString() {
|
||||
final random = Random.secure();
|
||||
return base64Url.encode(List<int>.generate(16, (_) => random.nextInt(256)));
|
||||
}
|
||||
...
|
||||
|
||||
Future<AuthResponse> signInWithGoogle() {
|
||||
/// TODO: update the iOS and Web client ID with your own.
|
||||
Future<AuthResponse> _googleSignIn() async {
|
||||
/// TODO: update the Web client ID with your own.
|
||||
///
|
||||
/// Client ID that you registered with Google Cloud.
|
||||
/// Note that in order to perform Google sign in on Android, you need to
|
||||
/// provide the web client ID, not the Android client ID.
|
||||
final clientId = Platform.isIOS ? 'IOS_CLIENT_ID' : 'WEB_CLIENT_ID';
|
||||
/// Web Client ID that you registered with Google Cloud.
|
||||
const webClientId = 'my-web.apps.googleusercontent.com';
|
||||
|
||||
late final String? idToken;
|
||||
late final String? accessToken;
|
||||
String? rawNonce;
|
||||
/// TODO: update the iOS client ID with your own.
|
||||
///
|
||||
/// iOS Client ID that you registered with Google Cloud.
|
||||
const iosClientId = 'my-ios.apps.googleusercontent.com';
|
||||
|
||||
// Use AppAuth to perform Google sign in on iOS
|
||||
// and use GoogleSignIn package for Google sign in on Android
|
||||
if (Platform.isIOS) {
|
||||
const appAuth = FlutterAppAuth();
|
||||
// Google sign in on Android will work without providing the Android
|
||||
// Client ID registered on Google Cloud.
|
||||
|
||||
// Just a random string
|
||||
rawNonce = _generateRandomString();
|
||||
final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString();
|
||||
final GoogleSignIn googleSignIn = GoogleSignIn(
|
||||
clientId: iosClientId,
|
||||
serverClientId: webClientId,
|
||||
);
|
||||
final googleUser = await googleSignIn.signIn();
|
||||
final googleAuth = await googleUser!.authentication;
|
||||
final accessToken = googleAuth.accessToken;
|
||||
final idToken = googleAuth.idToken;
|
||||
|
||||
/// Set as reversed DNS form of Google Client ID + `:/` for Google login
|
||||
final redirectUrl = '${clientId.split('.').reversed.join('.')}:/';
|
||||
|
||||
/// Fixed value for google login
|
||||
const discoveryUrl =
|
||||
'https://accounts.google.com/.well-known/openid-configuration';
|
||||
|
||||
// authorize the user by opening the concent page
|
||||
final result = await appAuth.authorize(
|
||||
AuthorizationRequest(
|
||||
clientId,
|
||||
redirectUrl,
|
||||
discoveryUrl: discoveryUrl,
|
||||
nonce: hashedNonce,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
'profile',
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (result == null) {
|
||||
throw 'No result';
|
||||
}
|
||||
|
||||
// Request the access and id token to google
|
||||
final tokenResult = await appAuth.token(
|
||||
TokenRequest(
|
||||
clientId,
|
||||
redirectUrl,
|
||||
authorizationCode: result.authorizationCode,
|
||||
discoveryUrl: discoveryUrl,
|
||||
codeVerifier: result.codeVerifier,
|
||||
nonce: result.nonce,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
accessToken = tokenResult?.accessToken;
|
||||
idToken = tokenResult?.idToken;
|
||||
} else {
|
||||
final GoogleSignIn googleSignIn = GoogleSignIn(
|
||||
serverClientId: clientId,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
],
|
||||
);
|
||||
final googleUser = await googleSignIn.signIn();
|
||||
final googleAuth = await googleUser!.authentication;
|
||||
accessToken = googleAuth.accessToken;
|
||||
idToken = googleAuth.idToken;
|
||||
}
|
||||
|
||||
if (idToken == null) {
|
||||
throw 'No ID Token';
|
||||
}
|
||||
if (accessToken == null) {
|
||||
throw 'No Access Token';
|
||||
throw 'No Access Token found.';
|
||||
}
|
||||
if (idToken == null) {
|
||||
throw 'No ID Token found.';
|
||||
}
|
||||
|
||||
return supabase.auth.signInWithIdToken(
|
||||
provider: Provider.google,
|
||||
idToken: idToken,
|
||||
accessToken: accessToken,
|
||||
nonce: rawNonce,
|
||||
);
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
### Configuration [#flutter-configuration-native-app]
|
||||
|
||||
1. Configure OAuth credentials for your Google Cloud project in the [Credentials](https://console.cloud.google.com/apis/credentials) page of the console. When creating a new OAuth client ID, choose _Android_ or _iOS_ depending on the mobile operating system your app is built for.
|
||||
1. Configure OAuth credentials for your Google Cloud project in the [Credentials](https://console.cloud.google.com/apis/credentials) page of the console. When creating a new OAuth client ID, choose _Android_ or _iOS_ depending on the mobile operating system your app is built for. Also create a web client ID.
|
||||
|
||||
- For Android, use the instructions on screen to provide the SHA-1 certificate fingerprint used to sign your Android app. You also need to create a web client ID to perform Google sign in on Android.
|
||||
- For iOS, use the instructions on screen to provide the app Bundle ID, and App Store ID and Team ID if the app is already published on the Apple AppStore.
|
||||
|
||||
2. Configure the [OAuth Consent Screen](https://console.cloud.google.com/apis/credentials/consent). This information is shown to the user when giving consent to your app. In particular, make sure you have set up links to your app's privacy policy and terms of service.
|
||||
3. Finally, add the client ID from step 1 in the [Google provider on the Supabase Dashboard](https://supabase.com/dashboard/project/_/auth/providers), under _Authorized Client IDs_.
|
||||
3. Finally, add the web client ID from step 1 in the [Google provider on the Supabase Dashboard](https://supabase.com/dashboard/project/_/auth/providers), under _Authorized Client IDs_. You do not need to add the Android or iOS client ID here. If you need iOS support, enable the `Skip nonce check` option.
|
||||
|
||||
Note that you do not have to configure the OAuth flow in the Supabase Dashboard in order to use native sign in.
|
||||
|
||||
@@ -411,8 +347,8 @@ Before you can use Sign in with Google, you need to obtain a [Google Cloud Platf
|
||||
|
||||
1. Configure OAuth credentials for your Google Cloud project in the [Credentials](https://console.cloud.google.com/apis/credentials) page of the console. When creating a new OAuth client ID, choose _Android_ or _iOS_ depending on the mobile operating system your app is built for.
|
||||
|
||||
- For Android, use the instructions on screen to provide the SHA-1 certificate fingerprint used to sign your Android app.
|
||||
- For iOS, use the instructions on screen to provide the app Bundle ID, and App Store ID and Team ID if the app is already published on the Apple AppStore.
|
||||
- For Android, use the instructions on screen to provide the SHA-1 certificate fingerprint used to sign your Android app.
|
||||
- For iOS, use the instructions on screen to provide the app Bundle ID, and App Store ID and Team ID if the app is already published on the Apple AppStore.
|
||||
|
||||
2. Configure the [OAuth Consent Screen](https://console.cloud.google.com/apis/credentials/consent). This information is shown to the user when giving consent to your app. In particular, make sure you have set up links to your app's privacy policy and terms of service.
|
||||
3. Finally, add the client ID from step 1 in the [Google provider on the Supabase Dashboard](https://supabase.com/dashboard/project/_/auth/providers), under _Authorized Client IDs_.
|
||||
|
||||
@@ -52,45 +52,49 @@ flutter create myauthapp
|
||||
then we can install the dependencies. Change the working directory to the newly created app directory and run the following command to install our dependencies.
|
||||
|
||||
```dart
|
||||
flutter pub add supabase_flutter flutter_appauth crypto google_sign_in
|
||||
flutter pub add supabase_flutter google_sign_in
|
||||
```
|
||||
|
||||
We will use [supabase_flutter](https://pub.dev/packages/supabase_flutter) to interact with our Supabase instance. [google_sign_in](https://pub.dev/packages/google_sign_in) will be used to authenticate on Android, and [flutter_appauth](https://pub.dev/packages/flutter_appauth) will be used for iOS. [crypto](https://pub.dev/packages/crypto) is a library that has utility functions for encryption that we will use when performing OIDC logins.
|
||||
The [supabase_flutter](https://pub.dev/packages/supabase_flutter) package is used to interact with a Supabase instance. The [google_sign_in](https://pub.dev/packages/google_sign_in) package is used to implement social sign-in with Google.
|
||||
|
||||
We are done installing our dependencies. Let’s set up [authentication](https://supabase.com/docs/guides/auth) now.
|
||||
|
||||
## Configure Google sign-in on Supabase Auth
|
||||
|
||||
We will obtain client IDs for iOS, Android, and web from the Google Cloud console, and register them to our Supabase project.
|
||||
We need the web client ID in order to use the Google sign-in flow on Android.
|
||||
The web client ID will be used by the auth server of Supabase to verify the ID token provided by the Google sign-in package.
|
||||
|
||||
First, create your Google Cloud project [here](https://cloud.google.com/) if you do not have one yet.
|
||||
Within your Google Cloud project, follow the [Get an OAuth client ID for the iOS](https://developers.google.com/identity/sign-in/ios/start-integrating#get_an_oauth_client_id) guide, [Configure a Google API Console project for Android](https://developers.google.com/identity/sign-in/android/start-integrating#configure_a_project) guide, and [Get your backend server's OAuth 2.0 client ID](https://developers.google.com/identity/sign-in/android/start-integrating#configure_a_project) to obtain client IDs for iOS, Android, and web respectively.
|
||||
|
||||
Once you have the client IDs, let’s add them to our Supabase dashboard. If you don’t have a Supabase project created yet, you can create one at [database.new](https://database.new) for free. The name is just an internal name, so we can call it “Auth” for now. Database Password will not be used in this example and can be reconfigured later, so press the `Generate a password` button and let Supabase generate a secure random password. No need to copy it anywhere. The region should be anywhere close to where you live, or where your users live in an actual production app.
|
||||
|
||||
Once you have the client IDs, let’s add them to our Supabase dashboard. If you don’t have a Supabase project created yet, you can create one at [database.new](https://database.new) for free. The name is just an internal name, so we can call it “Auth” for now.
|
||||
The database password won't be used in this example and can be reconfigured later, so press the `Generate a password` button and let Supabase generate a secure random password. The region should be anywhere close to where you live, or where your users live in an actual production app.
|
||||
Lastly, for the pricing plan choose the free plan that allows you to connect with all major social OAuth providers and supports up to 50,000 monthly active users.
|
||||
|
||||

|
||||
|
||||
Your project should be ready in a minute or two. Once your project is ready, you can open `authentication -> Providers -> Google` to set up Google auth. Toggle the `Enable Sign in with Google` switch first. Then add the two client IDs you obtained in your Google Cloud console to `Authorized Client IDs` field with a comma in between the two client IDs like this: `IOS_CLIENT_ID,ANDROID_CLIENT_ID,WEB_CLIENT_ID`.
|
||||
Your project should be ready in a minute or two. Once your project is ready, open `authentication -> Providers -> Google` to set up Google auth. Toggle the `Enable Sign in with Google` switch first. Then add the web client ID you obtained in your Google Cloud console to `Authorized Client IDs` field. No need to add the Android or iOS client IDs here.
|
||||
|
||||
Turn on the `Skip nonce checks` option. This would allow us to use the Google sign in package on iOS, which is not compatible with providing a method to access or specify a nonce.
|
||||
|
||||

|
||||
|
||||
We also need some Android specific settings to make [flutter_appauth](https://pub.dev/packages/flutter_appauth#android-setup) not throw during app building. Open `android/app/build.gradle` and find the `defaultConfig`. We need to to provide an empty string here.
|
||||
We also need some iOS specific settings. Open `ios/Runner/Info.plist` file and add the `CFBundleURLTypes` like the following. You need to provide the reverse client ID of the iOS client ID you registered earlier.
|
||||
|
||||
```groovy
|
||||
...
|
||||
android {
|
||||
...
|
||||
defaultConfig {
|
||||
...
|
||||
// We need an empty manifestPlaceholders for appauth to not throw an error
|
||||
manifestPlaceholders += [
|
||||
'appAuthRedirectScheme': ''
|
||||
]
|
||||
}
|
||||
}
|
||||
```plist
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<!-- TODO Replace this value: -->
|
||||
<!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID -->
|
||||
<string>com.googleusercontent.apps.my-ios</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
```
|
||||
|
||||
That is it for setting up our [Supabase auth to prepare for Google sign-in](https://supabase.com/docs/guides/auth/social-login/auth-google?platform=flutter).
|
||||
@@ -140,13 +144,7 @@ You can find your Supabase URL and Anon key in `Settings -> API` from your [Supa
|
||||
We will have two screens for this app, `LoginScreen` and `ProfileScreen`. `LoginScreen` presents a single sign-in button for the user to perform Google sign-in. Create a `lib/screens/login_screen.dart` file add add the following.
|
||||
|
||||
```dart
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_appauth/flutter_appauth.dart';
|
||||
import 'package:google_sign_in/google_sign_in.dart';
|
||||
import 'package:myauthapp/main.dart';
|
||||
import 'package:myauthapp/screens/profile_screen.dart';
|
||||
@@ -179,103 +177,40 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Function to generate a random 16 character string.
|
||||
String _generateRandomString() {
|
||||
final random = Random.secure();
|
||||
return base64Url.encode(List<int>.generate(16, (_) => random.nextInt(256)));
|
||||
}
|
||||
|
||||
Future<AuthResponse> _googleSignIn() async {
|
||||
/// TODO: update the iOS and Web client ID with your own.
|
||||
/// TODO: update the Web client ID with your own.
|
||||
///
|
||||
/// Client ID that you registered with Google Cloud.
|
||||
/// Note that in order to perform Google sign in on Android, you need to
|
||||
/// provide the web client ID, not the Android client ID.
|
||||
final clientId = Platform.isIOS ? 'IOS_CLIENT_ID' : 'WEB_CLIENT_ID';
|
||||
/// Web Client ID that you registered with Google Cloud.
|
||||
const webClientId = 'my-web.apps.googleusercontent.com';
|
||||
|
||||
late final String? idToken;
|
||||
late final String? accessToken;
|
||||
String? rawNonce;
|
||||
/// TODO: update the iOS client ID with your own.
|
||||
///
|
||||
/// iOS Client ID that you registered with Google Cloud.
|
||||
const iosClientId = 'my-ios.apps.googleusercontent.com';
|
||||
|
||||
// Use AppAuth to perform Google sign in on iOS
|
||||
// and use GoogleSignIn package for Google sign in on Android
|
||||
if (Platform.isIOS) {
|
||||
const appAuth = FlutterAppAuth();
|
||||
// Google sign in on Android will work without providing the Android
|
||||
// Client ID registered on Google Cloud.
|
||||
|
||||
// Just a random string
|
||||
rawNonce = _generateRandomString();
|
||||
final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString();
|
||||
final GoogleSignIn googleSignIn = GoogleSignIn(
|
||||
clientId: iosClientId,
|
||||
serverClientId: webClientId,
|
||||
);
|
||||
final googleUser = await googleSignIn.signIn();
|
||||
final googleAuth = await googleUser!.authentication;
|
||||
final accessToken = googleAuth.accessToken;
|
||||
final idToken = googleAuth.idToken;
|
||||
|
||||
/// Set as reversed DNS form of Google Client ID + `:/` for Google login
|
||||
final redirectUrl = '${clientId.split('.').reversed.join('.')}:/';
|
||||
|
||||
/// Fixed value for google login
|
||||
const discoveryUrl =
|
||||
'https://accounts.google.com/.well-known/openid-configuration';
|
||||
|
||||
// authorize the user by opening the concent page
|
||||
final result = await appAuth.authorize(
|
||||
AuthorizationRequest(
|
||||
clientId,
|
||||
redirectUrl,
|
||||
discoveryUrl: discoveryUrl,
|
||||
nonce: hashedNonce,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
'profile',
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (result == null) {
|
||||
throw 'No result';
|
||||
}
|
||||
|
||||
// Request the access and id token to google
|
||||
final tokenResult = await appAuth.token(
|
||||
TokenRequest(
|
||||
clientId,
|
||||
redirectUrl,
|
||||
authorizationCode: result.authorizationCode,
|
||||
discoveryUrl: discoveryUrl,
|
||||
codeVerifier: result.codeVerifier,
|
||||
nonce: result.nonce,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
accessToken = tokenResult?.accessToken;
|
||||
idToken = tokenResult?.idToken;
|
||||
} else {
|
||||
final GoogleSignIn googleSignIn = GoogleSignIn(
|
||||
serverClientId: clientId,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
],
|
||||
);
|
||||
final googleUser = await googleSignIn.signIn();
|
||||
final googleAuth = await googleUser!.authentication;
|
||||
accessToken = googleAuth.accessToken;
|
||||
idToken = googleAuth.idToken;
|
||||
}
|
||||
|
||||
if (idToken == null) {
|
||||
throw 'No ID Token';
|
||||
}
|
||||
if (accessToken == null) {
|
||||
throw 'No Access Token';
|
||||
throw 'No Access Token found.';
|
||||
}
|
||||
if (idToken == null) {
|
||||
throw 'No ID Token found.';
|
||||
}
|
||||
|
||||
return supabase.auth.signInWithIdToken(
|
||||
provider: Provider.google,
|
||||
idToken: idToken,
|
||||
accessToken: accessToken,
|
||||
nonce: rawNonce,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -300,87 +235,10 @@ In terms of UI, this page is very simple, it just has a basic `Scaffold` with an
|
||||
|
||||

|
||||
|
||||
Let’s break down what is going on within the `onPressed` callback of the sign in button.
|
||||
At the top, we check on which platform the user is running the application.
|
||||
We will break down the iOS flow, because it helps us understand how the Open ID Connect flow works.
|
||||
|
||||
First, we are generating a [nonce](https://openid.net/specs/openid-connect-core-1_0.html#SelfIssuedDiscovery:~:text=auth_time%20response%20parameter.)-,nonce,-String%20value%20used), which is essentially just a random string. This string is later passed to Google after being hashed to verify that the ID token has not been tampered to prevent a man-in-the-middle attack.
|
||||
|
||||
```dart
|
||||
// Random string to verify the integrity of the ID Token
|
||||
final rawNonce = _generateRandomString();
|
||||
final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString();
|
||||
```
|
||||
|
||||
`clientId` and `applicationId` are the app-specific values. These will be used to the authentication request to Google later on.
|
||||
|
||||
```dart
|
||||
/// Client ID that you registered with Google Cloud.
|
||||
/// You will have two different values for iOS and Android.
|
||||
final clientId = Platform.isIOS ? 'IOS_CLIENT_ID' : 'ANDROID_CLIENT_ID';
|
||||
```
|
||||
|
||||
`redirectUrl` is the URL at which the user will be redirected after a successful authentication request. For Google sign-in, we can set it to the reversed DNS form of the client ID followed by `:/`. `discoveryUrl` is a URL provided by Google that contains information about their Open ID configuration.
|
||||
|
||||
```dart
|
||||
/// Set as reversed DNS form of Google Client ID + `:/` for Google login
|
||||
final redirectUrl = '${clientId.split('.').reversed.join('.')}:/';
|
||||
|
||||
/// Fixed value for google login
|
||||
const discoveryUrl = 'https://accounts.google.com/.well-known/openid-configuration';
|
||||
```
|
||||
|
||||
Then we are sending an authorization request to Google. This is where the user is taken to Google’s page to perform sign in and consent our app to obtain some personal information. Note that we are requesting three scopes here. `openid` and `email` are required by Supabase auth to complete the sign-in process. `profile` is not required by Supabase auth, but we are requesting it to display some profile information on the profile screen later on. We do not actually obtain the requested information in this step though. All we are doing is requesting an access token that has permission to obtain the personal information we have requested.
|
||||
|
||||
```dart
|
||||
// Authorize the user by opening the concent page
|
||||
final result = await appAuth.authorize(
|
||||
AuthorizationRequest(
|
||||
clientId,
|
||||
redirectUrl,
|
||||
discoveryUrl: discoveryUrl,
|
||||
nonce: hashedNonce,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
'profile',
|
||||
],
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
Using the authorization token obtained in the previous step, we make the final request to Google’s auth server to obtain the personal information we asked for earlier. We get an ID token in return, which contains the personal information.
|
||||
|
||||
```dart
|
||||
// Request the access and id token to google
|
||||
final tokenResult = await appAuth.token(
|
||||
TokenRequest(
|
||||
clientId,
|
||||
redirectUrl,
|
||||
authorizationCode: result.authorizationCode,
|
||||
discoveryUrl: discoveryUrl,
|
||||
codeVerifier: result.codeVerifier,
|
||||
nonce: result.nonce,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
'profile',
|
||||
],
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
And lastly, we pass the ID token we obtained from Google to Supabase to complete the sign-in on Supabase auth. Once the user is signed in, the auth state listener in the `initState` fires and takes the user to the `ProfileScreen`.
|
||||
|
||||
```dart
|
||||
await supabase.auth.signInWithIdToken(
|
||||
provider: Provider.google,
|
||||
idToken: idToken,
|
||||
nonce: rawNonce,
|
||||
);
|
||||
```
|
||||
|
||||
The android flow goes through similar steps, but all of the heavy lifting of obtaining the access token and ID token is done by the `google_sign_in` package.
|
||||
Within the `onPressed` callback of the button, we are calling the `_googleSignIn` method.
|
||||
This method calls the Google sign-in package to perform the sign-in flow.
|
||||
Once the user completes the sign-in flow, we obtain an access token and an ID token.
|
||||
We will pass these tokens to Supabase auth to then obtain a Supabase session.
|
||||
|
||||
## Create the Profile Screen
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 331 KiB After Width: | Height: | Size: 274 KiB |
@@ -1,11 +1,11 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
channel: stable
|
||||
revision: "6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
||||
@@ -13,26 +13,26 @@ project_type: app
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
- platform: android
|
||||
create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
- platform: ios
|
||||
create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
- platform: linux
|
||||
create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
- platform: macos
|
||||
create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
- platform: web
|
||||
create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
- platform: windows
|
||||
create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
|
||||
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
|
||||
|
||||
# User provided section
|
||||
|
||||
|
||||
@@ -52,10 +52,6 @@ android {
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
// You need an empty manifestPlaceholders for appauth to not throw an error
|
||||
manifestPlaceholders += [
|
||||
'appAuthRedirectScheme': ''
|
||||
]
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,17 @@ PODS:
|
||||
- AppAuth/ExternalUserAgent (1.6.2):
|
||||
- AppAuth/Core
|
||||
- Flutter (1.0.0)
|
||||
- flutter_appauth (0.0.1):
|
||||
- AppAuth (= 1.6.2)
|
||||
- google_sign_in_ios (0.0.1):
|
||||
- Flutter
|
||||
- GoogleSignIn (~> 6.2)
|
||||
- GoogleSignIn (6.2.4):
|
||||
- AppAuth (~> 1.5)
|
||||
- GTMAppAuth (~> 1.3)
|
||||
- GTMSessionFetcher/Core (< 3.0, >= 1.1)
|
||||
- GTMAppAuth (1.3.1):
|
||||
- AppAuth/Core (~> 1.6)
|
||||
- GTMSessionFetcher/Core (< 3.0, >= 1.5)
|
||||
- GTMSessionFetcher/Core (2.3.0)
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -27,7 +35,7 @@ PODS:
|
||||
DEPENDENCIES:
|
||||
- app_links (from `.symlinks/plugins/app_links/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_appauth (from `.symlinks/plugins/flutter_appauth/ios`)
|
||||
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
|
||||
@@ -37,14 +45,17 @@ DEPENDENCIES:
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- AppAuth
|
||||
- GoogleSignIn
|
||||
- GTMAppAuth
|
||||
- GTMSessionFetcher
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
:path: ".symlinks/plugins/app_links/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_appauth:
|
||||
:path: ".symlinks/plugins/flutter_appauth/ios"
|
||||
google_sign_in_ios:
|
||||
:path: ".symlinks/plugins/google_sign_in_ios/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
shared_preferences_foundation:
|
||||
@@ -60,9 +71,12 @@ SPEC CHECKSUMS:
|
||||
app_links: 5ef33d0d295a89d9d16bb81b0e3b0d5f70d6c875
|
||||
AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_appauth: cf9b928962105b2a64a9802585d1c8adaf3e0f46
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
|
||||
google_sign_in_ios: 1256ff9d941db546373826966720b0c24804bcdd
|
||||
GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a
|
||||
GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd
|
||||
GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
139D526D6DAAC306FF934AF7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4AAD0E3ADC689337ACEF792 /* Pods_Runner.framework */; };
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
3304FB9E97805348E2562BE0 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B564902DECB04C26DF5C1990 /* Pods_Runner.framework */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
DEA8302A70C9ACD2650F9B7C /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 828A241E8FA8208665D3EB86 /* Pods_RunnerTests.framework */; };
|
||||
BAB0D682C8D30413CA341239 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAAD19358373E12AFFCF4373 /* Pods_RunnerTests.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -42,19 +42,17 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
01D09B21062AD4556A06A6E3 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
0CD475A43E8DA600E2B982AC /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
27BEFA69E5DA94D046EFBE00 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
20BC47085BC335E3D8D7FC90 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
38E30A4AF317B140613697D2 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
426FE104D430BF3CD70AF9E2 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
472D51D7E326E44047EEC5F0 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
828A241E8FA8208665D3EB86 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -62,31 +60,56 @@
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
B564902DECB04C26DF5C1990 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0870FF5D39BE2F0E613C78C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
F00CBB189671F834144DE713 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
B60B31F58DF0279BAF4DA310 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C94B4E330EE1AD8F6C0AC8F7 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
DAAD19358373E12AFFCF4373 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E4AAD0E3ADC689337ACEF792 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FA53A77B0831C3F3DE80EA3D /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
71EF4399EB075B7C77CF3021 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BAB0D682C8D30413CA341239 /* Pods_RunnerTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3304FB9E97805348E2562BE0 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F0B9F11E87752367F31C27C8 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DEA8302A70C9ACD2650F9B7C /* Pods_RunnerTests.framework in Frameworks */,
|
||||
139D526D6DAAC306FF934AF7 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
1DB24B391EB6593AFC13AA32 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
20BC47085BC335E3D8D7FC90 /* Pods-Runner.debug.xcconfig */,
|
||||
B60B31F58DF0279BAF4DA310 /* Pods-Runner.release.xcconfig */,
|
||||
01D09B21062AD4556A06A6E3 /* Pods-Runner.profile.xcconfig */,
|
||||
0CD475A43E8DA600E2B982AC /* Pods-RunnerTests.debug.xcconfig */,
|
||||
C94B4E330EE1AD8F6C0AC8F7 /* Pods-RunnerTests.release.xcconfig */,
|
||||
FA53A77B0831C3F3DE80EA3D /* Pods-RunnerTests.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
256B90543BCD7B7737B4F6B3 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E4AAD0E3ADC689337ACEF792 /* Pods_Runner.framework */,
|
||||
DAAD19358373E12AFFCF4373 /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -95,28 +118,6 @@
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4147D33225043F42F09814E7 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0870FF5D39BE2F0E613C78C /* Pods-Runner.debug.xcconfig */,
|
||||
38E30A4AF317B140613697D2 /* Pods-Runner.release.xcconfig */,
|
||||
F00CBB189671F834144DE713 /* Pods-Runner.profile.xcconfig */,
|
||||
27BEFA69E5DA94D046EFBE00 /* Pods-RunnerTests.debug.xcconfig */,
|
||||
472D51D7E326E44047EEC5F0 /* Pods-RunnerTests.release.xcconfig */,
|
||||
426FE104D430BF3CD70AF9E2 /* Pods-RunnerTests.profile.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83C49BB5102259C76EED0D53 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B564902DECB04C26DF5C1990 /* Pods_Runner.framework */,
|
||||
828A241E8FA8208665D3EB86 /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -135,8 +136,8 @@
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
4147D33225043F42F09814E7 /* Pods */,
|
||||
83C49BB5102259C76EED0D53 /* Frameworks */,
|
||||
1DB24B391EB6593AFC13AA32 /* Pods */,
|
||||
256B90543BCD7B7737B4F6B3 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -171,10 +172,10 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
42C78DCFB35050844813EE93 /* [CP] Check Pods Manifest.lock */,
|
||||
3F6E40BE5EE61FB34D24E363 /* [CP] Check Pods Manifest.lock */,
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
F0B9F11E87752367F31C27C8 /* Frameworks */,
|
||||
71EF4399EB075B7C77CF3021 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -190,14 +191,14 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
72352E8546CF6F5BA1AA1932 /* [CP] Check Pods Manifest.lock */,
|
||||
D13F0F6643ACD43F91A0DCB3 /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
D5C0C78971716833C4CC4F79 /* [CP] Embed Pods Frameworks */,
|
||||
2B4EFE470EC5A13A344C8224 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -214,7 +215,8 @@
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1300;
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1430;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
@@ -268,6 +270,23 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
2B4EFE470EC5A13A344C8224 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
@@ -284,7 +303,7 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
42C78DCFB35050844813EE93 /* [CP] Check Pods Manifest.lock */ = {
|
||||
3F6E40BE5EE61FB34D24E363 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -306,7 +325,22 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
72352E8546CF6F5BA1AA1932 /* [CP] Check Pods Manifest.lock */ = {
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
D13F0F6643ACD43F91A0DCB3 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -328,38 +362,6 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
D5C0C78971716833C4CC4F79 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@@ -484,14 +486,14 @@
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 27BEFA69E5DA94D046EFBE00 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
baseConfigurationReference = 0CD475A43E8DA600E2B982AC /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.myAuthApp.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.myauthapp.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -502,14 +504,14 @@
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 472D51D7E326E44047EEC5F0 /* Pods-RunnerTests.release.xcconfig */;
|
||||
baseConfigurationReference = C94B4E330EE1AD8F6C0AC8F7 /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.myAuthApp.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.myauthapp.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
@@ -518,14 +520,14 @@
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 426FE104D430BF3CD70AF9E2 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
baseConfigurationReference = FA53A77B0831C3F3DE80EA3D /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.myAuthApp.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.myauthapp.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1300"
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -2,12 +2,10 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>My Auth App</string>
|
||||
<string>Myauthapp</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -15,7 +13,7 @@
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Supabase Auth</string>
|
||||
<string>myauthapp</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
@@ -26,8 +24,6 @@
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
@@ -45,7 +41,22 @@
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<!-- TODO Replace this value: -->
|
||||
<!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID -->
|
||||
<string>com.googleusercontent.apps.my-ios</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,10 +1,4 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_appauth/flutter_appauth.dart';
|
||||
import 'package:google_sign_in/google_sign_in.dart';
|
||||
import 'package:myauthapp/main.dart';
|
||||
import 'package:myauthapp/screens/profile_screen.dart';
|
||||
@@ -37,103 +31,40 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Function to generate a random 16 character string.
|
||||
String _generateRandomString() {
|
||||
final random = Random.secure();
|
||||
return base64Url.encode(List<int>.generate(16, (_) => random.nextInt(256)));
|
||||
}
|
||||
|
||||
Future<AuthResponse> _googleSignIn() async {
|
||||
/// TODO: update the iOS and Web client ID with your own.
|
||||
/// TODO: update the Web client ID with your own.
|
||||
///
|
||||
/// Client ID that you registered with Google Cloud.
|
||||
/// Note that in order to perform Google sign in on Android, you need to
|
||||
/// provide the web client ID, not the Android client ID.
|
||||
final clientId = Platform.isIOS ? 'IOS_CLIENT_ID' : 'WEB_CLIENT_ID';
|
||||
/// Web Client ID that you registered with Google Cloud.
|
||||
const webClientId = 'my-web.apps.googleusercontent.com';
|
||||
|
||||
late final String? idToken;
|
||||
late final String? accessToken;
|
||||
String? rawNonce;
|
||||
/// TODO: update the iOS client ID with your own.
|
||||
///
|
||||
/// iOS Client ID that you registered with Google Cloud.
|
||||
const iosClientId = 'my-ios.apps.googleusercontent.com';
|
||||
|
||||
// Use AppAuth to perform Google sign in on iOS
|
||||
// and use GoogleSignIn package for Google sign in on Android
|
||||
if (Platform.isIOS) {
|
||||
const appAuth = FlutterAppAuth();
|
||||
// Google sign in on Android will work without providing the Android
|
||||
// Client ID registered on Google Cloud.
|
||||
|
||||
// Just a random string
|
||||
rawNonce = _generateRandomString();
|
||||
final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString();
|
||||
final GoogleSignIn googleSignIn = GoogleSignIn(
|
||||
clientId: iosClientId,
|
||||
serverClientId: webClientId,
|
||||
);
|
||||
final googleUser = await googleSignIn.signIn();
|
||||
final googleAuth = await googleUser!.authentication;
|
||||
final accessToken = googleAuth.accessToken;
|
||||
final idToken = googleAuth.idToken;
|
||||
|
||||
/// Set as reversed DNS form of Google Client ID + `:/` for Google login
|
||||
final redirectUrl = '${clientId.split('.').reversed.join('.')}:/';
|
||||
|
||||
/// Fixed value for google login
|
||||
const discoveryUrl =
|
||||
'https://accounts.google.com/.well-known/openid-configuration';
|
||||
|
||||
// authorize the user by opening the concent page
|
||||
final result = await appAuth.authorize(
|
||||
AuthorizationRequest(
|
||||
clientId,
|
||||
redirectUrl,
|
||||
discoveryUrl: discoveryUrl,
|
||||
nonce: hashedNonce,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
'profile',
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (result == null) {
|
||||
throw 'No result';
|
||||
}
|
||||
|
||||
// Request the access and id token to google
|
||||
final tokenResult = await appAuth.token(
|
||||
TokenRequest(
|
||||
clientId,
|
||||
redirectUrl,
|
||||
authorizationCode: result.authorizationCode,
|
||||
discoveryUrl: discoveryUrl,
|
||||
codeVerifier: result.codeVerifier,
|
||||
nonce: result.nonce,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
accessToken = tokenResult?.accessToken;
|
||||
idToken = tokenResult?.idToken;
|
||||
} else {
|
||||
final GoogleSignIn googleSignIn = GoogleSignIn(
|
||||
serverClientId: clientId,
|
||||
scopes: [
|
||||
'openid',
|
||||
'email',
|
||||
],
|
||||
);
|
||||
final googleUser = await googleSignIn.signIn();
|
||||
final googleAuth = await googleUser!.authentication;
|
||||
accessToken = googleAuth.accessToken;
|
||||
idToken = googleAuth.idToken;
|
||||
}
|
||||
|
||||
if (idToken == null) {
|
||||
throw 'No ID Token';
|
||||
}
|
||||
if (accessToken == null) {
|
||||
throw 'No Access Token';
|
||||
throw 'No Access Token found.';
|
||||
}
|
||||
if (idToken == null) {
|
||||
throw 'No ID Token found.';
|
||||
}
|
||||
|
||||
return supabase.auth.signInWithIdToken(
|
||||
provider: Provider.google,
|
||||
idToken: idToken,
|
||||
accessToken: accessToken,
|
||||
nonce: rawNonce,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
crypto:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
@@ -118,22 +118,6 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_appauth:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_appauth
|
||||
sha256: "19031ea2438a513762e64ec7b58ae1f00cad6fb87f818e405325cd183dfb9fec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
flutter_appauth_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_appauth_platform_interface
|
||||
sha256: "44feaa7058191b5d3cd7c9ff195262725773643121bcada172d49c2ddcff71cb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
|
||||
@@ -13,8 +13,6 @@ dependencies:
|
||||
sdk: flutter
|
||||
|
||||
supabase_flutter: ^1.10.19
|
||||
flutter_appauth: ^6.0.0
|
||||
crypto: ^3.0.3
|
||||
google_sign_in: ^6.1.5
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
Reference in new issue
Block a user