From ce7fb79f8745d32da6d5380aaa878e313b2e1d44 Mon Sep 17 00:00:00 2001 From: dshukertjr <18113850+dshukertjr@users.noreply.github.com> Date: Fri, 28 Jul 2023 15:37:10 +0700 Subject: [PATCH] update flutter code for native google login to use reverse dns form for redirect URL --- .../guides/auth/social-login/auth-google.mdx | 135 ++++++++++-------- 1 file changed, 73 insertions(+), 62 deletions(-) diff --git a/apps/docs/pages/guides/auth/social-login/auth-google.mdx b/apps/docs/pages/guides/auth/social-login/auth-google.mdx index 41d4fdb0f24..a4d2728207b 100644 --- a/apps/docs/pages/guides/auth/social-login/auth-google.mdx +++ b/apps/docs/pages/guides/auth/social-login/auth-google.mdx @@ -72,76 +72,87 @@ When the user provides consent, Google issues an identity token (commonly abbrev If you are building a Flutter app, you can use [flutter_appauth](https://pub.dev/packages/flutter_appauth) package to sign a user into your Supabase project: ````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'; -// Generate a random string -final rawNonce = generateRandomString(); -final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString(); - -// Your registered Google client ID here. -// This will be different for iOS and Android -const clientId = 'YOUR_GOODLE_CLIENT_ID'; - -// bundle ID for iOS, package name for Android here -final packageName = 'io.supabase.example'; - -/// fixed for google login -final redirectUrl = '$packageName:/google_auth'; - -/// fixed for google login -const discoveryUrl = - 'https://accounts.google.com/.well-known/openid-configuration'; - -final appAuth = FlutterAppAuth(); - -// authorize the user by opening the consent page -final result = await appAuth.authorize( - AuthorizationRequest( - clientId, - redirectUrl, - discoveryUrl: discoveryUrl, - nonce: hashedNonce, - scopes: [ - 'openid', - 'email', - ], - ), -); - -if (result == null) { - throw AuthException( - 'Could not find AuthorizationResponse after authorizing'); +/// Function to generate a random 16 character string. +String _generateRandomString() { + final random = Random.secure(); + return base64Url.encode(List.generate(16, (_) => random.nextInt(256))); } -// Request the access and id token to google -final tokenResponse = await appAuth.token( - TokenRequest( - clientId, - redirectUrl, - authorizationCode: result.authorizationCode, - discoveryUrl: discoveryUrl, - codeVerifier: result.codeVerifier, - nonce: result.nonce, - scopes: [ - 'openid', - 'email', - ], - ), -); +Future signInWithGoogle() { + // Just a random string + final rawNonce = _generateRandomString(); + final hashedNonce = + sha256.convert(utf8.encode(rawNonce)).toString(); -final idToken = tokenResponse?.idToken; + /// TODO: update the client ID with your own + /// + /// Client ID that you registered with Google Cloud. + /// You will have two different values for iOS and Android. + const clientId = 'YOUR_CLIENT_ID_HERE'; -if (idToken == null) { - throw AuthException('Could not find idToken from the token response'); + /// reverse DNS form of the client ID + `:/` is set as the redirect URL + final redirectUrl = '${clientId.split('.').reversed.join('.')}:/'; + + /// Fixed value for google login + const discoveryUrl = + 'https://accounts.google.com/.well-known/openid-configuration'; + + final appAuth = FlutterAppAuth(); + + // authorize the user by opening the consent page + final result = await appAuth.authorize( + AuthorizationRequest( + clientId, + redirectUrl, + discoveryUrl: discoveryUrl, + nonce: hashedNonce, + scopes: [ + 'openid', + 'email', + ], + ), + ); + + if (result == null) { + throw 'Could not find AuthorizationResponse after authorizing'; + } + + // 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', + ], + ), + ); + + final idToken = tokenResult?.idToken; + + if (idToken == null) { + throw 'Could not find idToken from the token response'; + } + + return supabase.auth.signInWithIdToken( + provider: Provider.google, + idToken: idToken, + accessToken: tokenResponse?.accessToken, + nonce: rawNonce, + ); } - -await signInWithIdToken( - provider: Provider.google, - idToken: idToken, - accessToken: tokenResponse?.accessToken, - nonce: rawNonce, -);``` +``` In the Supabase JavaScript library, which you can use with web-based native frameworks like React Native or Expo, you can invoke this functionality like so: