How to use SuperTokens refreshSession?

Viewed 21

I have written following snippet of code in NodeJs to use SuperTokens session management:

index.js

const express = require('express');
const cors = require('cors');
const supertokens = require("supertokens-node");
const Session = require("supertokens-node/recipe/session");
const {middleware, errorHandler} = require("supertokens-node/framework/express");
const {verifySession} = require("supertokens-node/recipe/session/framework/express");

supertokens.init({
    framework: "express", supertokens: {
        connectionURI: "http://localhost:3568",
        apiKey: "TestTestTest123456789987654321",
    },
    appInfo: {
        appName: "rezaTest",
        apiDomain: "http://localhost:1919",
        websiteDomain: "http://localhost:1919",
        apiBasePath: "/auth",
        websiteBasePath: "/auth"
    }, recipeList: [
        Session.init()
    ]
});


let app = express();

app.get('/refresh', async (req, res) => {
    await Session.refreshSession(req, res)
        .then(async refreshedSession => {
            res.end('Session refreshed');
        })
        .catch(err => {
            console.log('refresh Error:', err);
            res.end('could not refresh:\n\r' + JSON.stringify(err));
        });

})

app.get('/login', async (req, res) => {
    await Session.createNewSession(res, '1234');
    res.end('logged in');
})

app.get("/is-authorized", verifySession(), (req, res) => {
    console.log(req.session);
    if (req.session) {
        res.end('Authorized!');
    }
    else {
        res.end('Is not Authorized');
    }
});

app.use(errorHandler());

app.listen(1919, () => {
    console.log(`http://localhost:1919`);
})

package.json

{
  "name": "nodejs_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.18.1",
    "nodemon": "^2.0.19",
    "supertokens-node": "^11.3.0"
  }
}

with the following docker-compose.yml I have started SuperTokens and Postgresql:

version: '3'

services:
  db:
    image: 'postgres:14.5'
    environment:
      POSTGRES_USER: supertokens_user
      POSTGRES_PASSWORD: Pass123
      POSTGRES_DB: supertokensdb
    ports:
      - 5433:5432
    networks:
      - supertokens_network
    restart: unless-stopped
    healthcheck:
      test: [ 'CMD', 'pg_isready -U supertokens_user' ]
      interval: 5s
      timeout: 5s
      retries: 5

  supertokens:
    image: registry.supertokens.io/supertokens/supertokens-postgresql:3.16
    depends_on:
      - db
    ports:
      - 3568:3567
    environment:
      POSTGRESQL_CONNECTION_URI: "postgresql://supertokens_user:Pass123@db:5432/supertokensdb"
      API_KEYS: TestTestTest123456789987654321
      ACCESS_TOKEN_VALIDITY: 10
    networks:
      - supertokens_network
    restart: unless-stopped
    healthcheck:
      test: >
        bash -c 'exec 3<>/dev/tcp/127.0.0.1/3567 && echo -e "GET /hello HTTP/1.1\r\nhost: 127.0.0.1:3567\r\nConnection: close\r\n\r\n" >&3 && cat <&3 | grep "Hello"'
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  supertokens_network:
    driver: bridge
  • as you can see on the docker-compose.yml, I set ACCESS_TOKEN_VALIDITY to 10 seconds, so after 10 seconds, my access token will expire and I need to use refresh token.
  • after running the docker compose, if you can see Hello in http://localhost:3568/hello, it mean SuperTokens is running correctly.

I can login and authorize routes like the following:

When I am running my NodeJs App, I can call GET http://localhost:1919/login, and the response is the following:

Response body (status code 200): logged in

before 10 seconds finish, I can call GET http://localhost:1919/is-authorized, and the response is the following:

Response body (status code 200): Authorized!

If after 10 seconds, I call GET http://localhost:1919/is-authorized, I will get the following response:

Response body (status code 401):

{
    "message": "try refresh token"
}

So I will call GET http://localhost:1919/refresh and I will get the following Error:

Response body:

could not refresh:

{"type":"UNAUTHORISED","message":"Refresh token not found. Are you sending the refresh token in the request as a cookie?","payload":{"clearCookies":true},"errMagic":"ndskajfasndlfkj435234krjdsa","fromRecipe":"session"}

but I have the cookies in Postman like the following: cookies are set in postman before request to refresh session So I am confused, to how to use refreshSession in SuperTokens. I don't know the problem is from which side, it is because of SuperTokens or Postman or ExpressJs! I have checked the postman and it is sending the cookies correctly until calling the /refresh url.

Could you please guide me where is the problem and how I can solve it?

Thanks in advance.

1 Answers

You have missed out on adding the supertokens middleware to your app. You should add it like the following:

let { middleware } = require("supertokens-node/framework/express");

// ...

let app = express();
app.use(middleware());


//... rest of your code

The middleware adds a few APIs to your app:

  • The refresh endpoint
  • The sign out endpoint

If you initialise other recipes, it will add endpoints specific to those recipes.

This way, you can remove your implementation of the refresh API, and the way you can query your app to refresh is to query http://localhost:1919/auth/session/refresh POST with an empty body. Assuming that Postman will send the refresh token in the request, it should yield a 200 response.

Related