Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor RESTful Authentication. Is it possible?

I have searched around but cant find an a satisfactory answer to this question.

I have a meteor website where users login and create content. I also want to create a phone app, that is capable of interacting with the website, and I want the users to log into the phone app and access the same content on the website. Pretty normal.

I have created a basic REST API for accessing the collections using the meteorite package HTTP.publish. It is working without any user info (no auth), but now I want to use the the userId of the GET methods and in the Meteor.allow rules of the collections to access the current user.

So I am currently struggling with how to tell meteor on a REST request, the id of the user, even while just testing. I thought I could get the Accounts._storedLoginToken of a valid user in the browser and use that to test with CURL. Something like

curl -H "X-Auth-Token: asdklfjasldfjlsadkjf" -H "Content-Type: application/json" -d '{"name":"A Name","description":"Testing description"}' http://localhost:3000/api/places

I tried this, but no joy, I get a 403 which is good at least.

My questions are this:

  • Are the tokens created specific to the client (ie hashed with host url or something)?
  • Has bcrypt change the way X-Auth-Token is used? If not what am I doing wrong in the curl command.
  • Is DDP the ONLY way to create valid tokens or can I create a API call that will create a token on the server, even just passing plain text credentials for now?

eg /api/login?user=shane&pwd=qwerty => return token I can use in curl request.

I am really stuck with this so anything pointing me in the right direction would be appreciated. I also note the http.publish has not yet created the login/logout methods, so maybe it's not that easy.

like image 636
Shane Avatar asked Jul 06 '14 14:07

Shane


3 Answers

A few days ago I started on an app with similar requirements regarding authentication. I found that Differential's RESTstop2 recently, in version 0.6.0, upgraded their authentication support to support the newly added Bcrypt encryption in Meteor.

You simply send username and password either as URL params or body like this:

curl --data "password=testpassword&user=test" http://localhost:3000/api/login/

and the server will return the following (if credentials are correct):

{ success: true, loginToken: "f2KpRW7KeN9aPmjSZ", userId: fbdpsNf4oHiX79vMJ }

On each request you make to the server, include the loginToken and userId as headers.

You should check it out:

Docs: http://github.differential.io/reststop2/

Github: https://github.com/Differential/reststop2

like image 181
AndreasB Avatar answered Oct 10 '22 08:10

AndreasB


Another option (besides RESTstop2 mentioned in other answer), you can use stand-alone api-password package from Atmosphere, which does exactly what you need: authenticate REST calls on the server side. It supports Meteor 0.8.2 (with bcrypt) as well.

Example for the server side

  try {
    if (ApiPassword.isPasswordValid(username, password)) {
      console.log('password is valid for this user');
    } else {
      console.log('password is not valid');
    }

  } catch (exc) {
      console.log(exc.message);
      // possible causes: 'User is not found', 'User has no password set'
  }
like image 36
Andrei Karpushonak Avatar answered Oct 10 '22 06:10

Andrei Karpushonak


I published a package for writing REST APIs in Meteor 0.9.0+ that supports authentication. It is meant to replace RestStop2 (the accepted answer) now that it is deprecated, and has a similar API:

https://github.com/krose72205/meteor-restivus

It was inspired by RestStop2 and built with Iron Router's server-side routing.

UPDATE: I just wanted to include a code example for anyone that finds this. This is the Restivus Quick Start example from the GitHub README:

Items = new Mongo.Collection 'items'

if Meteor.isServer

  # API must be configured and built after startup!
  Meteor.startup ->

    # Global API configuration
    Restivus.configure
      useAuth: true
      prettyJson: true

    # Generates: GET, POST, DELETE on /api/items and GET, PUT, DELETE on
    # /api/items/:id for Items collection
    Restivus.addCollection Items

    # Generates: GET, POST on /api/users and GET, DELETE /api/users/:id for
    # Meteor.users collection
    Restivus.addCollection Meteor.users,
      excludedEndpoints: ['deleteAll', 'put']
      routeOptions:
        authRequired: true
      endpoints:
        post:
          authRequired: false
        delete:
          roleRequired: 'admin'

    # Maps to: /api/posts/:id
    Restivus.addRoute 'posts/:id', authRequired: true,
      get: ->
        post = Posts.findOne @urlParams.id
        if post
          status: 'success', data: post
        else
          statusCode: 404
          body: status: 'fail', message: 'Post not found'
      post:
        roleRequired: ['author', 'admin']
        action: ->
          post = Posts.findOne @urlParams.id
          if post
            status: "success", data: post
          else
            statusCode: 400
            body: status: "fail", message: "Unable to add post"
      delete:
        roleRequired: 'admin'
        action: ->
          if Posts.remove @urlParams.id
            status: "success", data: message: "Item removed"
          else
            statusCode: 404
            body: status: "fail", message: "Item not found"
like image 32
kahmali Avatar answered Oct 10 '22 08:10

kahmali