Question about accountId

confluence-cloud

#1

The accountId’s that apps are able to interact with - are they unique to a particular instance/product?

For example, if I have an app an installed on 2 Jira instances located at https://instance1.atlassian.net and https://instance2.atlassian.net. If Andrea has an account on both of these instances - will I see her as accountId as the same or will they come as 2 different strings?

If they are the same, let’s expand the question to include Confluence. Both instances have Confluence installed on it. Are the accountId’s the same there?


#2

I think accountId is allocated against Atlassian account and not to specific apps. I can confirm that two instances which I’m user of, gives same account Id of mine for API /rest/api/2/myself.

However, that’s not the case for add-on user account id. I found add-on user account ids are different for individual cloud instances.


#3

It’s a huge problem if add-on users don’t at least have a constant accountId. It’s already impossible to discern regular users from add-on users from the “shape” of the accountId, now if an app can’t at least identify its own add-on user by its accountId, this will lead to major issues (especially considering you can’t impersonate an add-on user).


#4

Hi @danielwester accountId will be the same for all normal users that have an Atlassian Account and should be the same in confluence as well.

It won’t be the same for jira service desk customers as those users are unique to that instance. I’m not sure about addon accounts.


#5

Is that something we can/should be able to depend on (that the accounts id are the same)? Would really love to not have to redo work later if I can avoid it. Also don’t want to worry about mid identifying users down the road.

Is this something that could be documented somewhere?


#6

Can anyone from Atlassian staff confirm that? It will be a huge problem for us in the following scenario:

  • our add-on calls the issue edit through JIRA REST API
  • our add-on receives /issue-updated webhook - we recognize that the change comes from our add-on (and not a regular user) by user_key that will disappear due to GDPR.

So, the question: how should we recognize our add-on user in the server side code?

@tpechacek, @kkercz,

Thanks,
Jack


#7

@jack,

Today I verified again and fortunately I am getting the same account id for our add-on on different instances, but that was not the case earlier.

To confirm the same for your app you can do following,

Hit following API from two different instances,

https://urinstance.atlassian.net/rest/api/2/user/search?query=<addon_user_key>

I would still wait for someone from Atlassian staff to confirm on this but as I noticed now it’s working as expected.

Hope this helps! :slight_smile:


#8

So… anyone from Atlassian that could help to officially demystify the accountId as how it works across products, instances for regular users and for app users?

It would be awesome if there was a document somewhere that we could refer to in the future as well?

Hoping that somebody like @pvandevoorde @rwhitbeck @rmassaioli @acalantog (if they’re still around before the holidays) could perhaps know who to talk to? (Please?)


#9

I asked @akassab and she said “Yes, but server products won’t use Account IDs” which I think you were aware of regarding Server.

I’ll track the ask about updating the docs internally.


#10

@rwhitbeck, thank you for chiming in.

Could you please clarify what “Yes” from your answer means in relation to Cloud and user/app accountID?

Does the app keep the same accountID across product instances or not?

Also, the auxiliary question. Is the accountID tied to app released on AMKT only or the same accountID is used for development mode too?

I would prefer to get a clear statement from Atlassian here. Testing the assumptions on a few instances might lead to a big surprise when the app is released to production with over 1k of different Jiras served.
I want to avoid that.

@aakash.thakare, thank you for the valuable input.

Cheers,
Jack


#11

For global end user accounts (doesn’t include Service Desk users), the following definitely holds:
Atlassian user accounts are global, and their immutable identifiers are unique in the global domain of account IDs. Those identifiers will be reported consistently by all systems backed by Atlassian account (which includes Cloud instances of Jira, Confluence and Stride).

For app accounts:
I believe that the same applies, but I cannot personally assert it. Apologies!


#12

@jack re: your question about accountId on production instances vs. developer instances — yes, also the same. Two things here… first, a development instance is no different than a live customer prod instance. They’re just on a different license/subscription. Second, the accountId is tied to the account login. So, if you’re signing in with the same email address across two cloud instances, the accountId will be the same.


#13

@nmansilla and what about add-on users? Will they have the same accountId across all instances?


#14

@david2 @jack @danielwester
The accountId of the user created for an app will be the same across all instances. There is a single account made per app key, not per-installation. I will confirm if apps installed using different mechanisms (marketplace, and via url in dev-mode) get different users, but I suspect that isn’t the case.

@danielwester you mentioned ‘It’s already impossible to discern regular users from add-on users from the “shape” of the accountId’. AccountId’s are meant to be opaque identifiers, and their format can change, so we would not advise on using the shape of the id to extract any information. The only guarantee that we can provide is that it will be 1-128 alphanumeric containers, with maybe a few “:”'s in it.


#15

Awesome! Thank you! Now can I that if this changes can i go the normal deprecation routes for app developers (ie. announcement with some period of heads up)?

The reason I’m asking for that is that I’ve seen the response of “it wasn’t an api so it the api deprecations didn’t apply” and since this isn’t really an api but a behavior/output of a system which the apps are a downstream consumer of it, the might not be alerted to it until after it changes (and a change with anything user identifications could cause all kinds of “fun”).

/Daniel


#16

