Problems when acting on behalf of users

Hi everyone!

We are developing some JIRA Cloud addons and we are having problems when we try to do REST calls to JIRA acting act on behalf of users.

We have followed the instructions from the documentation, implementing OAuth 2.0 and looking at the example codes.

The problem is that we are getting a 400 error when we request to the authorization server for OAuth 2.0 authentication. We get something like this:

Requesting access token
ERROR [400]: Couldn't get access token from response
 { error: 'invalid_grant',
  error_description: 'The token is expired' }

For this, we cannot do any REST call on behalf of any user. This is an important thing with us, we need to solve some bugs and include some new features that require this to be working.

I have developed an example addon for OAuth 2.0 authentication, please, if you can, have a look at the code. It will be great if you can test it on your instances or review the code to put some light on this. You can find it here. We are using the atlassian-connect-express 2.0.3.

@dmeyer, perhaps you can also help us. Moreover, @david.gonzalez write a topic about it before.


Hi, @alvaro.aranda!

Did you know that atlassian-connect-express comes with built-in support for authentication using OAuth 2.0 JWT Bearer token since version 2.0.0? The section How to send a signed outbound HTTP request back to the host of the README describes how to use it.

I don’t immediately see any problem with your implementation. You seem to be calculating the JWT token expiration time in the same way as atlassian-oauth2-js does, so I guess it could be a problem with clock drift. But before anything else, could you try if you have better luck with the #asUser() method?

Hi @epehrson!

Thanks for the quick response. Yes, I have read this documentation, and as you has said, I know that the method #asUser is what I need to act on behalf of users. But, it gives me the same error message as the OAuth 2.0 authentication:

            .get('/rest/api/2/myself', function(err, res, body) {
                console.log(err, res.statusCode, body);
{ error: 'invalid_grant',
  error_description: 'The token is expired' }

Any idea to test something in order to look for a clock drift?

How about comparing the output of date +%s on your server to that from a site like

I have tested it right now and it seems there isn’t a clock drift, my computer time is sync with this time and the time when the request is done is in the time range (iat, exp). Any other idea? Can you test this code on any other instance?

I’m using a JIRA Cloud development instance, perhaps this put some light on the problem.

I just tried installing your add-on on my dev instance and got the message OAuth is working fine!!

So I’m still thinking it’s clock drift. Could you try forcing an update of your system time against an NTP server?

Hi Einar,

Now it’s working!! As you said, it was a clock drift finally, you were right!

The problem is that is getting the time from your server, that misleads me yesterday.

Great thanks, we can continue our development now.



We have developed this solution and it works great! But, we are having a problem with some users of different instances (on production): we are building all the token to reach the OAuth validation and it works, we are getting the access_token fine; but, when we do the request to act on behalf of the user, we get this message:

{ error: 'Add-on \'my.addon.key' disallowed to impersonate the user because \'no valid active user exists\'' }

Do you know what could be the cause to have a trace like that? We have implemented a fallback method to make the REST call to JIRA without acting as user, but it will be great we can have this working. In fact, we haven’t been able to reproduce this problem on our instances.


Hi guys,

Can anyone help us with the previous comment? We have a fallback process to protect us from this errors but the perfect solution will be to solve them because it’s making our addon not to show the real data every time.

Please @epehrson or @dmeyer, can you bring some light to this?

Great regards!

@alvaro.aranda, where are you getting the user key from?

Is there an chance you are using the username instead? Our documentation for the sub claim touches on it, and this question has some background on the difference between user keys (which never change) and usernames (which can).

Hi @epehrson,

Great explanation, you give the clue to solve the problem. You were right, I though I was using the user key but it was the user name. Now it’s working nice.