Expose Meteor user context to Express endpoints

Hello community!

I recently pushed a PR that allows Express endpoints defined through the Meteor WebApp package to apply authorization. This makes it possible to protect specific REST endpoints in a way similar to how DDP endpoints like methods and subscriptions already work.

As an example, on the server you can define the following:

import { WebApp } from 'meteor/webapp';
import { Accounts } from 'meteor/accounts-base';

// Apply auth middleware to /api routes
WebApp.connectHandlers.use('/api', Accounts.auth());

// Protected endpoint under /api
WebApp.connectHandlers.use('/api/users', async (req, res) => {
  try {
    // User context is available
    console.log('Authenticated user ID:', Meteor.userId(), req.userId);
    console.log('Authenticated user:', await Meteor.userAsync());

	if (!Meteor.userId()) {
      res.status(401).json({ error: 'Unauthorized' });
      return;
    }

    const users = await Meteor.users
      .find({}, { fields: { username: 1, createdAt: 1, updatedAt: 1 } })
      .fetchAsync();

    res.json(users);
  } catch (error) {
    console.log(error);
    res.status(500).json({ error: error.message });
  }
});

On the client side Meteor.fetchWithAuth is available to inject the current user token to the endpoint call:

async function getUsers() {
  const response = await Meteor.fetchWithAuth('/api/users');
  return response.json();
}

console.log(await getUsers());

When logged in and authorized the console logs:

[
  {
    "_id": "Ystii57EhB6aFyXup",
    "createdAt": "2026-01-20T16:11:09.406Z",
    "username": "meteorite"
  }
]

When logged out, given the error handled within the endpoint:

{
  "error": "Unauthorized"
}

By default, Accounts.auth does not require authentication, but it can detect the logged-in user. This is closer to how methods and subscriptions handle authorization logic, as it lets you customize authorization once you have access to the userId that attempted to reach the endpoint.

If you want to protect endpoints unconditionally, you can apply the middleware with Accounts.auth({ required: true }), which will reject unauthenticated requests automatically.


I opened this forum discussion because, even though the implementation is done, covered by tests, and already used for a long time in my own projects, I would like feedback on the developer experience when moving it to the core. The goal is to discuss details early and make decisions together.

This is an experimental feature planned for a future minor release, likely Meteor 3.5+ (with a beta launched as soon as possible). I think it is worth bringing up now and discussing it ahead of time, so the deliver can coverage all planned usage scenarios.

3 Likes