Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RA will logout if custom page is opened #2

Open
yanosuke opened this issue Sep 23, 2020 · 2 comments
Open

RA will logout if custom page is opened #2

yanosuke opened this issue Sep 23, 2020 · 2 comments

Comments

@yanosuke
Copy link

I am currently at a complete loss. I have tried all I can think of and am stuck on one particular issue.

So far, the JWT memory function is working perfectly for any Resource in the app, such as:
<Admin dataProvider={dataProvider} authProvider={authProvider} loginPage={LoginPage}> <Resource name="users" list={ListGuesser} /> </Admin>

However, if I add a dashboard page such as:

`
import * as React from "react";
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';

import { Title } from 'react-admin';

const Dashboard = () => {

return(
    
    <Card>
        <Title title="Welcome to the administration" />
        <CardContent>Lorem ipsum sic dolor amet...</CardContent>
    </Card>
    

);

}

export default Dashboard;`

and include it to the admin:
<Admin dashboard={Dashboard} dataProvider={TrueIMSDataProvider} authProvider={TrueIMSAuthProvider} loginPage={LoginPage}> <Resource name="companies" list={ListGuesser} /> </Admin>

RA will logout if you refresh the page while on the dashboard without error.
I believe the checkAuth it called, which in turns calls the logout function, however, I have no idea why.

Any help would be GREATLY appreciated

@MGxpwr
Copy link

MGxpwr commented Feb 12, 2021

@yanosuke I ran into the same problem. And struggled with it for over a day. But i have found the solution.

I made a few changes.
In the dataProvider i changed this:

const httpClient = (url) => {
        const options = {
            headers: new Headers({ Accept: 'application/json' }),
        };
        const token = inMemoryJWT.getToken();

        if (token) {
            options.headers.set('Authorization', `Bearer ${token}`);
            return fetchUtils.fetchJson(url, options);
        } else {
            inMemoryJWT.setRefreshTokenEndpoint('http://localhost:8001/refresh-token');
            return inMemoryJWT.getRefreshedToken().then((gotFreshToken) => {
                if (gotFreshToken) {
                    options.headers.set('Authorization', `Bearer ${inMemoryJWT.getToken()}`);
                };
                return fetchUtils.fetchJson(url, options);
            });
        }
    };

To:

const httpClient = (url) => {
        const options = {
            headers: new Headers({ Accept: 'application/json' }),
        };
        const token = inMemoryJWT.getToken();
        return fetchUtils.fetchJson(url, options);
};

Because instead of checking for a token in there i do it in the auth provider which is called before the data provider which created the issue for me.

So in the auth provider i changed this:

 checkAuth: () => {
        return inMemoryJWT.waitForTokenRefresh().then(() => {
            return inMemoryJWT.getToken() ? Promise.resolve() : Promise.reject();
        });
    },

To this:

 checkAuth: () => {
    const token = inMemoryJWT.getToken();

    if (token) {
      return Promise.resolve();
    } else {
      return inMemoryJWT.getRefreshedToken().then((gotFreshToken) => {
        if (gotFreshToken) return Promise.resolve();

        return Promise.reject();
      });
    }
  },

Sorry for the bad English and I hope this helps you or someone else who runs into the same problem.

@rvrolijk
Copy link

rvrolijk commented Feb 16, 2021

So far so good! I had come up with a roundabout way by storing the permissions scope in localstorage (front-end only), then using that the check if someone is logged in or not. I was able to use your solution and adapt it to work with the permissions scope which is now also stored in memory.

This is what my httpClient looks like in the DataProvider:

    const locale = inMemoryJWT.getLocale();

    if (!options.headers) {
        options.headers = new Headers({Accept: 'application/json'});
    }

    const token = inMemoryJWT.getToken();

    options.headers.set('Authorization', `Bearer ${token}`);
    options.headers.set('Accept-Language', locale);
    options.credentials = 'include';
    options.cache = "no-cache";
    return fetchUtils.fetchJson(url, options); 

In my case, the user's locale is also used to translate some information within the API.
My checkAuth is now the same as yours and my getPermissions is as follows:

        return inMemoryJWT.waitForTokenRefresh().then(() => {
            const permissions = inMemoryJWT.getPermissions();
            return inMemoryJWT.getToken() ? Promise.resolve(permissions) : Promise.reject({message: false});        
        });

Where the permissions are obtained at the same time as the access tokens in the 'JWTProvider' (inMemoryJWT).

Thank you for your solution! i'm sure it will help others as well,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants