Asana/node-asana

Impossible to use oAuth with fixed refresh_token

krystianolech opened this issue · 3 comments

Hi!
I'm working on server-side usage of node-asana which need to write some data in Asana. In my case users of the app are not asana users, and all actions in asana should happen as some sort of technical user.

Based on recommendations I tried to use oAuth flow. As in my case, any user interaction to login is not possible and this library does not allow to authenticate using login and password, I thought I need to save in my application config refresh_token which will be used to automatically authenticate.
Documentation provide example how to use it https://github.com/Asana/node-asana#with-a-refresh-token but the problem is that its not working.

When I do something like this:

client = Asana.Client.create({
            clientId: 'CLIENT_ID',
            clientSecret: 'SECRET',
        }).useOauth(<any>{ credentials: { refresh_token: 'REFRESH_TOKEN' } });

await client.tasks.create( /// some asana api call here

it fails with error No Authorization. I
If I will add, however client.authorize(); before API call, it tries to start CLI interaction (which shold not happen as I provided valid refresh_token).

Form my investigation it looks the problem is in establishCredentials method which is called whenever authorize() method is called.
This method implementation looks like this:

OauthAuthenticator.prototype.establishCredentials = function() {
  var me = this;
  if (me.flow) {
    // Request new credentials
    me.credentials = null;
    return me.flow.run().then(function(credentials) {
      me.credentials = credentials;
    });
  } else {
    if (me.credentials.access_token) {
      // Assume what we have is ok.
      return Bluebird.resolve();
    } else if (me.credentials.refresh_token) {
      // We were given a refresh token but NOT an access token. Get access.
      return me.refreshCredentials();
    } else {
      // What kind of credentials did we get anyway?
      return Bluebird.reject(new Error('Invalid credentials'));
    }
  }
};

so it will actually try to get token based on refresh token, but the first flow property must be null. This will never happen as this property is always initialized. In fact, I found some old open issues where it was also mentioned #133 (comment). In this issue, it was recommended to walkaround it by setting flowType: null but it also not working for me.

Hello @krystianolech !

If your app is only for a few workspaces, you could use a PAT for the technical user instead (one for each workspaces). PATs are much simpler than setting up oauth, and make a lot of sense for admin-y type functionality. (You could even use a Service Account, which is an admin-level permissions account that uses a PAT)

However, if you want to publish this app for multiple people/workspaces to use, you'll need oauth. Implementing server side oauth means the command line you execute from will open a browser for you and prompt you to login to Asana. Once you login, you'll get a code that you paste back into the command line.

Before I give a big explanation of how to debug server-side oauth, are you sure that it's what you'd like to use for this app?

@rossgrambo you are right, I'm fine with PAT for my use case, and I will use them, thanks :)

However, any way I would recommend to take a look at the issue I reported as it looks that there might be some bug with documentation, as the example provided there (with providing refresh_token to refresh_token method) is not working as expected

Thanks @krystianolech, I'll make task to re-evaluate that example.