Accessing full HTTP headers from Meteor.methods

Hi, I have a Meteor app deployed behind Cloudflare Zero Trust and I’m trying to get the user’s identity when executing a Meteor method.

The two ways that Cloudflare gives me the user identity are both HTTP headers:

  • a plain text header: Cf-Access-Authenticated-User-Email: user@domain.com
  • a JWT in a Cookie called CF_Authorization

I’m trying to get at either of these values, but this.connection?.httpHeaders seems to be a strict subset of the actual headers. so I’m not getting cookie or cf-access-authenticated-user-email from inside my method.

I tried out WebApp.connectHandlers.use(...) to get the real headers, and do in fact see the HTTP cookies there. But I can’t figure out how to correlate that info with code inside a DDP method.

Ideally I’d be able to use the JWT to call setUserId() in Meteor.onConnection and then have everything in order from there.

Am I missing anything about how to grab the full HTTP info from a method?

I tried a package: The trusted source for JavaScript packages, Meteor resources and tools | Atmosphere which doesn’t seem to reach into the DDP scope.

The server side version of this might help you: GitHub - veliovgroup/meteor-cookies: 🍪 Isomorphic bulletproof cookie functions for client and server

1 Like

ostrio:cookies is the exact package I tried linking to in my first post :sweat_smile:

It helps with managing cookies from a WebApp.connectHandlers.use context - as shown in README - but I wasn’t able to correlate any of that from within a DDP context like Meteor.methods(). If I don’t have the HTTP headers / cookies from a DDP context, I don’t think I can log the user into an account based on HTTP headers.

2 Likes

I ended up working around this Meteor method limitation by adding client code which automatically submits the JWT from the cookie:

Meteor.startup(() => {
  const accessJwt = document.cookie
    .split('; ')
    .find(row => row.startsWith('CF_Authorization='))
    ?.split('=')[1];
  if (!accessJwt) return;

  Tracker.autorun(() => {
    if (Meteor.userId()) return;
    console.log('Logging in with JWT...');
    Accounts.callLoginMethod({
      methodArguments: [{
        jwt: accessJwt,
      }],
      userCallback: err => {
        console.log('login result:', {err});
      },
    });
  });
});

This workaround requires that the cookie is not ‘http only’. And the exact implementation above is paired with a Accounts.registerLoginHandler(...) call in the server code. When submitted from the browser, the token source can’t be trusted so the server requires proper JWKS validation as well.

1 Like