1

I want my Login Screen to be shown if a user isn't logged in and the MainPage to be shown if the user is logged in from the device. For GitHub authentication, the browser is being opened and once the authentication is successful, I want the user to be redirected to the MainPage and not the login screen, but with my code, the user is redirected again to the Login Screen. The code for the login_screen.dart is,

import 'package:flutter/material.dart';
import 'package:githubapp/custom_widgets/custom_login_page.dart';
import 'package:githubapp/screens/user_initial_screen.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:async';
import 'package:uni_links/uni_links.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  StreamSubscription _subs;

  @override
  void initState() {
    _initDeepLinkListener();
    super.initState();
  }

  @override
  void dispose() {
    _disposeDeepLinkListener();
    super.dispose();
  }

  void _initDeepLinkListener() async {
    _subs = getLinksStream().listen((String link) {
      _checkDeepLink(link);
    }, cancelOnError: true);
  }

  void _checkDeepLink(String link) {
    if (link != null) {
      String code = link.substring(link.indexOf(RegExp('code=')) + 5);
      loginWithGitHub(code)
          .then((firebaseUser) {
        print("LOGGED IN AS: " + firebaseUser.displayName);
        Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (BuildContext context){
          return MainPage();
        }));
      }).catchError((e) {
        print("LOGIN ERROR: " + e.toString());
      });
    }
  }

  void _disposeDeepLinkListener() {
    if (_subs != null) {
      _subs.cancel();
      _subs = null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return customLoginPage(context);
  }
}

const String GITHUB_CLIENT_ID = "My Client Id";
const String GITHUB_CLIENT_SECRET = "My Client Secret";

void onClickGitHubLoginButton() async {
  const String url = "https://github.com/login/oauth/authorize" +
      "?client_id=" + GITHUB_CLIENT_ID +
      "&scope=public_repo%20read:user%20user:email";

  if (await canLaunch(url)) {
    await launch(
      url,
      forceSafariVC: false,
      forceWebView: false,
    );
  } else {
    print("CANNOT LAUNCH THIS URL!");
  }
}

Future<FirebaseUser> loginWithGitHub(String code) async {
  //ACCESS TOKEN REQUEST
  final response = await http.post(
    "https://github.com/login/oauth/access_token",
    headers: {
      "Content-Type": "application/json",
      "Accept": "application/json"
    },
    body: jsonEncode(GitHubLoginRequest(
      clientId: GITHUB_CLIENT_ID,
      clientSecret: GITHUB_CLIENT_SECRET,
      code: code,
    )),
  );

  GitHubLoginResponse loginResponse =
  GitHubLoginResponse.fromJson(json.decode(response.body));

  final AuthCredential credential = GithubAuthProvider.getCredential(
    token: loginResponse.accessToken,
  );

  final FirebaseUser user = (await FirebaseAuth.instance.signInWithCredential(credential)).user;
  return user;
}

class GitHubLoginRequest {
  String clientId;
  String clientSecret;
  String code;

  GitHubLoginRequest({this.clientId, this.clientSecret, this.code});

  dynamic toJson() => {
    "client_id": clientId,
    "client_secret": clientSecret,
    "code": code,
  };
}

class GitHubLoginResponse {
  String accessToken;
  String tokenType;
  String scope;

  GitHubLoginResponse({this.accessToken, this.tokenType, this.scope});

  factory GitHubLoginResponse.fromJson(Map<String, dynamic> json) =>
      GitHubLoginResponse(
        accessToken: json["access_token"],
        tokenType: json["token_type"],
        scope: json["scope"],
      );
}

The code on the main.dart is,

import 'package:flutter/material.dart';
import 'package:githubapp/auth/login_screen.dart';
import 'package:githubapp/screens/user_initial_screen.dart';
import 'package:githubapp/screens/user_profile_page.dart';
import 'package:firebase_auth/firebase_auth.dart';


void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  // This widget is the root of your application.
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  String routeToMainPage = 'mainPage';
  String routeToLoginPage = 'loginPage';
  String routeInitial = '';

  getCurrentUser() async {
    FirebaseUser user = await FirebaseAuth.instance.currentUser();
    return user;
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    if(getCurrentUser() != null){
      routeInitial = routeToMainPage;
    } else {
      routeInitial = routeToLoginPage;
    }
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'GitHub',
     initialRoute: '/${routeInitial}',
      routes: {
        '/mainPage': (context) => MainPage(),
        '/loginPage': (context) => LoginPage(),
        '/userprofile': (context) => UserProfilePage(),
      },
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
    );
  }
}

The code where the MainPage() function is present is,

import 'package:flutter/material.dart';
import 'package:githubapp/custom_widgets/custom_appbar.dart';

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Scaffold(
        appBar: customAppBar(context),
//        body: ,
      ),
      onTap: () {
        FocusScopeNode currentFocus = FocusScope.of(context);
        if (!currentFocus.hasPrimaryFocus) {
          currentFocus.unfocus();
        }
      },
    );
  }
}

For the Authorization callback URL, which we have to enter while getting the ClientId and ClientSecret from GitHub is, appname://auth?code=auth/

Devansh Baldwa
  • 129
  • 2
  • 4
  • 14

1 Answers1

0

you should navigate user to mainPage after login was successfully

void _checkDeepLink(String link) {
    if (link != null) {
      String code = link.substring(link.indexOf(RegExp('code=')) + 5);
      loginWithGitHub(code)
          .then((firebaseUser) {
        print("LOGGED IN AS: " + firebaseUser.displayName);
        Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (BuildContext context){
          return MainPage();
        }));
      }).catchError((e) {
        print("LOGIN ERROR: " + e.toString());
      });
    }
  }
Amir
  • 2,225
  • 2
  • 18
  • 27
  • Not sure why but I am again being redirected to the LoginPage. Please could you show the code what I should be using in the MainPage code also. – Devansh Baldwa Feb 23 '20 at 08:16
  • you should check user login on splash screen or some where like splash screen because `getCurrentUser()` is a async function and before this function get response your initial route execute and it think user not login because `getCurrentUser()` response is null yet and navigate you to login page – Amir Feb 23 '20 at 11:38
  • Is there a way to check user login at splash screen because when we code for the app, we start from the first page only, so how to check for it at the splash screen? – Devansh Baldwa Feb 23 '20 at 11:42
  • you cant start from first page, another way is you set your initial route to main page and check user login on main page and set and `CircularProgressIndicator()` until `getCurrentUser()` response come and then choose user stay in main page or navigate to login page but its better you check login on splash screen – Amir Feb 23 '20 at 11:48
  • I've tried it like you said, but still the LoginPage is being redirected again. Please could make the changes you are suggesting in the code of the question and answer? – Devansh Baldwa Feb 23 '20 at 12:33
  • Have you tried to debug it and correct the mistake? If not, please try to solve it. Any help will be appreciated. – Devansh Baldwa Feb 29 '20 at 05:08