neurosity-sdk-js icon indicating copy to clipboard operation
neurosity-sdk-js copied to clipboard

Token returned from getOAuthToken is unusable

Open louis030195 opened this issue 11 months ago • 5 comments

My users connect their Neurosity account by going to an url created with:

// server ...

import { Neurosity } from "@neurosity/sdk";
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const neurosity = new Neurosity({
    autoSelectDevice: false
});
export async function GET(request: NextRequest) {
    return neurosity
        .createOAuthURL({
            clientId: process.env.NEUROSITY_OAUTH_CLIENT_ID!,
            clientSecret: process.env.NEUROSITY_OAUTH_CLIENT_SECRET!,
            redirectUri: process.env.NEUROSITY_OAUTH_CLIENT_REDIRECT_URI!,
            responseType: "token",
            state: Math.random().toString().split(".")[1], // A random string is required for security reasons
            scope: [
                "read:devices-info",
                "read:devices-status",
                "read:signal-quality",
                "read:brainwaves",
                "read:focus",
            ]
        })
        .then((url) => NextResponse.json({url: url}))
        .catch((error) => NextResponse.json({ error: error.response.data }, { status: 400 }))
}


// ... later on client

const neurosity = new Neurosity();

console.log(token);

await neurosity.login({ customToken: token });

neurosity.focus().subscribe(console.log)
// works
{
  label: 'focus',
  metric: 'awareness',
  probability: 0.7761862422393826,
  timestamp: 1691170018286
}

OAuth tokens expire after 60 minutes, so I renew them with getOAuthToken. When I try to use the token from getOAuthToken it fails:

const { Neurosity } = require("@neurosity/sdk");
const fs = require('fs');
const dotenv = require("dotenv");
dotenv.config();

main();

async function main() {

    const neurosity = new Neurosity();

    const token = await neurosity.getOAuthToken({
        clientId: process.env.NEUROSITY_OAUTH_CLIENT_ID!,
        clientSecret: process.env.NEUROSITY_OAUTH_CLIENT_SECRET!,
        userId: userId,
    });

    console.log(token);

    await neurosity.login({ customToken: token });

    neurosity.focus().subscribe(console.log)
}
            throw err;
            ^

Error: Neurosity SDK: You are trying to access data with an OAuth token without access to the following scopes: read:focus.
    at getScopeError (/Users/louisbeaumont/Documents/hello-world/node_modules/@neurosity/sdk/dist/cjs/utils/oauth.js:92:12)
    at validateOAuthScopeForFunctionName (/Users/louisbeaumont/Documents/hello-world/node_modules/@neurosity/sdk/dist/cjs/utils/oauth.js:88:19)
    at Neurosity.focus (/Users/louisbeaumont/Documents/hello-world/node_modules/@neurosity/sdk/dist/cjs/Neurosity.js:857:91)
    at main (/Users/louisbeaumont/Documents/hello-world/oauth.js:22:15)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Node.js v20.0.0

If I use the first token it works. Seems to be an unexpected behaviour? What is the usage of the new token?

louis030195 avatar Aug 04 '23 17:08 louis030195

Hi @louis030195,

Are you still experiencing this issue?

alexcastillo avatar Aug 16 '23 20:08 alexcastillo

I've lost a bit track of it now, I have an implementation that works but not sure how. Basically renew the token every time the user has his crown ON

My biggest problem now is that I cannot find a way to login multiple users and listen to multiple users brain in the same process, is there an example of doing so somewhere with oauth?

the pseudo code look like this:

// ...
for each user
    const neurosity = new Neurosity();
    await neurosity.logout(); // tried with or without

    const token: string = await neurosity.getOAuthToken({
        clientId: process.env.NEUROSITY_OAUTH_CLIENT_ID!,
        clientSecret: process.env.NEUROSITY_OAUTH_CLIENT_SECRET!,
        userId: userId,
    });

    if (!token) {
        console.error("Failed to obtain token for userId:", userId);
        return;
    }

    console.log("Obtained token for userId:", userId);

    await neurosity.login({ customToken: token })
    // here: Error logging in: Already logged in.

// ...

Is there some kind of state in the file system? I was expecting that creating a Neurosity client for each user would allow me to have multiple connections

Any feedback appreciated @alexcastillo 🙏

louis030195 avatar Aug 21 '23 17:08 louis030195

Are you running the code above in node or the browser?

alexcastillo avatar Aug 22 '23 16:08 alexcastillo

@alexcastillo node

louis030195 avatar Aug 22 '23 22:08 louis030195

soo ... i found a solution

i run each "brain listening" in different processes using fork from child_process, because i assumed there is some state that cause concurrency issue

this is not ideal but it works

PS: noticed

https://github.com/neurosity/neurosity-sdk-js/blob/68a33cf4936ca5de959a06e045f6f6d26084f52e/src/api/index.ts#L157

and

https://github.com/neurosity/neurosity-sdk-js/blob/68a33cf4936ca5de959a06e045f6f6d26084f52e/src/api/index.ts#L71

tried to set the user to null or such hack, didn't solve my problem, went for the multi process solution

louis030195 avatar Aug 23 '23 16:08 louis030195