idanwe / accounts-password-client-side

Use Meteor's accounts-password package with meteor-client-side.
MIT License
13 stars 10 forks source link

accounts-twitter-client-side #2

Open v-marcel opened 8 years ago

v-marcel commented 8 years ago

How would this be done for the other accounts packages? is it possible?

idanwe commented 8 years ago

Yes it is, you will need to create bundle of the client side of the package.

I already done it with meteor-client-side, angular-meteor, accounts-base, accounts-password and accounts-phone.

I'm using at the moment a bash script take a look at and change the names and the scripts the need to be concat accounts-password / accounts-phone / agular-meteor.

Inform me if you need further help

dinesh36 commented 8 years ago

@idanwe I have the same issue as @v-marcel , I want to use facebook login of meteor.

Can you create plugin for the facebook and twitter or can you explain how can we create the bower for that ?

idanwe commented 8 years ago

@dinesh36 @v-marcel I will glad to explain how to bundle the packages:

The process of creating the bundled files is describe at bundle-min.sh with bash commands and comments. The same bash script is applied to all packages with a different concatenation of files.

I'm using at the moment a bash script take a look at and change the names and the scripts the need to be concat accounts-password / accounts-phone / agular-meteor.

Copy this repo and change the package name and the required files at bundle-min.sh In order to figure out what are the needed files:

  1. Look at the dependencies at atmospherejs.com
  2. Comment this line and enter to bundle/programs/web.browser/packages to see the packages that downloaded.
  3. Require the bundled file that you created to some meteor-client-side project ionic-whatsapp / meetup-NY-ionic-chat

Hope it helps

mixersoft commented 8 years ago

Hello, I'm trying to build an accounts-facebook-client-side.bundle.js but having problems. I have used the following for dependencies

cat "$PACKAGES_PATH/reactive-var.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/observe-sequence.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/htmljs.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/jquery.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/blaze.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/spacebars.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/templating.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/url.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/reload.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/oauth.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/accounts-oauth.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/facebook.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/accounts-facebook.js" >> $OUTPUT_PATH/$NAME.bundle.js
cat "$PACKAGES_PATH/global-imports.js" >> $OUTPUT_PATH/$NAME.bundle.js

and built the script as directed. However, I'm getting the following error:

errorType: "Accounts.LoginCancelledError"
message: "No matching login attempt found"

It seems to get stuck on the redirect URL. I have added the following static files to my project:

www/_oath/facebook/index.html
www/_oath/facebook/end_of_popup_response.js

But the credentialToken and credentialSecret are never set by the oauth redirect. see http://stackoverflow.com/questions/37114997/how-does-the-meteor-accounts-oauth-workflow-happen

mixersoft commented 8 years ago

I think all the action happens on the Meteor.isServer side. I need to somehow set the oauth redirectUrl to point to my meteor server, currently http://localhost:3333/_oauth/facebook, to get something like this:

<div id="config" style="display:none;">{
"setCredentialToken":true,
"credentialToken":"bsgEZrFbK-UruR1iX81dEitIR0t5nC_a1HM4-EGSGx5",
"credentialSecret":"hi8rJxbyOsI0gVaoIHrr7N9kH9k2Fku1DYQXP5BmQMt",
"storagePrefix":"Meteor.oauth.credentialSecret-",
"isCordova":false
}</div>

BUT, I am guessing if I do that, I won't be able to read these values from localstorage(?) on my web.browser client page (port 3000)

any ideas for a workaround?

mixersoft commented 8 years ago

I figured it out, but my solution is not very pretty...

I created a "proxy service" to on the client to get load oauth redirect_uri from the Meteor server(running on port=3333) and grab the oauth credentials.

file=./_oauth/facebook/index.html

<!DOCTYPE html>
<html>
  <head>
    <script src="/lib/ionic/js/ionic.bundle.js"> // load angular first</script>
    <script src="./proxy.js"></script>
  </head>
  <body ng-app="oauth">
    <p id="completedText" style="display:none;"><span>Login completed. &nbsp;</span><a id="loginCompleted" href="#">Click here</a><span>&nbsp; to close this window.</span></p>
    <div id="config" style="display:none;"></div>
  </body>
</html>

and file= ./_oauth/facebook/proxy.js

(function() {
  'use strict';
  var OauthProxy, appRun;

  angular.module('oauth', ['ionic']);

  OauthProxy = function($http) {
    var config, self;
    config = {
      rootUrl: 'http://localhost:3333',
      path: location.pathname
    };
    self = {
      get: function(options) {
        var url;
        if (options == null) {
          options = {};
        }
        options = angular.copy(config, options);
        url = [options.rootUrl, options.path, location.search].join('');
        console.log('proxy=' + url);
        return $http.get(url);
      },
      doOauthRedirect: function(config) {
        var credentialSecret, credentialString, credentialToken, err, error;
        if (config.setCredentialToken) {
          credentialToken = config.credentialToken;
          credentialSecret = config.credentialSecret;
          if (config.isCordova) {
            credentialString = JSON.stringify({
              credentialToken: credentialToken,
              credentialSecret: credentialSecret
            });
            window.location.hash = credentialString;
          }
          if (window.opener && window.opener.Package && window.opener.Package.oauth) {
            window.opener.Package.oauth.OAuth._handleCredentialSecret(credentialToken, credentialSecret);
          } else {
            try {
              localStorage[config.storagePrefix + credentialToken] = credentialSecret;
            } catch (error) {
              err = error;
              angular.noop;
            }
          }
        }
        if (!config.isCordova) {
          document.getElementById("completedText").style.display = "block";
          document.getElementById("loginCompleted").onclick = function() {
            return window.close();
          };
          window.close();
        }
      }
    };
    return self;
  };

  OauthProxy.$inject = ['$http'];

  appRun = function(oauthProxy) {
    console.log('href=' + window.location.href);
    return oauthProxy.get().then(function(result) {
      var credentials;
      if (result.status !== 200) {
        return console.warn(['Status', result.status]);
      }
      credentials = result.data.match(/({.*})/).pop();
      return credentials;
    }, function(err) {
      return console.warn(err);
    }).then(function(credentials) {
      var config;
      document.getElementById("config").innerHTML = credentials;
      config = JSON.parse(credentials);
      console.log('config=' + credentials);
      return oauthProxy.doOauthRedirect(config);
    });
  };

  appRun.$inject = ['oauthProxy'];

  angular.module('oauth').factory('oauthProxy', OauthProxy).run(appRun);

}).call(this);

But to make this work, I had to add 2 hacks to the Meteor.server

  1. fix CORS on server by adding "Access-Control-Allow-Origin" to the ./_oauth page, and
  2. fix the oauth security violation by manually setting the redirect_uri on the Meteor server to the same value as used by the client

file=server/server/bootstrap.js

// meteor: add package webapp
WebApp.rawConnectHandlers.use("/_oauth", function(req, res, next) {
      res.setHeader("Access-Control-Allow-Origin", "*");
      return next();
    });

file=server/.meteor/local/build/programs/server/packages/facebook.js

// line 79, client uses port=3000, Meteor server uses port=3333
responseContent = HTTP.get(
      "https://graph.facebook.com/v2.2/oauth/access_token", {
        params: {
          client_id: config.appId,
          redirect_uri: OAuth._redirectUri('facebook', config,null,{rootUrl:'http://localhost:3000/'})),
          client_secret: OAuth.openSecret(config.secret),
          code: query.code
        }
      }).content;

BUT, to make the Meteor server changes persist I had to find the code and make changes in .meteor/local/bundler-cache/linker

There must be a better way, right?