-
-
Notifications
You must be signed in to change notification settings - Fork 167
Extracting x_mtok authentication into own package? #841
Copy link
Copy link
Open
Labels
Description
I have a suggestion:
- Describe your feature / request
I currently implement connect route authentication with ostrio:cookies and basically the code from this package:
- client: https://github.com/veliovgroup/Meteor-Files/blob/master/client.js#L115
- server: https://github.com/veliovgroup/Meteor-Files/blob/master/server.js#L1165
From what I can see, the code for authentication could completely be extracted into an own package and being reused for cookies-based auth in routes, right?
- How you going to use it? Give a usage example(s)
Example code could look like this:
Client
import { Accounts } from 'meteor/accounts-base'
import { DDP } from 'meteor/ddp-client'
import { Meteor } from 'meteor/meteor'
// cookie injected from outside to let host control cookie options
export const cookieAuth = cookie => {
const setTokenCookie = () => {
if (Meteor.connection._lastSessionId) {
cookie.set('x_mtok', Meteor.connection._lastSessionId, { path: '/', sameSite: 'Lax' });
if (Meteor.isCordova && this.allowQueryStringCookies) {
cookie.send();
}
}
};
const _accounts = (Package && Package['accounts-base'] && Package['accounts-base'].Accounts) ? Package['accounts-base'].Accounts : undefined;
if (_accounts) {
DDP.onReconnect((conn) => {
conn.onReconnect = setTokenCookie;
});
Meteor.startup(setTokenCookie);
_accounts.onLogin(setTokenCookie);
}
}Server
import { Meteor } from 'meteor/meteor'
export const getUser = (req, res, next) => {
if (req.userId && req.user) { return next() }
let mtok = null
if (req.headers['x-mtok']) {
mtok = req.headers['x-mtok']
} else {
const cookie = req.Cookies
if (cookie.has('x_mtok')) {
mtok = cookie.get('x_mtok')
}
}
if (mtok) {
const userId = getUserIdFromToken(mtok)
if (userId) {
req.userId = () => userId
req.user = (() => {
let user
return () => {
if (!user) {
user = Meteor.users.findOne(userId)
}
return user
}
})()
}
}
return next()
}
const isObject = obj => typeof obj === 'object'
const getUserIdFromToken = (xmtok) => {
if (!xmtok) return null
const sessions = Meteor.server.sessions
const sessionIsMap = sessions instanceof Map
const sessionIsObject = isObject(sessions)
// throw an error upon an unexpected type of Meteor.server.sessions in order to identify breaking changes
if (!sessionIsMap || !sessionIsObject) {
throw new Error('Received incompatible type of Meteor.server.sessions')
}
if (sessionIsMap && sessions.has(xmtok) && isObject(sessions.get(xmtok))) {
// to be used with >= Meteor 1.8.1 where Meteor.server.sessions is a Map
return sessions.get(xmtok).userId
}
else if (sessionIsObject && xmtok in sessions && isObject(sessions[xmtok])) {
// to be used with < Meteor 1.8.1 where Meteor.server.sessions is an Object
return sessions[xmtok].userId
}
return null
}What do you think about it? Also, do you have any concerns regarding security on that approach?
Reactions are currently unavailable