siegesmund / SwiftDDP

A Meteor client, written in Swift
MIT License
145 stars 60 forks source link

facebook login issue #73

Closed sayed19 closed 8 years ago

sayed19 commented 8 years ago

We have created a custom method to login with facebook. For the sever side, the method is working fine. New user is created on the server and server authenticates. It returns the user id and other credentials which we can see on the log. But there is an issue on the client side. From the client side when we call Meteor.client.userId() it returns nil. Not only that then we logout using Meteor.logout(). It does not execute. We assume some how client side doesn't get the user which is created on the server. How to over come this issue. Kindly response first.

siegesmund commented 8 years ago

You haven't said what are you doing on the client side to login.

To login with Facebook, you will need to follow this pattern. You should be able to follow the tutorial exactly on the server side; on the client side, you'll use the Facebook iOS SDK and pass the token via a method call.

zahedul commented 8 years ago

is there any method like loginWithToken ? code is like now

    extension LoginViewController: LoginButtonDelegate {
        func loginButtonDidCompleteLogin(loginButton: LoginButton, result: LoginResult) {
        switch result {
        case .Failed(let error):
            print(error)
        case .Cancelled:
            print("User cancelled login.")
        case .Success(let grantedPermissions, _, let accessToken):

            let accountData = [
                "email" : "",
                "userId": accessToken.userId!,
                "accessToken" : accessToken.authenticationToken,
                "facebookLoginPlugin" : true
            ]

            Meteor.call("login", params: [accountData])  { result, error in
                if  error != nil {
                    SCLAlertView().showError("\(result)", subTitle: "Failed")
                } else {
                    print(result); 
                    print(Meteor.client.userId())
                }
            }
        }
    }
    }

in result get from server ...

Optional({
    id = Sqrp3o3qA9Ph8gZXT;
    token = "4ClVKZLDN_4SEBXHn2aeRbLTMdHFOcRv-ve3WZZaER4";
    tokenExpires =     {
        "$date" = 1482237409970;
    };
})

server code is

Accounts.registerLoginHandler(function(request) {
    logger.info('platform', 'third party login request');
    logger.debug('platform',request);
    if (request.facebookLoginPlugin) {
        try {
            logger.info('platform', 'a request from android facebook');

            var user = Meteor.users.findOne({ "emails.address": request.email }),
                userId = null,
                serviceResponse = {},
                profileData = {},
                apiResponse,
                apiResponseToken;

            //  First frame the insertObject for google or linkedin
            if (request.facebookLoginPlugin) {

                apiResponse = Meteor.http.get("https://graph.facebook.com/me", {
                    params: {
                        access_token: request.accessToken,
                        fields: ['id', 'email', 'name', 'first_name', 'last_name', 'link', 'gender', 'locale', 'age_range']
                    }
                });

                logger.info('platform', 'response from facebook');
                logger.debug('platform', apiResponseToken);

                if (apiResponse.error) {
                    throw apiResponse.error;
                } else {
                    apiResponse["accessToken"] = request.accessToken;
                    apiResponseToken = Meteor.http.get("https://graph.facebook.com/oauth/access_token_info", {
                        params: {
                            access_token: request.accessToken,
                            client_id: Meteor.settings.FACEBOOK.appId
                        }
                    });

                    logger.info('platform', 'apiResponseToken from facebook');
                    logger.debug('platform', apiResponse);

                    apiResponse["accessToken"] = parseInt((+new Date)) + parseInt(1000 * apiResponseToken.expires_in);

                    serviceResponse = {
                        facebook: apiResponse
                    };
                    profileData = {
                        name: apiResponse.data.name
                    };
                }
            }
            if (request.email === "") {
                user = Meteor.users.findOne({ "emails.address": apiResponse.data.email });
                request.email = apiResponse.data.email;
            }
            if (!user) {
                logger.info('platform', 'new user request sign-up from android');
                var newUser = {
                    services: serviceResponse,
                    emails: [{
                        address: request.email,
                        verified: false
                    }],
                    profile: profileData,
                    roles: ['customer']
                };

                logger.debug('platfrom', newUser);
                userId = Meteor.users.insert(newUser);
                if (userId) {
                    logger.info('platform', 'new user id: ' + userId);
                }
            } else {
                userId = user._id;

                var updateQuery = {};
                if (request.facebookLoginPlugin) {
                    updateQuery = {
                        'services.facebook': serviceResponse.facebook
                    };
                }

                Meteor.users.update({
                    _id: userId
                }, {
                    $set: updateQuery
                });
            }

            var stampedToken = Accounts._generateStampedLoginToken();
            var stampedTokenHash = Accounts._hashStampedToken(stampedToken);

            Meteor.users.update({
                _id: userId
            }, {
                $push: {
                    "services.resume.loginTokens": stampedTokenHash
                }
            });

            return {
                token: stampedToken.token,
                userId: userId
            };
        } catch (e) {
            logger.error('platform', e.reason);
            logger.debug('platform', e.stack);
            throw new Meteor.Error(e.error, e.reason);
        }
    }
});

in android-ddp it works. check the issue there104

siegesmund commented 8 years ago

You can call any Meteor server method with Meteor.call. A hypothetical "loginWithToken" would be nothing but a thin wrapper around Meteor.call. In other words, you implement this yourself.

zahedul commented 8 years ago

Hi, In my upper example we are successful to login in server. But In client side user object do not update. If I'm not wrong, following code store login user information.

self.userData.setObject(id, forKey: DDP_ID)
self.userData.setObject(token, forKey: DDP_TOKEN)
self.userData.setObject(expiration, forKey: DDP_TOKEN_EXPIRES)
self.userData.synchronize()

Now I need to update login user object in client side. Will you please help me to do that .

thanks