Adds session creation code in Auth.js (#4574)

This commit is contained in:
Florent Vilmart
2018-02-19 11:15:54 -05:00
committed by GitHub
parent b754d51e8e
commit 11c40dce97
5 changed files with 81 additions and 80 deletions

View File

@@ -1,5 +1,6 @@
var Parse = require('parse/node').Parse; const cryptoUtils = require('./cryptoUtils');
var RestQuery = require('./RestQuery'); const RestQuery = require('./RestQuery');
const Parse = require('parse/node');
// An Auth object tells you who is requesting something and whether // An Auth object tells you who is requesting something and whether
// the master key was used. // the master key was used.
@@ -212,11 +213,46 @@ Auth.prototype._getAllRolesNamesForRoleIds = function(roleIDs, names = [], queri
}) })
} }
const createSession = function(config, {
userId,
createdWith,
installationId,
additionalSessionData,
}) {
const token = 'r:' + cryptoUtils.newToken();
const expiresAt = config.generateSessionExpiresAt();
const sessionData = {
sessionToken: token,
user: {
__type: 'Pointer',
className: '_User',
objectId: userId
},
createdWith,
restricted: false,
expiresAt: Parse._encode(expiresAt)
};
if (installationId) {
sessionData.installationId = installationId
}
Object.assign(sessionData, additionalSessionData);
// We need to import RestWrite at this point for the cyclic dependency it has to it
const RestWrite = require('./RestWrite');
return {
sessionData,
createSession: () => new RestWrite(config, master(config), '_Session', null, sessionData).execute()
}
}
module.exports = { module.exports = {
Auth, Auth,
master, master,
nobody, nobody,
readOnly, readOnly,
getAuthForSessionToken, getAuthForSessionToken,
getAuthForLegacySessionToken getAuthForLegacySessionToken,
createSession,
}; };

View File

