Logout user with expired session

Hi friends

I’m working on a web application, I am using the JavaScript SDK.

I do session expiration tests, in order to either log in with a short session of 30mm, or have a permanent session (default at 1 year).

For my tests I place the expiration at only a few seconds (10 seconds). Everything is fine, but when the session expires I can no longer make sure to disconnect the user! because the “logOut” method is no longer accessible because the session has expired! arrg!

How to logOut properly user using Parse method when the user session token has expired ??

What do you mean by logOut not being accessible? What kind of error/problem do you have?

step to reproduce:

  1. login
    Parse.User.logIn(email, pwd)

  2. n second later , the session linked to the user expired, and then, every action from the client (Js SDk) will fail due to the fact that the sessionToken is dead ! (expired).

  3. Catch this error when client app tries whatever Parse method, like exemple provided in the doc, OK, client app knows is because of the expired session , but then I would like to logOut user properly and by the way delete the associated session (Parse internal mechanism )
    Parse.User.logOut() — will fail — with 209 error code (normal)

In fact, my real question is, how to set User with expired session in a “clean state”, i mean logged out and with no “zombie” session binded to him (what a crappy English sentence, sorry for that :pensive:)

I see your problem. I believe that’s something we should improve in the SDK. In the meantime, I believe that Parse.User._clearCache() should fix your issue. Could you please check?

Yeahh! :love_you_gesture: now Parse.User.current() == null and the UI correspoding is ok. I do not find this method in the official doc ? it simply clear the User localStorage data ? isn’t it ?.
Anyway, thank’s for your help Antonio !

Ok, so finally, I can not do what I wanted to do initially : I can’t change th expiresAt date to the current User session with this error : Cannot modify readonly attribute juste after the logIn phase … or if someone knows how to ?

I believe you can change the expiresAt from a cloud code function using the master key.

yeah, I’ll try this and come back here for de feedback :slight_smile:

I’ve tried a cloud function with no more results, my code:

Parse.Cloud.define("setSessionExpiration", (request) => {

    let q = new Parse.Query(Parse.Session);

    q.find({useMasterKey: true}).then((response) => {
        let mySession = response[0]; // unique user / session in table for my test !
        mySession.set("expiresAt", "2021-08-18T06:00:00.739Z");
        mySession.save(null, {useMasterKey: true};
    }

}

well it’s return invariably this error :frowning:
UnhandledPromiseRejectionWarning: Error: Cannot modify readonly attribute: expiresAt

1 Like

It is actually the sdk throwing the error (and not the server). So I have one more thing you can try. You can call the rest api directly. Anyways I’m afraid that it can have a reason for that to happen. Why don’t you disable session expiration? Maybe it is easier than change the expired at. Not sure what is your use-case here.

Also see this issue: Allow logout with invalid session · Issue #7277 · parse-community/parse-server · GitHub

1 Like

I wanted to add on the login form of the app, a checkbox with “keep connected”: if it’s check, I’m setting a long time expiration date, if not, a short time expiration date :wink:

Anyway, the thing most important thing is the logout feature and with your help, I’ve got a solution now, so everything is allright (thank’s Manuel to for your link).

I’ve discovered Parser-serve for 2 week’s now and it’s f***g great. Implementing User login/signIn + session in 5 minutes chrono (Vue.js app) is over-cool. And there is so much more to do with Parse-server. I’m surprised to see almost 90% tuto and youtuber talking about FireBase while Parse-server is doing the same with the possibility for self hosted with an open-source project… what ?

That sounds like an interesting feature, is that somehow currently possible with Parse Server, @davimacedo ?

I believe that’s not straightforward to be done and it would be a good addition. It looks the js sdk is blocking the session token expiration to be written (what makes sense since we don’t want clients setting their own expiration times), but I’m almost sure that it can be done via rest api passing the master key. But, since cloud code uses the sdk, it can’t be easily done even via cloud code. So, two ideas here:

  • the sdk could leave changing session expiration validation responsibility to the server
  • we could have some option in the beforeLogin trigger to change the default expiration date
2 Likes

I must say, even if I am an noob with ParseServer that the perseptive of the second solution is logical and natural for this functionality

Yes, I think security demands that changing the expiration date should only be possible via Cloud Code.

I’m thinking of a universal concept where the client can just set an ordinary field of the user object, like user.set('sessionLifetime', 'long'); or even a specific expiration date and the Cloud Code trigger can validate / translate that into an actual expiration date.

That means the SDKs wouldn’t need changes as this is just using an ordinary user object field, only the JS SDK and likely Parse Server to allow the actual manipulation in beforeLogin. Mind that beforeLogin is not called after sign-up, so that may need another change.

finally ! I’ve found an example on stackOverFlow to how to change expiration date, thank’s dstar ! :slight_smile:

post

For people interested, the same Cloud function but with axios :

const axios = require('axios');

const baseHeaders = {
    'X-Parse-Application-Id': "APP-ID",
    'X-Parse-Master-Key': "APP-MASTER-KEY",
    'Content-Type': 'application/json'
};


Parse.Cloud.define("setExpiration", async (request) => {

    const mySessionToken = request.params.sessionToken;
    let mySessionID;

    //===========================
    // get current session ID
    //===========================
    try {
        let response = await axios.get("https://APP-URL/parse/sessions/me",
            {
                headers: {...baseHeaders, 'X-Parse-Session-Token': mySessionToken}
            })
        mySessionID = response.data.objectId;
    } catch (err) {
        console.log("=======================================");
        console.log("Get user session Object -  On Error : ", err);
        console.log("=======================================");
    }

    //===========================
    // change expiration Date :  3 year more (foo exemple)
    //===========================
   let newSessionYear = new Date(); // ou new Date("2025-01-01")
    newSessionYear.setFullYear(newSessionYear.getFullYear() + 3);

    let newSessionPayload = {
        expiresAt: {"__type": "Date", "iso": newSessionYear.toISOString()}
    }
    try {
        await axios.put("https://APP-URL/parse/sessions/" + mySessionID,
            newSessionPayload,
            {
                headers: {
                    ...baseHeaders,
                    'X-Parse-Session-Token': mySessionToken,
                    'Content-Length': JSON.stringify(newSessionPayload).length
                }
            })

    } catch (err) {
        console.log("Update session expiration date - On Error : ", err);
    }

    return "new expiration date updated !";

});

Since it is possible via the REST API, it should be easy so simplify this and make it possible in a beforeSave session trigger. If you feel like making a PR, please feel free.

yeah you’re right, well I have to practice before with ParseServer as is totally new for me, I will implement a full little project with it, and then why not try to do a PR on this subject !

Great, making a PR is a great way to deepen your understanding about the inner workings of Parse Server. You can find more info in the contribution guide and if you need any guidance when it comes to the PR, please feel free to reach out.

1 Like