Any Flutter Package that fetchs GoogleCredential Access Token

305 Views Asked by At

In Flutter(Dart) is there any package to get GoogleCredential Accesstoken (This below sample is for getting Access Token in Java)

private static String getAccessToken() throws IOException {
  GoogleCredential googleCredential = GoogleCredential
      .fromStream(new FileInputStream("service-account.json"))
      .createScoped(Arrays.asList(SCOPES));
  googleCredential.refreshToken();
  return googleCredential.getAccessToken();
}

I need it to modify firebase remote config.

2

There are 2 best solutions below

0
On

If you are searching for identity provider by google this may help you https://pub.dartlang.org/packages/google_sign_in

0
On

You can use this library to do that:

https://pub.dev/packages/googleapis_auth

Or you can use this one (as they recommend):

https://pub.dev/packages/extension_google_sign_in_as_googleapis_auth

import "package:googleapis_auth/auth_io.dart";


// Use service account credentials to get an authenticated and auto refreshing client.
Future<AuthClient> obtainAuthenticatedClient() async {
  final accountCredentials = ServiceAccountCredentials.fromJson({
    "private_key_id": "<please fill in>",
    "private_key": "<please fill in>",
    "client_email": "<please fill in>@developer.gserviceaccount.com",
    "client_id": "<please fill in>.apps.googleusercontent.com",
    "type": "service_account"
  });
  var scopes = ["https://www.googleapis.com/auth/firebase.messaging"];

  AuthClient client = await clientViaServiceAccount(accountCredentials, scopes);

  return client; // Remember to close the client when you are finished with it.
}

I created this class to handle it, using the recommended library.

class Messaging {
  // region Singleton
  static final Messaging _instance = Messaging._internal();

  Messaging._internal();

  static Messaging get instance => _instance;

//endregion

  static final String projectId = '<your-project-id>';
  static final String fcmUri =
      'https://fcm.googleapis.com/v1/projects/$projectId/messages:send';
  static final String messagingScope =
      'https://www.googleapis.com/auth/firebase.messaging';

  /// Credentials used to authenticate the http calls.
  /// If it is null, at the first time, it will be created.
  /// After that, we will check if the access token is valid.
  /// If it is expired, we are going to refresh it.
  /// We also need the client to refresh the token.
  AccessCredentials? _credentials;

  FirebaseMessaging get fcmInstance => FirebaseMessaging.instance;

  /// Sends a message to a topic or specific device
  /// [topic] might be a topic itself or a registered fcm token (the device token)
  Future<String> sendMessage({
    required String title,
    required String message,
    required String topic,
  }) async {
    Map<String, dynamic> notification = Map();
    notification['title'] = title;
    notification['body'] = message;

    Map<String, dynamic> body = Map();
    body["message"] = {
      'topic': topic,
      'notification': notification,
    };

    return _post(body);
  }

  /// Send data to the informed destionation
  /// [data] must have a maximum 3kb
  Future<String> sendData({
    required String topic,
    required Map<String, String> data,
  }) async {
    debugPrint('Send data to topic $topic: ');

    Map<String, dynamic> body = Map();
    body['message'] = {
      'topic': topic,
      'data': data,
    };

    return _post(body);
  }

  /// Posts the message
  Future<String> _post(Map<String, dynamic> body) async {
    Map<String, String> headers = await _buildHeaders();
    return http
        .post(
      Uri.parse(fcmUri),
      headers: headers,
      body: json.encode(body),
    )
        .then((http.Response response) {
      debugPrint(response.body);
      return response.body;
    });
  }

  /// Builds default header
  Future<Map<String, String>> _buildHeaders() async {
    await _autoRefreshCredentialsInitialize();
    String token = _credentials!.accessToken.data;
    Map<String, String> headers = Map();
    headers["Authorization"] = 'Bearer $token';
    headers["Content-Type"] = 'application/json';
    return headers;
  }

  /// Use service account credentials to obtain oauth credentials.
  /// Whenever new credentials are available, [_credentials] is updated automatically
  Future<void> _autoRefreshCredentialsInitialize() async {
    if (_credentials != null) {
      return;
    }

    // [Assets.files.serviceAccount] is the path to the json created on Services Account
    // Assets is a class that I created to access easily files on assets folder.
    String source = await Assets.readString(Assets.files.serviceAccount);
    final serviceAccount = jsonDecode(source);
    var accountCredentials = ServiceAccountCredentials.fromJson(serviceAccount);

    AutoRefreshingAuthClient autoRefreshingAuthClient =
        await clientViaServiceAccount(
      accountCredentials,
      [messagingScope],
    );

    /// initialization
    _credentials = autoRefreshingAuthClient.credentials;

    // when new credetials are available, _credentials will be updated
    // (it checks if the current credentials is expired)
    autoRefreshingAuthClient.credentialUpdates.listen((credentials) {
      _credentials = credentials;
    });
  }

  //region Registered Token

  Future<void> requestMessagingToken() async {
    // Get the token each time the application loads
    String? token = await fcmInstance.getToken();

    // Save the initial token to the database
    await _saveTokenToSharedPreference(token!);

    // Any time the token refreshes, store this in the database too.
    fcmInstance.onTokenRefresh.listen(_saveTokenToSharedPreference);
  }

  /// Verifica a necessidade de persistir o token
  Future<void> _saveTokenToSharedPreference(String token) async {
    FlutterSecureStorage prefs = FlutterSecureStorage();

    // verifica se é igual ao anterior
    String? prev = await prefs.read(key: 'tokenMessaging');

    if (prev == token) {
      debugPrint('Device registered!');
      return;
    }

    try {
      await prefs.write(key: "tokenMessaging", value: token);
      debugPrint('Firebase token saved!');
    } catch (e) {
      FirebaseCrashlytics.instance.recordError(e, null);
      print(e);
    }
  }

  Future<String?> get firebaseToken {
    FlutterSecureStorage prefs = FlutterSecureStorage();
    return prefs.read(key: 'tokenMessaging');
  }

//endregion
}