@@ -511,7 +511,7 @@ class DatabaseController {
addRelation(key: string, fromClassName: string, fromId: string, toId: string) { addRelation(key: string, fromClassName: string, fromId: string, toId: string) {
const doc = { const doc = {
relatedId: toId, relatedId: toId,
owningId : fromId owningId: fromId
}; };
return this.adapter.upsertOneObject(`_Join:${key}:${fromClassName}`, relationSchema, doc, doc); return this.adapter.upsertOneObject(`_Join:${key}:${fromClassName}`, relationSchema, doc, doc);
} }
@@ -658,7 +658,7 @@ class DatabaseController {
// Returns a promise for a list of owning ids given some related ids. // Returns a promise for a list of owning ids given some related ids.
// className here is the owning className. // className here is the owning className.
owningIds(className: string, key: string, relatedIds: string): Promise<string[]> { owningIds(className: string, key: string, relatedIds: string[]): Promise<string[]> {
return this.adapter.find(joinTableName(className, key), relationSchema, { relatedId: { '$in': relatedIds } }, {}) return this.adapter.find(joinTableName(className, key), relationSchema, { relatedId: { '$in': relatedIds } }, {})
.then(results => results.map(result => result.owningId)); .then(results => results.map(result => result.owningId));
} }

View File

@@ -5,7 +5,7 @@
var SchemaController = require('./Controllers/SchemaController'); var SchemaController = require('./Controllers/SchemaController');
var deepcopy = require('deepcopy'); var deepcopy = require('deepcopy');
var Auth = require('./Auth'); const Auth = require('./Auth');
var cryptoUtils = require('./cryptoUtils'); var cryptoUtils = require('./cryptoUtils');
var passwordCrypto = require('./password'); var passwordCrypto = require('./password');
var Parse = require('parse/node'); var Parse = require('parse/node');
@@ -568,29 +568,24 @@ RestWrite.prototype.createSessionToken = function() {
if (this.auth.installationId && this.auth.installationId === 'cloud') { if (this.auth.installationId && this.auth.installationId === 'cloud') {
return; return;
} }
var token = 'r:' + cryptoUtils.newToken();
var expiresAt = this.config.generateSessionExpiresAt(); const {
var sessionData = { sessionData,
sessionToken: token, createSession,
user: { } = Auth.createSession(this.config, {
__type: 'Pointer', userId: this.objectId(),
className: '_User',
objectId: this.objectId()
},
createdWith: { createdWith: {
'action': this.storage['authProvider'] ? 'login' : 'signup', 'action': this.storage['authProvider'] ? 'login' : 'signup',
'authProvider': this.storage['authProvider'] || 'password' 'authProvider': this.storage['authProvider'] || 'password'
}, },
restricted: false,
installationId: this.auth.installationId, installationId: this.auth.installationId,
expiresAt: Parse._encode(expiresAt) });
};
if (this.response && this.response.response) { if (this.response && this.response.response) {
this.response.response.sessionToken = token; this.response.response.sessionToken = sessionData.sessionToken;
} }
return new RestWrite(this.config, Auth.master(this.config), '_Session', null, sessionData).execute(); return createSession();
} }
RestWrite.prototype.destroyDuplicatedSessions = function() { RestWrite.prototype.destroyDuplicatedSessions = function() {
@@ -675,29 +670,23 @@ RestWrite.prototype.handleSession = function() {
} }
if (!this.query && !this.auth.isMaster) { if (!this.query && !this.auth.isMaster) {
var token = 'r:' + cryptoUtils.newToken(); const additionalSessionData = {};
var expiresAt = this.config.generateSessionExpiresAt();
var sessionData = {
sessionToken: token,
user: {
__type: 'Pointer',
className: '_User',
objectId: this.auth.user.id
},
createdWith: {
'action': 'create'
},
restricted: true,
expiresAt: Parse._encode(expiresAt)
};
for (var key in this.data) { for (var key in this.data) {
if (key === 'objectId' || key === 'user') { if (key === 'objectId' || key === 'user') {
continue; continue;
} }
sessionData[key] = this.data[key]; additionalSessionData[key] = this.data[key];
} }
var create = new RestWrite(this.config, Auth.master(this.config), '_Session', null, sessionData);
return create.execute().then((results) => { const { sessionData, createSession } = Auth.createSession(this.config, {
userId: this.auth.user.id,
createdWith: {
action: 'create',
},
additionalSessionData
});
return createSession().then((results) => {
if (!results.response) { if (!results.response) {
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR,
'Error creating session.'); 'Error creating session.');

View File

@@ -3,8 +3,6 @@ import ClassesRouter from './ClassesRouter';
import Parse from 'parse/node'; import Parse from 'parse/node';
import rest from '../rest'; import rest from '../rest';
import Auth from '../Auth'; import Auth from '../Auth';
import RestWrite from '../RestWrite';
import { newToken } from '../cryptoUtils';
export class SessionsRouter extends ClassesRouter { export class SessionsRouter extends ClassesRouter {
@@ -32,30 +30,24 @@ export class SessionsRouter extends ClassesRouter {
handleUpdateToRevocableSession(req) { handleUpdateToRevocableSession(req) {
const config = req.config; const config = req.config;
const masterAuth = Auth.master(config)
const user = req.auth.user; const user = req.auth.user;
// Issue #2720 // Issue #2720
// Calling without a session token would result in a not found user // Calling without a session token would result in a not found user
if (!user) { if (!user) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'invalid session'); throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'invalid session');
} }
const expiresAt = config.generateSessionExpiresAt(); const {
const sessionData = { sessionData,
sessionToken: 'r:' + newToken(), createSession
user: { } = Auth.createSession(config, {
__type: 'Pointer', userId: user.id,
className: '_User',
objectId: user.id
},
createdWith: { createdWith: {
'action': 'upgrade', 'action': 'upgrade',
}, },
restricted: false,
installationId: req.auth.installationId, installationId: req.auth.installationId,
expiresAt: Parse._encode(expiresAt) });
};
const create = new RestWrite(config, masterAuth, '_Session', null, sessionData); return createSession().then(() => {
return create.execute().then(() => {
// delete the session token, use the db to skip beforeSave // delete the session token, use the db to skip beforeSave
return config.database.update('_User', { return config.database.update('_User', {
objectId: user.id objectId: user.id

View File

@@ -7,8 +7,6 @@ import ClassesRouter from './ClassesRouter';
import rest from '../rest'; import rest from '../rest';
import Auth from '../Auth'; import Auth from '../Auth';
import passwordCrypto from '../password'; import passwordCrypto from '../password';
import RestWrite from '../RestWrite';
const cryptoUtils = require('../cryptoUtils');
export class UsersRouter extends ClassesRouter { export class UsersRouter extends ClassesRouter {
@@ -142,8 +140,6 @@ export class UsersRouter extends ClassesRouter {
} }
} }
const token = 'r:' + cryptoUtils.newToken();
user.sessionToken = token;
delete user.password; delete user.password;
// Remove hidden properties. // Remove hidden properties.
@@ -161,31 +157,19 @@ export class UsersRouter extends ClassesRouter {
delete user.authData; delete user.authData;
} }
} }
const {
sessionData,
createSession
} = Auth.createSession(req.config, { userId: user.objectId, createdWith: {
'action': 'login',
'authProvider': 'password'
}, installationId: req.info.installationId });
user.sessionToken = sessionData.sessionToken;
req.config.filesController.expandFilesInObject(req.config, user); req.config.filesController.expandFilesInObject(req.config, user);
const expiresAt = req.config.generateSessionExpiresAt(); return createSession();
const sessionData = {
sessionToken: token,
user: {
__type: 'Pointer',
className: '_User',
objectId: user.objectId
},
createdWith: {
'action': 'login',
'authProvider': 'password'
},
restricted: false,
expiresAt: Parse._encode(expiresAt)
};
if (req.info.installationId) {
sessionData.installationId = req.info.installationId
}
const create = new RestWrite(req.config, Auth.master(req.config), '_Session', null, sessionData);
return create.execute();
}).then(() => { }).then(() => {
return { response: user }; return { response: user };
}); });