Meteor session cookie & meteor_login_token - javascript

According to the docs , Meteor doesn't use session cookies.
However, what's the meteor_login_token cookie used for then? It looks to me like a session cookie, created after the user successfully signs in, and passed then to every request made to the server.

Meteor definitely doesn't use cookies.
Do you have any additional packages with your app that could add this cookie? For example, fast-render has the ability to get data related to a user by sending the same login token using cookies.
If we take a look at their code, they indeed have a function setting a cookie named meteor_login_token.
function setToken(loginToken, expires) {
Cookie.set('meteor_login_token', loginToken, {
path: '/',
expires: expires
});
}
This behavior is described in the security part of their readme.
If you're not using fast-render, you should definitely check any additional packages you may have that could add an additional cookie.

Related

Google oauth session lost after page reload (javascript)

I recently moved from the deprecated gapi.auth2 to the new Google Identity Services, using the javascript client library, and noticed a big difference: if someone signs in, and then reloads the page, the session is lost, and has to sign in again, every time the page is loaded. This was not the case with the deprecated library.
The problem can be easily reproduced with the Calendar API example.
Is there any configuration option to keep the session persistent? Or do I need to store the access tokens somehow? I could not find anything relevant in the official docs.
UPDATE:
The migration guide states the following:
Previously, Google Sign-In helped you to manage user signed-in status using:
Callback handlers for Monitoring the user's session state.
Listeners for events and changes to signed-in status for a user's Google Account.
You are responsible for managing sign-in state and user sessions to your web app.
However there's absolutely no information on what needs to be done.
UPDATE 2
To be more specific, the actual issue is not making the session persistent. Managing the sign in state and user session is something I can solve.
The real problem is the access token used to call the Google APIs.
As mentioned in the comments, the access tokens are 1) short lived 2) are not stored anywhere, so even if not expired, they do not persist between page reloads.
Google provides the requestAccessToken method for this, however even if I specify prompt: '', it opens the sign-in popup. If I also specify the hint option with the signed in user's email address, than the popup opens, displays a loading animation briefly, and closes without user interaction. I could live with this, however this only works if triggered by a user interaction, otherwise the browser blocks the popup window, meaning that I cannot renew the token without user interaction, e.g. on page load. Any tips to solve this?
I faced all the same issues you described in your question.
In order to help:
Google 3P Authorization JavaScript Library: in this link we can check all the methods the new library has (it does not refresh token, etc..)
This doc says the library won't control the cookies to keep the state anymore.
Solution
Firstly I need to thanks #Sam O'Riil answer.
As Sam described: "you can somehow save access token and use it to speed-up things after page reload."
Given the the Google's exampe, we should call initTokenClient in order to configure the Google Auth and the requestAccessToken to popup the auth:
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: tokenCallback
});
tokenClient.requestAccessToken({prompt: ''})
In your tokenCallback you can save the credentials you get somehow, e.g.:
const tokenCallback(credentials) => {
// save here the credentials using localStorage or cookies or whatever you want to.
}
Finally, when you restart/reload your application and you initialize the gapi.server again, you only need to get the credentials again and set token to gapi, like:
gapi.load('client', function() {
gapi.client.init({}).then(function() {
let credentials = // get your credentials from where you saved it
credentials = JSON.parse(credentials); // parse it if you got it as string
gapi.client.setToken(credentials);
... continue you app ...
}).catch(function(err) {
// do catch...
});
});
Doing it, your application will work after the reload. I know it could not be the best solution, but seeing what you have and the library offers, I think that's you can do.
p.s.: the token expires after 1 hour and there is no refresh token (using the implicit flow) so, you will have to ask the user to sign-in again.

Adal.js logging out without a redirect

