Closed ivriets closed 2 years ago
Two parts have to be implemented.
An extension to MeteorClient
Backend (meteor side) to handle Google sign-in
accounts_google.dart
import 'package:dart_meteor/dart_meteor.dart';
extension AccountsGoogle on MeteorClient {
Future
In the UI together with `google_sign_in` package.
void signInWithGoogle(BuildContext context) async {
setState(() {
_isProcessing = true;
});
try {
var googleSignIn = GoogleSignIn(
scopes:
2. Here is some example of the meteor side code. Use it with care.
import { Accounts } from 'meteor/accounts-base'; import { Log } from 'meteor/logging';
const ERROR_MESSAGE = 'Something went wrong while doing sign-in with Google.';
const createUser = (userData) => { const { username, email } = userData; if (!username && !email) { throw new Meteor.Error(400, 'Need to set a username or email'); } const user = { services: {} }; return Accounts._createUserCheckingDuplicates({ user, username, email, options: userData, }); };
Accounts.registerLoginHandler('googleFlutter', function (options) { if (options.googleFlutter) { Log.info('Login with googleFlutter'); Log.info(this.connection); // console.log('Login with googleFlutter'); const { authHeaders } = options.googleFlutter;
if (!authHeaders) {
Log.error('Login with googleFlutter but no authHeaders was provided!');
throw new Meteor.Error(403, ERROR_MESSAGE);
}
const bearerToken = authHeaders.Authorization;
let res = null;
try {
res = HTTP.get('https://people.googleapis.com/v1/people/me/', {
headers: {
Authorization: bearerToken,
},
params: {
personFields: 'names,emailAddresses,photos',
},
});
} catch (err) {
Log.error(JSON.stringify(err));
throw new Meteor.Error(403, ERROR_MESSAGE);
}
if (res && res.statusCode === 200 && res.data) {
let email;
let firstName;
let lastName;
let profilePictureUrl;
let profilePictureThumbnailUrl;
let etag;
let resourceName;
if (
res.data.emailAddresses &&
res.data.emailAddresses instanceof Array &&
res.data.emailAddresses.length > 0
) {
email = res.data.emailAddresses[0].value;
}
if (
res.data.names &&
res.data.names instanceof Array &&
res.data.names.length > 0
) {
firstName = res.data.names[0].givenName;
lastName = res.data.names[0].familyName;
}
if (
res.data.photos &&
res.data.photos instanceof Array &&
res.data.photos.length > 0
) {
profilePictureUrl = res.data.photos[0].url;
if (profilePictureUrl) {
profilePictureUrl = profilePictureUrl.replace('=s100', '');
}
profilePictureThumbnailUrl = res.data.photos[0].url;
}
if (res.data.resourceName) {
resourceName = res.data.resourceName;
}
if (res.data.etag) {
etag = res.data.etag;
}
// console.log(email, firstName, lastName, profilePictureUrl, profilePictureThumbnailUrl, resourceName, etag);
if (email && firstName && lastName) {
let user = Accounts._findUserByQuery(
{
email: email,
},
{
fields: { emails: 1 },
}
);
if (
!user &&
(options.userCreationDisabled ||
Accounts._options.forbidClientAccountCreation)
) {
Accounts._handleError('User not found');
}
if (!user) {
Log.info(`Creating new user from Google account: ${email}`);
const userId = createUser({
email: email,
profile: {
prefix: {
local: '',
en: '',
},
firstName: {
local: firstName,
en: firstName,
},
lastName: {
local: lastName,
en: lastName,
},
profilePictureUrl: profilePictureUrl,
profilePictureThumbnailUrl: profilePictureThumbnailUrl,
},
});
user = Accounts._findUserByQuery(
{ id: userId },
{
fields: { emails: 1 },
}
);
}
if (!user) {
Log.info(`User could not be created: ${email}`);
Accounts._handleError('User could not be created');
}
Meteor.users.update(user._id, {
$set: {
'services.googleFlutter': {
createdAt: new Date(),
resourceName: resourceName,
etag: etag,
},
'profile.profilePictureUrl': profilePictureUrl,
'profile.profilePictureThumbnailUrl': profilePictureThumbnailUrl,
},
});
try {
Meteor.users.update(
{
_id: user._id,
'emails.address': email,
},
{
$set: {
'emails.$.verified': true,
},
}
);
} catch (error) {
Log.error(JSON.stringify(error));
throw new Meteor.Error(403, ERROR_MESSAGE);
}
Log.info(`Login with googleFlutter successed for ${email}`);
return {
userId: user._id,
};
}
}
throw new Meteor.Error(403, ERROR_MESSAGE);
} });
The server-side code inspired by https://gist.github.com/wendellrocha/794b2154bb18ce2b81b21c5da79cc76e
Thank you for response, I'll try to implemented to my apps,
I got an error on "await secureTokenWithPinCode(result.token);" is this default void from package? If yes which package or should I write own void? @tanutapi
I can't find any docs how to use loginWithGoogle, is it any tips to make this work, Thank you