Log in to a meteor app from a Google chrome extens

2020-08-01 02:46发布

I have a meteor app that uses restop2 package to allow posting data.

The restop2 package provides a way to log in by sending user / password to a specific URL :

curl --data "password=PASSWORD&user=USERNAME" http://localhost:3000/api/login/

It returns a JSON response containing a user ID and an access token :

{"loginToken":"TOKEN","userId":"USERID","success":true}

I can then post to the api by sending the user ID and the access token in the header :

curl -X POST -H "X-Login-Token: TOKEN" -H "X-User-Id: USERID" -H "Content-Type: application/json" -d '{"title":"My title","content":"My content"}' http://localhost:3000/api/clip/add

So far, so good.

Now I'd like to log into my app from a Google extension. How can I do this ? Should I simply implement a login form in the extension's popup, post the data to my web site over HTTPS and use the returned token in subsequent requests ? And where should I store this token ?

1条回答
混吃等死
2楼-- · 2020-08-01 03:29

After some digging, here is how I achieved this :

When making an XHR request to a remote URL from a Chrome extension, cookies from the domain are sent along with the request.

Unfortunately, Meteor uses local storage instead of cookies to store user id and token.

So the first thing to do is to add a way to identify a user using cookies. I used the technique described in Access Meteor.userId from outside a method/publish and modified it a little.

Since we will use cookies, we don't need restop2 and its authentication process anymore; we will retrieve login token directly from the cookies.

First, set cookies when user authenticates :

if (Meteor.isClient) {
  Deps.autorun(function() {
    if(Accounts.loginServicesConfigured() && Meteor.userId()) {
        setCookie("meteor_userid", Meteor.userId(),30);
        setCookie("meteor_logintoken", localStorage.getItem("Meteor.loginToken"),30);
    }
  });
}

Then, add a route as your endpoint where the user will be retrieved from the cookies. I found out that the login token needs to be hashed before being used in the query :

this.route('extension', {
  path: '/extension/post',
  where: 'server',
  action: function() {
    var userId = get_cookies(this.request)['meteor_userid'];
    var loginToken = get_cookies(this.request)['meteor_logintoken'];
    var user = Meteor.users.findOne({_id:userId, "services.resume.loginTokens.hashedToken":Accounts._hashLoginToken(loginToken)});

    if (user) {
      var doc = this.request.body; // You should do some sanitization here...
      Clips.insert(doc);
    }
  }
});

Then, the extension :

First, ensure you have set the correct permissions in manifest.json :

"permissions": [
  "http://localhost:3000/"
],

Finally, send the request in popup.js :

var data = {...};
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:3000/extension/post", true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify(data));

And voilà !

查看更多
登录 后发表回答