1

I've been using Google Places Search in flutter using my own simple client service which uses Google Places API. I've noticed there are other SDK specifically designed for Android and IOS - (Places SDK for Android / IOS)

When I looked inside the key restriction for the API, I realized this seems Google Places API is designed to use for the server-side applications (the key can be restricted for certain IPs) while it cannot be restricted to Android / IOS apps.

As far as I know, everyone can hack the app then they can get the API. Is that a safer way to use google place search within flutter?

e-j5
  • 1,759
  • 1
  • 11
  • 23

2 Answers2

0

I assume you means API key from GG service. Like most API services provider it is the key to use the service with very minimum security measure. It really the renter of the service (you) to have protection measure against abusive usage.

Imagine you operate a Bakery store and Google supply you the bread through a door with a key. If all your customers has access to that key, they will open and use as many bread as they want. Solution is for you to have that door in the back house and only your staffs (your programs/services) has access. Then customer can buy your bread and you can decorate the bread more beautiful to increase the price.

I don't think this is related to Flutter only. The thing is you need to protect that API key. Completely not allow the user to have access to it. Some of the defense technique can be implemented. I would recommend a read on this short list: https://dev.to/bearer/api-security-best-practices-3gjl

Chop TRAN
  • 487
  • 4
  • 9
  • 1
    Thank you for the insight into security around API. My question is more to Google's place API/SDK as I stated, there are three types of it. If I develop native Android I will use Place SDK for Android, as for IOS as well. But for Flutter, I cannot use any of those yet (as far as I know - would be nice if there is one that wrapping abounds the SDKs). And I know there are many people using just the Places API inside their Flutter app. I wanted to know how they protect their API key for Places API. – e-j5 Nov 04 '20 at 04:57
  • a similar question asked around Android, here is the answer. https://stackoverflow.com/a/44745592/2641128 – e-j5 Nov 04 '20 at 05:00
0

pubspec.ymal

 flutter_inappwebview: ^5.3.2

main.dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';



class MyChromeSafariBrowser extends ChromeSafariBrowser {
  @override
  void onOpened() {
    print("ChromeSafari browser opened");
  }

  @override
  void onCompletedInitialLoad() {
    print("ChromeSafari browser initial load completed");
  }

  @override
  void onClosed() {
    print("ChromeSafari browser closed");
  }
}

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();

  if (Platform.isAndroid) {
    await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
  }

  runApp(MaterialApp(home: MyApp(), theme: new ThemeData(scaffoldBackgroundColor: const Color(0xFFA7A5A5)),
      debugShowCheckedModeBanner: false));
}

class MyApp extends StatefulWidget {
  final ChromeSafariBrowser browser = new MyChromeSafariBrowser();

  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // @override
  // void initState() {
  //   widget.browser.addMenuItem(new ChromeSafariBrowserMenuItem(
  //       id: 1,
  //       label: 'Custom item menu 1',
  //       action: (url, title) {
  //         print('Custom item menu 1 clicked!');
  //       }));
  //   super.initState();
  // }

  TextEditingController controller=TextEditingController();
  var urlString="";
  launchUrl()
  async {
    String prefix = "https://www.google.com/search?q=";
    urlString=controller.text;
    if(!urlString.startsWith("http://") && !urlString.startsWith("https://")&&
        !urlString.endsWith(".com")  && !urlString.endsWith(".as") &&
        !urlString.endsWith(".uk") && !urlString.endsWith(".biz")&&!urlString.endsWith(".in")|| urlString.contains(" ") )
    {
      urlString=prefix+urlString;
    }
    if(urlString.endsWith(".com") || urlString.endsWith(".as") || urlString.endsWith(".uk") || urlString.endsWith(".biz")||urlString.endsWith(".in") )
    {
      if(!urlString.startsWith("http://") && !urlString.startsWith("https://"))
      {
        urlString = "http://"+urlString;
      }
    }
    await widget.browser.open(
        url: Uri.parse(urlString),
        options: ChromeSafariBrowserClassOptions(
            android: AndroidChromeCustomTabsOptions(
              addDefaultShareMenuItem: false,),
            ios: IOSSafariOptions(barCollapsingEnabled: true)));
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title:  TextField(
          autofocus: false,
          controller: controller,
          cursorColor: Colors.black,
          textInputAction: TextInputAction.search,
          onSubmitted: (url)=>launchUrl(),
          style: TextStyle(color: Colors.black),
          decoration: InputDecoration(
            border:InputBorder.none,
            hintText: "Search Google Or Enter URL",
            hintStyle: TextStyle(color:Colors.grey),
            filled: true,
            fillColor: Colors.white,
            prefixIcon: Icon(Icons.search),
          ),
        ),
      ),

      body:


      SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child:
        Column(children: <Widget>[


          Row(children: <Widget>[
            Container(
              // padding: EdgeInsets.all(50),
              alignment: Alignment.center,
              margin: const EdgeInsets.only(top: 30.0,left:10.0),
              child:
              Text(
                'youtube.com/bappasaikh',
                style: TextStyle(fontSize: 25),
              ) ,
            ),
          ]),





        ]),


      ),


    );
  }
}