Search code examples
facebook-graph-apimeteorfacebook-oauth

How can I get the credential secret in Meteor, when I do Facebook.requestCredential on the client?


I'm trying to implement a login/link account system like the one in this question.
(scroll down to where it says "Methods for explicit associations")

You used to be able to get the user's login data with something like this:
data = Package.facebook.Facebook.retrieveCredential(token).serviceData

Now it looks like this retrieveCredential(token, secret).
Here's the commit where that happened.

I for the life of me can't figure out how to get the credential secret on the server after I call:

Package.facebook.Facebook.requestCredential(
    requestPermissions: Accounts.ui._options.requestPermissions["facebook"]
, (token) ->
    Meteor.call "userAddOauthCredentials", token, Meteor.userId(), service, (err, resp) ->
        if err?
            Meteor.userError.throwError(err.reason)
)

Solution

  • Turns out you can do it like this at the moment (on the client):

    service = "facebook"
    Package.facebook.Facebook.requestCredential(
        requestPermissions: Accounts.ui._options.requestPermissions["facebook"]
    , (token) ->
        secret = Package.oauth.OAuth._retrieveCredentialSecret(token)
        Meteor.call "userAddOauthCredentials", token, secret, service, (err, resp) ->
            if err?
                Meteor.userError.throwError(err.reason)
    )
    

    Then on the server you'll need the secret to access the service data for the user.

    userAddOAuthCredentials: (token, secret, service) ->
        services = Meteor.user().services
        serviceSearch = {}
        data = {}
        switch service
            when "facebook"
                if not services.facebook?
                    data = Package.facebook.Facebook.retrieveCredential(token, secret)?.serviceData
                    services.facebook = data
                    serviceSearch = {"services.facebook.id": services.facebook.id}
                else
                    throw new Meteor.Error(500, "You already have a linked Facebook account with email #{services.facebook.email}...")
        oldUser = Meteor.users.findOne(serviceSearch)
        if oldUser?
            throw new Meteor.Error(500, "Your #{service} account has already been assigned to another user.")
    
        Meteor.users.update(@userId, {$set: {services: services}})
        if data.email?
            if not _.contains(Meteor.user().emails, data.email)
                Meteor.users.update(@userId, {$push: {"emails": {address: data.email, verified: true}}})
    

    Those functions will get you the user's service data so you can link multiple accounts, or do whatever you want with them.