Meteor: Endpoint for images fetched from S3 - How to authenticate connection?

独自空忆成欢 提交于 2019-12-12 04:23:04

问题


We have encrypted images stored in S3 that we need to serve to clients, meaning that we cannot give clients S3 URLs for the img src. The files are also potentially large, so idealy we would like to not go through js.

With no serverside routing available we were going down the route of having a separate express setup in Meteor, and this works, since the router on the client side doesn't interfere with

We could add the Auth token to the src url and poke the DB, but we're wary of doing so as it would expose the token in the DOM and in copy pasta cooked up by the users.

Is there a good way of getting this to work properly? Is it posible to configure other routers to serve up the angular app on a specific URL maybe?

Any input welcome :)

app = Express();

app.get('/order/:orderID/image/:UUID', function(mainReq, mainRes) {
// TODO: security check, but not getting current loggedin user info
// There are no cookies, only the DDP connection is authenticated (?)

console.log(Meteor.userId()); // fails

// S3 fetch and decrypt here

});

回答1:


The answer is:

It's not possible using out of the box Meteor. If you wanna restrict HTTP requests, you're on your own.

Meteor doesn't use cookies (on purpose and for good reason; https://blog.meteor.com/why-meteor-doesnt-use-session-cookies-e988544f52c9), but instead only ever authenticate the DDP websocket connection, and hence any HTTP request to the server is not authed in any way. There are a few packages that tries to handle these things, and this article explains a way of putting the auth token (and the user ID) into the url: https://blog.kayla.com.au/server-side-route-authentication-in-meteor/ The problem with this is that you then expose the token in the DOM, and any browser extension would be able to read it, and the user would be able to copy/paste the url and send it to others. This could end up in session hijacking.

If you wanna authenticate HTTP requests, you will have to wither find a package that write a cookie (and prevents CSRF attacks if you're doing actions) or have the user supply the username/password each time.

For my situation it is sufficient to have the client side write a cookie with the auth token on login on the client. It will then be sent with the request and can be checked server side. Since all I'm doing is send back a picture, it's not nessaccary to prevent CSRF for me, so beware of that while reading the snippets below og how to have the client send a cookie to the server:

Accounts.onLogin(() => {
  removeExistingCookie(cookieName);
  document.cookie = "loginToken=" + localStorage['Meteor.loginToken'] + "; domain=" + document.location.hostname + "; path=/; expires=" + expiryTime + ";secure"
});

Then you'll have to parse the cookie header on the server and auth the request on the server using something like this

let cookieParser = Npm.require('cookie-parser');

app = Express();
app.use(cookieParser());

app.get('/order/:orderID/image/:UUID', function(mainReq, mainRes) {

    let loginToken = mainReq.cookies["loginToken"];
    if (!loginToken) {
        mainRes.status(404).send();
        return;
    }

    let hashedToken = Accounts._hashLoginToken(loginToken),
        sessionBelongsToUser = Meteor.users.findOne(
        {
            'services.resume.loginTokens.hashedToken': hashedToken,
        });

    if (!sessionBelongsToUser) {
        mainRes.status(404).send();
        return;
    }


来源:https://stackoverflow.com/questions/41550192/meteor-endpoint-for-images-fetched-from-s3-how-to-authenticate-connection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!