marmelab / ra-auth-cognito

An auth provider for react-admin which handles authentication with AWS Cognito.
MIT License
10 stars 6 forks source link

How to get the access token for the data provider? #6

Closed julienV closed 1 year ago

julienV commented 1 year ago

It seems like the authProvider doesn't provide a hook or handle to provide the access token back to the data provider. Here is how i deal with it, intercepting the handleCallback call:

const authProvider = CognitoAuthProvider({
    mode: 'oauth',
    clientId: `${process.env.REACT_APP_COGNITO_APP_CLIENT_ID!}`,
    userPoolId: `${process.env.REACT_APP_COGNITO_USERPOOL_ID!}`,
    hostedUIUrl:  `${process.env.REACT_APP_COGNITO_APP_HOSTED_UI_URL!}`,
});

const saved = authProvider.handleCallback;
authProvider.handleCallback = async () => {
    const user = await saved!();
    const session = user.getSignInUserSession();
    localStorage.setItem('token', session.getAccessToken().getJwtToken());

    return Promise.resolve(user);
}

i can then get the token from the local storage in the data provider, but i feel like I am maybe missing a better way to do that...

stripethree commented 1 year ago

I'm not sure if this is the best way to do it, but here's an example of I have done it when wanting to pass the id token via request headers on each request. You could do something similar with session.getAccessToken().getJwtToken()

const authProvider = CognitoAuthProvider({
  mode: 'oauth',
  clientId: process.env.REACT_APP_COGNITO_CLIENT_ID,
  userPoolId: process.env.REACT_APP_COGNITO_POOL_ID,
  hostedUIUrl: process.env.REACT_APP_COGNITO_HOSTED_UI_URL,
  scope: ['openid', 'email', 'profile', 'aws.cognito.signin.user.admin']
});

const userPool = new CognitoUserPool({
  ClientId: process.env.REACT_APP_COGNITO_CLIENT_ID,
  UserPoolId: process.env.REACT_APP_COGNITO_POOL_ID
});

const httpClient = (url, options = { headers: null }) => {
  if (!options.headers) {
    options.headers = new Headers({ Accept: 'application/json' });
  }
  const user = userPool.getCurrentUser();
  user.getSession((err, session: CognitoUserSession) => {
    if (session) {
      const idJwt = session.getIdToken().getJwtToken();
      options.headers.set('Authorization', `Bearer ${idJwt}`);
    }
  });
  return fetchUtils.fetchJson(url, options);
};

I've experimented with passing the CognitoUserPool into authProvider as the support appears to be there in code, but something with my configuration does not play well with the implementation.

djhi commented 1 year ago

Both approach are valid. I would favor https://github.com/marmelab/ra-auth-cognito/issues/6#issuecomment-1503541232 though

julienV commented 1 year ago

@djhi both solution work, but they feel rather workaroundish, why not have a function exported directly from the authprovider so we don't have to do this ?

djhi commented 1 year ago

We are actually thinking about it. In the mean time, that's the recommended way.