Skip to content

Commit

Permalink
updated with new token login options
Browse files Browse the repository at this point in the history
  • Loading branch information
aadamsx committed Jul 28, 2017
1 parent 9ba75fb commit b65dc2c
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 23 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,21 @@ If you have `accounts-password` in your app, and you want to be able to use it o

Make sure to serve your app over HTTPS if you are using this for login, otherwise people can hijack your passwords. Try the [`force-ssl` package](https://atmospherejs.com/meteor/force-ssl).

### POST /users/login, POST /users/register
### POST /users/login, POST /users/register, POST /users/token-login

The login and registration endpoints take the same inputs. Pass an object with the following properties:

- `username`
- `email`
- `password`
- `dbId`

`password` is required, and you must have at least one of `username` or `email`.
`password` is required, and you must have at least one of `username` or `email`. dbId is optional and for multi-database scenarios.

The token-login endpoint only requires a token and optionally a Database ID.

- `dbId`
- `loginToken`

#### Responses

Expand Down Expand Up @@ -321,6 +327,12 @@ JsonRoutes.add('get', 'handle-error', function () {

# Change Log

#### 2.0.0

- Added ability to log in with token at ```/users/token-login```.
- Pass in an optional Database ID for multi database scenarios to ```/users/login```.
- The log in option ```/users/login``` now has the option to pass in a Database ID for multi database scenarios.
- Use the setting.json file in your root project to specify your database ID.

#### 1.0.0 - 1.0.12

Expand Down
127 changes: 108 additions & 19 deletions json-routes.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* global JsonRoutes:true */
import Fiber from 'fibers';
import connect from 'connect';
import connectRoute from 'connect-route';

var Fiber = require('fibers');
var connect = require('connect');
var connectRoute = require('connect-route');
import { Mongo, MongoInternals } from 'meteor/mongo';

JsonRoutes = {};

Expand Down Expand Up @@ -131,16 +131,13 @@ JsonRoutes.Middleware.authenticateMeteorUserByToken =
* is invalid
*/
function getUserIdFromAuthToken(token) {
if (!token) {
return null;
}
if (!token) return null;

const user = Meteor.users.findOne({
'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken(token)
}, {fields: {_id: 1}});
if (user) {
return user._id;
}
const driver = new MongoInternals.RemoteCollectionDriver(Meteor.settings[dbId]); // must have the database URL in your settings.json file
const users = new Mongo.Collection("users", { _driver: driver, _suppressSameNameError: true });

const user = users.findOne({ 'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken(token) }, { fields: { _id: 1 } });
if (user) return user._id;

return null;
}
Expand Down Expand Up @@ -210,6 +207,7 @@ JsonRoutes.Middleware.use(JsonRoutes.Middleware.authenticateMeteorUserByToken);

// Handle errors specifically for the login routes correctly
JsonRoutes.ErrorMiddleware.use('/users/login', RestMiddleware.handleErrorAsJson);
JsonRoutes.ErrorMiddleware.use('/users/token-login', RestMiddleware.handleErrorAsJson);
JsonRoutes.ErrorMiddleware.use('/users/register', RestMiddleware.handleErrorAsJson);


Expand Down Expand Up @@ -284,19 +282,39 @@ JsonRoutes.add('options', '/users/login', (req, res) => {
JsonRoutes.add('post', '/users/login', (req, res) => {
const options = req.body;

var user;
if (options.hasOwnProperty('email')) {
let user;
if (options.hasOwnProperty('email') && options.hasOwnProperty('dbId')) {
check(options, {
email: String,
password: String,
dbId: String
});
user = Meteor.users.findOne({ 'emails.address': options.email });
} else {
const driver = new MongoInternals.RemoteCollectionDriver(Meteor.settings[dbId]); // must have the database URL in your settings.json file
const users = new Mongo.Collection("users", { _driver: driver, _suppressSameNameError: true });
user = users.findOne({ 'emails.address': options.email });
} else if (options.hasOwnProperty('username') && options.hasOwnProperty('dbId')) {
check(options, {
username: String,
password: String,
dbId: String
});
const driver = new MongoInternals.RemoteCollectionDriver(Meteor.settings[dbId]); // must have the database URL in your settings.json file
const users = new Mongo.Collection("users", { _driver: driver, _suppressSameNameError: true });
user = users.findOne({ username: options.username });
} else if (options.hasOwnProperty('email')) {
check(options, {
email: String,
password: String
});
user = Meteor.users.findOne({ username: options.username });
const users = new Mongo.Collection("users");
user = users.findOne({ 'emails.address': options.email });
} else if (options.hasOwnProperty('username')) {
check(options, {
username: String,
password: String
});
const users = new Mongo.Collection("users");
user = users.findOne({ username: options.username });
}

if (!user) {
Expand All @@ -320,7 +338,8 @@ JsonRoutes.add('post', '/users/login', (req, res) => {
when: Date,
});

Accounts._insertLoginToken(result.userId, stampedLoginToken);
const hashedToken = Accounts._hashStampedToken(stampedLoginToken);
users.update({ _id: result.userId }, { $addToSet: { "services.resume.loginTokens": hashedToken } });

const tokenExpiration = Accounts._tokenExpiration(stampedLoginToken.when);
check(tokenExpiration, Date);
Expand All @@ -335,6 +354,76 @@ JsonRoutes.add('post', '/users/login', (req, res) => {

});


JsonRoutes.add('options', '/users/token-login', (req, res) => {
JsonRoutes.sendResult(res);
});

JsonRoutes.add('post', '/users/token-login', (req, res) => {
const options = req.body;

let multiMode = true;
if (options.hasOwnProperty('dbId')) {
check(options, {
dbId: String,
loginToken: String
});
} else {
multiMode = false
check(options, {
loginToken: String
});
}

const dbId = options.dbId;
const loginToken = options.loginToken;

let users = null;
if (multiMode) {
const driver = new MongoInternals.RemoteCollectionDriver(Meteor.settings[dbId]); // must have the database URL in your settings.json file
users = new Mongo.Collection("users", { _driver: driver, _suppressSameNameError: true });
}
else {
users = new Mongo.Collection("users");
}
let user = users.findOne({ 'services.login.token': loginToken });

// No user, in the wrong, could be invalid userId or database, or event token.
if (!user) {
throw new Meteor.Error('not-found',
'User with that login token not found.');
}

// We have a valid user, now assign the id to a variable.
const userId = user._id;

// You're done with this one-time login token, now throw it away so it can't be used again.
users.update({ _id: userId }, { $unset: { 'services.login.token': '' } });

// Generate the stamped token and add it to the user collection
const stampedLoginToken = Accounts._generateStampedLoginToken();
check(stampedLoginToken, {
token: String,
when: Date,
});

const hashedToken = Accounts._hashStampedToken(stampedLoginToken);
users.update({ _id: userId }, { $addToSet: { "services.resume.loginTokens": hashedToken } });

const tokenExpiration = Accounts._tokenExpiration(stampedLoginToken.when);
check(tokenExpiration, Date);

JsonRoutes.sendResult(res, {
data: {
id: userId,
token: stampedLoginToken.token,
tokenExpires: tokenExpiration,
},
});

});


JsonRoutes.add('options', '/users/register', (req, res) => {
JsonRoutes.sendResult(res);
});
Expand Down
2 changes: 1 addition & 1 deletion package.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package.describe({
name: 'fine-rest',
version: '1.0.12',
version: '2.0.0',

// Brief, one-line summary of the package.
summary: 'A fine way to define server-side routes that return JSON',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fine-rest",
"version": "1.0.12",
"version": "2.0.0",
"license": "MIT",
"description": "Json Routing for Web API",
"main": "json-routes.js",
Expand Down

0 comments on commit b65dc2c

Please sign in to comment.