Weakky / ra-data-opencrud

A react-admin data provider for Prisma and GraphCMS
MIT License
159 stars 45 forks source link

Authentication in react-admin #24

Open sen0va opened 5 years ago

sen0va commented 5 years ago

I tried to implement authentication with prisma with no success. Do you have a working example with auth?

dreglad commented 5 years ago

It uses ApolloClient so you can set authentication as you'd normally do in Apollo. Here are some exmples.

As mentioned here, you can supply your own Apollo client (once configured for authentication)


// Create and configure your own client
const myLinkWithAuthentication = { /* see Apollo docs */ };
const client = new ApolloClient({
  link: myLinkWithAuthentication
});

// Supply the Apollo client to buildOpenCrudProvider
buildOpenCrudProvider({ client });
MaksimKlepikov commented 5 years ago

If you use it with a prisma token, you will receive an error message, and redirection to the login page will not occur (ra failed) I think it is because ra trying to init but getting this error (at this point, we does't have token), so he can't redirect to login page.

Uncaught (in promise) Error: GraphQL error: Your token is invalid. It might have expired or you might be using a token from a different project.
    at new ApolloError (ApolloError.js:33)
    at eval (QueryManager.js:360)
    at eval (QueryManager.js:808)
    at Array.forEach (<anonymous>)
    at eval (QueryManager.js:807)
    at Map.forEach (<anonymous>)
    at QueryManager.broadcastQueries (QueryManager.js:803)
    at Object.next (QueryManager.js:887)
    at notifySubscription (Observable.js:152)
    at onNotify (Observable.js:196)
    at SubscriptionObserver.next (Observable.js:248)
    at eval (bundle.esm.js:98)
    at Array.forEach (<anonymous>)
    at Object.next (bundle.esm.js:97)
    at notifySubscription (Observable.js:152)
    at onNotify (Observable.js:196)
    at SubscriptionObserver.next (Observable.js:248)
    at notifySubscription (Observable.js:152)
    at onNotify (Observable.js:196)
    at SubscriptionObserver.next (Observable.js:248)
    at eval (bundle.esm.js:175)

My App.js

const authLink = setContext((_, { headers }) => {
    // get the authentication token from local storage if it exists
    const token = localStorage.getItem('token');
    // return the headers to the context so httpLink can read them
    return {
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : "",
      }
    }
  });
const client = new ApolloClient({
    link: authLink.concat(httpLink),
    cache: new InMemoryCache()
  });

My authProvider.js

import { AUTH_LOGIN, AUTH_LOGOUT, AUTH_ERROR, AUTH_GET_PERMISSIONS, AUTH_CHECK } from 'react-admin';
// import decodeJwt from 'jwt-decode';

export default (type, params) => {
    if (type === AUTH_LOGIN) {
        const { token } = params;
        localStorage.setItem('token', token);
    }
    if (type === AUTH_LOGOUT) {
        localStorage.removeItem('role');
        return Promise.resolve();
    }
    if (type === AUTH_ERROR) {
        debugger
    }
    if (type === AUTH_CHECK) {
        return localStorage.getItem('token') ? Promise.resolve() : Promise.reject();
    }
    return Promise.reject('Unknown method');
};

(I also use a custom login page where I just get the token from user)

How we can resolve this issue?

gabrieltong commented 5 years ago

+1

Vadorequest commented 4 years ago

Doc should be improved to showcase authentication example, it's not that straightforward.

Vadorequest commented 4 years ago

Here's how I did it.

const httpLink = createHttpLink({
      uri: 'https://api-euwest.graphcms.com/v1/xxxxx/master',
    });

    const authLink = setContext((_, { headers }) => {
      // get the authentication token from local storage if it exists
      const token = '';
      // return the headers to the context so httpLink can read them
      return {
        headers: {
          ...headers,
          authorization: token ? `Bearer ${token}` : '',
        },
      };
    });
    const client = new ApolloClient({
      link: authLink.concat(httpLink),
      cache: new InMemoryCache(),
    });

    buildGraphQLProvider({
      client,
    }).then((dataProvider) => this.setState({ dataProvider }));