In our current SPA implementation we authenticate against AzureAD using adal.js and upon successful authentication hit our web api to get the authorization data. There are a couple of edge case scenarios where the get authorization data call could fail. In this case we would like to clear out the state/cache created by adal.js. I have tried a few things but I have not not been able to create a clean slate. Here is some code that I have tried.
localStorage.clear();
var authContext = AuthenticationContext.prototype._singletonInstance;
authContext.clearCache();
authContext._user = null;
I don't want to use the built in logout function. Calling logout redirects the user to the Azure signout page. The UX is pretty wierd so trying to avoid it.
If you want to clear all the cache entries created by adal, clearCache() is the method that should be used, and if you want to clear the cache only for a specific resource entry, then use clearCacheForResource.
But one more thing to note is, these two methods only clear the cache/storage though, it won't clear any session/cookie hold on azure ad, if you want to clear that, then the built in logout should be the one to use.
You could probably try to implement the silent logout(probably using iframe, this will prevent the ux from displaying), and then call clearCache to clear the localstorage/sessionstorage
You can set postLogoutRedirectUri to your aplication setup:
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'www.contoso.com',
clientId: '0101001010101',
extraQueryParameter: 'nux=1',
cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
endpoints: endpoints,
postLogoutRedirectUri: 'https://www.yourapp.com'
},
$httpProvider
);

How to check Node session cookie expiration from browser

We're using Node + Connect to manage sessions for our app, which is a single-page application (SPA) built with Backbone.js. I'm trying to write some code which will check from the client if the session is still valid. I know I can do it in Node itself, but as this is an SPA, I need to be able to do it completely client-side.
My first thought was to read the connect.sid cookie with jQuery and if it wasn't there, then that would mean that the session is expired. Unfortunately, that session cookie is protected with the HttpOnly flag and for good reason. I don't want to disable that.
My second thought was to write a second, parallel cookie every time the connect.sid cookie is written. This second cookie would only store the expire date of the session cookie and would set HttpOnly to false so that the client could read it.
So my question is, how do I go about writing that second cookie, or is there a better solution for being able to detect session expiration status from the browser?
I know how to write cookies with Node, but I'm not sure where to put the code so that it will fire every time that Connect writes the main connect.sid session cookie. Additionally, I would like to be to read the expire date of the session cookie so that I can write it in my parallel cookie.
UPDATE: To be clear, I'm not looking to read the expiration date of the session. I know that JS cannot access the expires date of a cookie. I just want to see whether or not the cookie exists, as it will only exist when it's valid and therefore its absence is enough data for me.
updated after clarifications in comments
Add another middleware right next to your session middleware. Excerpt below assumes express, but if you are using connect without express you should be able to interpret accordingly.
app.use(connect.session(sessionOptions));
app.use(function (req, res, next) {
res.cookie("sessionIsAlive", "1", {
//just make sure this matches your expiration time of the real session cookie
expires: new Date(Date.now() + 900000),
httpOnly: false
});
next();
});
Then you can check for the existence of that via javascript in the browser. And just FYI connect writes a new cookie with an updated expiration time on every response. That's how the "expires after N minutes of inactivity" behavior is implemented.

Node express verifying signed cookie

I am trying to use signed cookies in Node's express module, and have read the documentation, but am confused on how to verify them. As I understand it, I must verify the cookies on the server. However, how I do so is unclear to me. I will receive the cookie, and then what? Must I run a function to verify it? If so, what function? If not, and its automatic, how do I program what to do if the cookie is indeed modified? What code must I use to check for this? I intend to use these signed cookies for user authentication. So if I go to a page, and want to show different content depending on whether or not the user is authenticated, I'm not sure how to do this. If the page renders before I verify the cookie, I don't see how this would be possible. I therefore assume that I must verify the cookie before rendering the page, which leads me to ask this question, in order to figure out how to do so.
Essentially, I wish to do something like this:
if(CookieIsVerified)
{
.....
}
else if (!CookieIsVerified)
{
.....
}
You don't need to verify the cookie yourself. If you use the cookieParser middleware you can pass in a secret which will be used to sign the cookie. This means that nobody can change it.
Secondly, use the cookieSession middleware. This will take anything that is in req.session and serialize it into the cookie.
app.use(express.cookieParser('yoursecretkeyhere'));
app.use(express.cookieSession());
To check whether a user is authenticated, you can create your own middleware which checks that the current session has been authenticated. If it's not redirect to the login page or return a 401. This middleware should be used on all your routes except the login route.
Create a login route which takes credentials and doesn't use the above middleware. In here you can check username/password or tokens and if the user is a valid one, set an authenticated flag on the session. You can check this flag in your above middleware.

How do sessions work in Express.js with Node.js?

Using Express.js, sessions are dead simple. I'm curious how they actually work though.
Does it store some cookie on the client? If so, where can I find that cookie? If required, how do I decode it?
I basically want to be able to see if a user is logged in, even when the user is not actually on the site at the time (like how facebook knows you're logged in when you're on other sites). But I suppose to understand that I should first understand how sessions work.
Overview
Express.js uses a cookie to store a session id (with an encryption signature) in the user's browser and then, on subsequent requests, uses the value of that cookie to retrieve session information stored on the server. This server side storage can be a memory store (default) or any other store which implements the required methods (like connect-redis).
Details
Express.js/Connect creates a 24-character Base64 string using utils.uid(24) and stores it in req.sessionID. This string is then used as the value in a cookie.
Client Side
Signed cookies are always used for sessions, so the cookie value will have the following format.
[sid].[signature]
Where [sid] is the sessionID and [signature] is generated by signing [sid] using the secret key provided when initializing the session middleware.
The signing step is done to prevent tampering. It should be computationally infeasable to modify [sid] and then recreate [signature] without knowledge of the secret key used. The session cookie is still vulnerable to theft and reuse, if no modification of [sid] is required.
The name for this cookie is
connect.sid
Server Side
If a handler occurs after the cookieParser and session middleware it will have access to the variable req.cookies. This contains a JSON object whose keys are the cookie keys and values are the cookie values. This will contain a key named connect.sid and its value will be the signed session identifier.
Here's an example of how to set up a route that will check for the existence of the session cookie on every request and print its value to the console.
app.get("/*", function(req, res, next) {
if(typeof req.cookies['connect.sid'] !== 'undefined') {
console.log(req.cookies['connect.sid']);
}
next(); // Call the next middleware
});
You'll also need to make sure the router (app.use(app.router)) is included after cookieParser and session in your configure section.
The following is an example of the data stored internally by Express.js/Connect.
{
"lastAccess": 1343846924959,
"cookie": {
"originalMaxAge": 172800000,
"expires": "2012-08-03T18:48:45.144Z",
"httpOnly": true,
"path": "/"
},
"user": {
"name":"waylon",
"status":"pro"
}
}
The user field is custom. Everything else is part of session management.
The example is from Express 2.5.
I have never used Express.js, although according to their documentation on the subject it sounds like:
Cookies are stored on the client, with a key (which the server will use to retrieve the session data) and a hash (which the server will use to make sure the cookie data hasn't been tampered with, so if you try and change a value the cookie will be invalid)
The session data, as opposed to some frameworks (e.g. Play Framework!) is held on the server, so the cookie is more like a placeholder for the session than a holder of actual session data.
From here, it looks like this session data on the server is by default held in memory, although that could be altered to whatever storage form implements the appropriate API.
So if you want to check things without a specific req request object, like you said, you need to just access that same storage. On the bottom of the first documentation page, it details required methods the storage needs to implement, so if you're familiar with your storage API, maybe you could execute a .getAll() if something like that exists, and loop through the session data and read whatever values you want.
I'm curious how they actually work though.
Try to look at this answer and wiki stuff.
Does it store some cookie on the client?
Yes, it's usually a cookie with assigned session ID, which should be signed with a secret in order to prevent forgery.
If so, where can I find that cookie? If required, how do I decode it?
You shouldn't mess with a session cookie on the client side. If you want to work with sessions on the server side you should check out related express.js and connect docs.
In addition to already excellent answers, here are 2 diagrams I've created to explain Express sessions, their link with cookies and store :
chocolate cookie:
strawberry cookie:
Diagram's explanation:
Each cookie has a unique "flavor" (or sessionId). When the strawberry cookie is presented to the server (within the HTTP request), the server recognises this flavor and loads from the store the corresponding datas: Rosie's datas, and populates req.session with.

Categories

Resources