@shraj thanks for the reply.
Actually, I was the one asking about how to identify add-on users, and the question still stands. It is essential that we are able to identify that an accountId represents an add-on user, because Connect will not let an app impersonate an add-on user, and will instead return all sorts of errors (depending on the REST API endpoint) when such an attempt is made.
Let me explain when that might happen: when a post-function implemented by an app is triggered, the qpp receives a /trigger http call with the accountId of the “current user” (i.e. the user who triggered the transition on which the post-function is defined) in the JWT token. The post-function will in turn call Jira back (through the REST API) to make changes: set a field value, transition issues, add comments, etc. It will generally make these changes “on behalf of” the current user, using impersonation, so that the appropriate user shows in the issue history. However, if the original transition was triggered by another app (e.g. the Salesforce connector), the “current user” will be… an add-on user!
When that is the case, all REST calls back into Jira done with impersonation will fail - and the error message generally won’t even be explicit as to why the call failed.
That’s why we need to be able to know ahead of time that the “current user” is an add-on user, in which case we don’t attempt impersonation. This was easy with userKeys, since every add-on user’s userKey started with “addon_”. this is not the case with accountIds.


#17

@danielwester:
As far as I know, we don’t really anticipate this behaviour changing for now, and will likely provide a heads up if that were to change.

We try and adhere to a 6 month deprecation where possible, and our “it wasn’t an API so api deprecations didn’t apply” is usually for undocumented API’s / behaviours that we’re changing.

@david2 That’s definitely an interesting case! I don’t think we currently have a way of differentiating the two, but will have a chat with the rest of the team to see what the options are.


#18

@shraj thanks!
Of course, one easy solution would be to re-allow impersonating addon users like it was with JWT impersonation (“sub” claims).


#19

@david2, let me take my chance at answering your question. With the user keys gone, the app will only receive the account ID in the webhook. Now, I think at least one more API call needs to be made to figure out what kind of user it is. Here is the Jira API that returns details of a user, given the account ID: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-api-2-user-get

With me so far? Now that we agreed (?) on making one extra call to fetch the details of the user, this is what we need to do: Make the API return whether the user is an app user, or a regular user. The underlying Atlassian Accounts API already provides this information in a field called account_type. Jira and Confluence should relay that information back to the client. It is also worth pointing out that there are other ‘app’ users in the system, besides the ones created for Connect apps. This solution will work for all other cases where the acting user is not a real person.

About enabling impersonation for app users, the reason for disabling that was an app could impersonate other app users, which was a security concern. We could perhaps look into allowing an app to impersonate its own user, but it wouldn’t solve for all the cases.


#20

Hi @natashbar,
first of all, I don’t think that having to make an extra call to the Jira REST API is a good thing - Atlassian is trying to reduce the number of calls apps have to make to function (c.f. the GraphQL initiative), and now you’re saying we should increase it…
Then, I tried to call the (Jira) /rest/api/2/user endpoint for our addon user, and the response did not include an account_type field:

{
  "self": "https://innovalog.atlassian.net/rest/api/2/user?accountId=557058:472c64c9-2567-4213-839b-86bf21558300",
  "key": "addon_com.innovalog.jmwe.jira-misc-workflow-extensions",
  "accountId": "557058:472c64c9-2567-4213-839b-86bf21558300",
  "name": "addon_com.innovalog.jmwe.jira-misc-workflow-extensions",
  "emailAddress": "com.innovalog.jmwe.jira-misc-workflow-extensions@connect.atlassian.com",
  "avatarUrls": {
    "16x16": "https://avatar-cdn.atlassian.com/7dc7b05da33fdf03bcef359457ceb3f0?s=16&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2F7dc7b05da33fdf03bcef359457ceb3f0%3Fd%3Dmm%26s%3D16%26noRedirect%3Dtrue",
    "24x24": "https://avatar-cdn.atlassian.com/7dc7b05da33fdf03bcef359457ceb3f0?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2F7dc7b05da33fdf03bcef359457ceb3f0%3Fd%3Dmm%26s%3D24%26noRedirect%3Dtrue",
    "32x32": "https://avatar-cdn.atlassian.com/7dc7b05da33fdf03bcef359457ceb3f0?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2F7dc7b05da33fdf03bcef359457ceb3f0%3Fd%3Dmm%26s%3D32%26noRedirect%3Dtrue",
    "48x48": "https://avatar-cdn.atlassian.com/7dc7b05da33fdf03bcef359457ceb3f0?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2F7dc7b05da33fdf03bcef359457ceb3f0%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue"
  },
  "displayName": "Jira Misc Workflow Extensions",
  "active": true,
  "timeZone": "Europe/Berlin",
  "locale": "en_US",
  "groups": {
    "size": 3,
    "items": [
      
    ]
  },
  "applicationRoles": {
    "size": 2,
    "items": [
      
    ]
  },
  "expand": "groups,applicationRoles"
}

I still believe this information should be passed to apps without requiring an extra call.

Finally, we use Atlassian Connect Express, and it could also handle whatever is required to identify add-on users when calling the “asUserByAccountId()” method - for example as part of the impersonation token acquisition. Basically, if the impersonated user is unacceptable (because it’s an add-on user), it should revert to no impersonation.

Am I missing anything?