skip to Main Content

I am working on a flutter application, and I want to implement social login (Google and Facebook).

My API is implemented with Laravel and uses Laravel-socialite to authenticate users, there is the backend, web frontend (using VueJs) and now I am working on the mobile application using flutter.

The web application is working good (using the vue-social-auth package).

What I have done till now:

  1. Used flutter_google_sign_in to handle authentication on the flutter app.
  2. Did configure the package and I can successfully get user info through that package.

Problem I am facing:

What I don’t seem to get working is to send the user that just logged in to the backend in order to provide an in-app user experience.

This is what the vue-social-auth package provides and what I send to the backend, which is working fine:

{code: "4/0AY0e-g442SMxdtLb_MVdQ63u1ydp48bbCRQco5Azoyf3y1rvYybDabyZGOvwAs7ZFJDQHA", scope: "email+profile+openid+https://www.googleapis.com/au…le+https://www.googleapis.com/auth/userinfo.email", authuser: "0", prompt: "consent"}

And this is what flutter_google_sign_in gives (aside of the user profile data:

idToken: "",
accessToken: "",
serverAuthCode: "", 

serverAuthCode is always null.

How can I make it so that, using the same API logic, log-in users on flutter through social accounts?

Thank you.

2

Answers


  1. Chosen as BEST ANSWER

    I have solved it, after some digging I found out Laravel-Socialite has the functionality to log in users using their token built-in:

    Quoting Socialite documentation:

    If you already have a valid access token for a user, you can retrieve their details using Socialite's userFromToken method.


  2. Apparently, google sign in doesn’t work on flutter except with Firebase/some cloud API backend service. I was using a local Laravel API for user auth so adding google sign in functionality requires setting up a firebase account/profile, downloading and adding the googleservices.json file to flutter project as explained in google_sign_in package installation manual. You also need to import firebase-auth package

    Flutter Code (I use flutter modular pattern but same applies with Bloc/Provider if you get the idea as explained by Hamza Mogni above)

    import 'package:google_sign_in/google_sign_in.dart';
     import 'package:firebase_auth/firebase_auth.dart';
    
      final GoogleSignIn _googleSignIn = GoogleSignIn();
      final FirebaseAuth _auth = FirebaseAuth.instance;
    
      Future<LoginResponseModel> googleLoginResponse() async {
        
        String url = env['API_BASE_URL'] + '/api/auth/google';
    
        //click on google sign in. Get accessToken from google through googlesignin 
         plugin.
        //Send accessToken to socialite in backend to request/create user data
    
        GoogleSignInAccount googleSignInAccount = await _googleSignIn.signIn();
        if (googleSignInAccount == null) {
          print('Google Signin ERROR! googleAccount: null!');
          return null;
        }
        GoogleSignInAuthentication googleSignInAuthentication =
            await googleSignInAccount.authentication;
        
       //this is user access token from google that is retrieved with the plugin
        print("User Access Token: ${googleSignInAuthentication.accessToken}");
        String accessToken = googleSignInAuthentication.accessToken;
        
        //make http request to the laravel backend 
        final response =
            await http.post(
                      url,
                      body: json.encode({"token": accessToken}),
                      headers: {"Content-Type": "application/json"});
        if (response.statusCode == 200 || response.statusCode == 422) {
          return LoginResponseModel.fromJson(
            json.decode(response.body), // {'message':'Google signin successful'}
          );
        } else {
          throw Exception('Failed to load data!');
        }
      }
    

    For Logout function, you need to signout of both firebase and google account instance or you will always be logged in by the first known/used google account in subsequent login attempts.

    Future<LogoutResponseModel> logout() async {
        try {
          await _auth.signOut();
          await _googleSignIn.disconnect();
        } catch (e) {
          print('Failed to sign out ' + e.toString());
        }
        //api route to destroy sanctum token. santum token is added as authorization header
        var url = env['API_BASE_URL'] + "/api/logout";
        final response =
            await http.post(Uri.tryParse(url), headers: {'Bearer ' $sanctumtoken});
        if (response.statusCode == 200 || response.statusCode == 422) {
          return LogoutResponseModel.fromJson(
            json.decode(response.body),
          );
        } else {
          throw Exception('Failed to load data!');
        }
      }
    

    Laravel Code (route to controller method is api/auth/google, method expects to receive google access token from flutter app)

    public function requestTokenGoogle(Request $request) {
            // Getting the user from socialite using token from google
            $user = Socialite::driver('google')->stateless()->userFromToken($request->token);
    
            // Getting or creating user from db
            $userFromDb = User::firstOrCreate(
                ['email' => $user->getEmail()],
                [
                    'email_verified_at' => now(),
                    'first_name' => $user->offsetGet('given_name'),
                    'last_name' => $user->offsetGet('family_name'),
                    'avatar' => $user->getAvatar(),
                ]
            );
    
            // Returning response
            $token = $userFromDb->createToken('Laravel Sanctum Client')->plainTextToken;
            $response = ['token' => $token, 'message' => 'Google Login/Signup Successful'];
            return response($response, 200);
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search