Skip to main content
Version: Latest

Atlassian products: multi-connector setup

This page is not about a single connector — it's about running one or more Atlassian connectors (today: identos.jira-user; on the roadmap: Confluence, Bitbucket, OpsGenie) off a single Atlassian IdP.

It mirrors the Google Workspace setup page — same pattern, different vendor, a few Atlassian-specific quirks.

One IdP, many connectors

identity_provider
└── atlassian (registered once, OAuth client_id/client_secret from
developer.atlassian.com)

managed_resource
├── jira-user → identos.jira-user + idp_passthrough + atlassian IdP
├── confluence-user → identos.confluence-user + idp_passthrough + atlassian IdP (future)
├── bitbucket-user → identos.bitbucket-user + idp_passthrough + atlassian IdP (future)
└── opsgenie-user → identos.opsgenie-user + idp_passthrough + atlassian IdP (future)

A single Atlassian login grants access to every product whose connector is provisioned against that IdP. The user consents once, on the Atlassian consent screen, for the union of scopes every connector declares.

How scope growth works

Each connector declares upstream_scopes on its idp_passthrough auth option — the actual Atlassian OAuth scopes its users need. Jira wants read:jira-user + read:jira-work + write:jira-work + read:me + offline_access.

When you provision a managed resource in idp_passthrough mode, the gateway automatically merges that connector's upstream_scopes into the target IdP's scopes list (IdpScopeMerger). Subsequent user logins at /authorize pass the union of all those scopes to Atlassian.

before jira-user provision:       idp.scopes = [openid, email, profile]
after jira-user provision: idp.scopes = [openid, email, profile,
read:me, read:jira-user,
read:jira-work,
write:jira-work,
offline_access]
after confluence-user provision: idp.scopes = [... + read:confluence-user,
read:confluence-content.all,
write:confluence-content]

The merge is additive and idempotent — uninstalling a connector does not remove scopes (another managed resource may still need them, and we can't safely attribute scopes to a single installer).

The audience=api.atlassian.com quirk

Atlassian 3LO's /authorize endpoint requires an audience=api.atlassian.com query parameter. Without it, Atlassian returns a generic "There seems to be an issue with your identity provider" / server_error on id.atlassian.com.

The Atlassian IdP preset bundled with PBAC now auto-populates this via authorize_params when you pick Atlassian from the preset tile in Add identity provider. You can verify / override it in the IdP's Advanced → Extra authorize params textarea. Every Atlassian 3LO integration needs it — there is no supported setup without.

Classic vs granular scopes

Atlassian has two scope styles for Cloud APIs:

  • Classic: read:jira-work, write:jira-work, read:me, read:confluence-content.all, etc. Single scope covers many API endpoints.
  • Granular: read:issue:jira, read:project:jira, read:comment:jira, etc. Scope per resource × action.

PBAC connectors ship with classic scopes because the mapping from connector route → required scope is 1:1 and the consent screen stays short. Don't mix the two — Atlassian treats them as separate grant sets, and requesting both can cause the consent screen to loop or deny. If a granular-scope migration becomes necessary, update the connector manifest's upstream_scopes and re-provision; the merger will rewrite the IdP row on next install.

Pre-configuring the Atlassian 3LO app

On the Atlassian side, at https://developer.atlassian.com/console/myapps/:

  1. Create appOAuth 2.0 (3LO). Name it something recognisable (PolicyArc gateway — prod).
  2. Authorization tab → set Callback URL to the AS callback:
    http://localhost:8080/oauth2/callback
    (or your real AS issuer + /oauth2/callback).
  3. Permissions tabAdd API for each Atlassian product you plan to connect. For Jira Cloud, add the Jira API; then click Configure on that row and grant every scope from the table below that matches a connector you'll provision.
  4. Settings tab → copy the Client ID and Secret into the PBAC admin UI (Add identity provider → Atlassian tile → paste into Step 3).

PBAC auto-merges scopes into its IdP row; it cannot teach Atlassian about scopes your app hasn't been granted. If the app's Permissions tab doesn't list write:jira-work, no amount of PBAC configuration will fix the consent-screen reject.

Per-product scope reference

ProductClassic OAuth scopes to grantShipped as a connector?
Jira Cloudread:me, read:jira-user, read:jira-work, write:jira-work, offline_accessidentos.jira-user
Jira Service Managementabove + read:servicedesk-request, write:servicedesk-request, manage:servicedesk-customernot yet
Confluence Cloudread:me, read:confluence-user, read:confluence-space.summary, read:confluence-content.all, write:confluence-content, offline_accessnot yet
Bitbucket Cloudaccount, repository, repository:write, pullrequest, pullrequest:write, issue, offline_accessnot yet
OpsGenieread:opsgenie, write:opsgenie, offline_accessnot yet

Always cross-check against Atlassian's current scope documentation — Atlassian occasionally renames or adds scopes.

Bitbucket Cloud uses a different scope vocabulary from the rest of Atlassian; its scopes are verbs (repository, pullrequest:write, issue) rather than the verb:resource-product form. Don't mix Bitbucket's scope style with Jira/Confluence scopes in the same connector — they're granted separately on the Atlassian app, and the consent screen will surface them as distinct API blocks.

When a user sees "stored IdP token missing required scopes"

If you install / provision an Atlassian connector after users have already logged in through PBAC, their stored IdP tokens do not carry the newly-added scopes. The first gateway call that needs those scopes fails with a 502:

Stored IdP token missing required scopes: [write:jira-work]. User must re-authenticate with step-up.

Two paths out:

  1. Recommended: have the user sign out and back in. On the next /authorize pass, PBAC requests the expanded scope list and the user re-consents on Atlassian's screen. No operator action needed.
  2. Batch: clear upstream_identity_token for the affected users via the admin API; their next interaction will bounce through Atlassian for consent.

Going forward, the rule is: install and provision Atlassian connectors before inviting users to the gateway, and users never see this error.

Two managed resources, one connector

Atlassian connectors today ship only in idp_passthrough mode — every call acts as the signed-in user, with that user's Atlassian permissions. There's no "service account" equivalent like Google's domain-wide-delegation because Atlassian Cloud doesn't expose one at the OAuth layer.

If a future use case needs a non-user identity (e.g. webhook ingest, batch reporting), expect a separate connector that uses Atlassian Connect or an API token with Basic auth rather than 3LO. This page doesn't cover those modes.

Troubleshooting

SymptomLikely causeFix
id.atlassian.com/error?error=server_error on first redirectIdP row missing audience=api.atlassian.comEdit the IdP, paste audience=api.atlassian.com into Extra authorize params. The Atlassian preset should auto-fill this — if not, your IdP row predates the preset change
"There seems to be an issue with your identity provider" after entering credentialsScope list on the request includes a scope the app doesn't have on its Permissions tabAdd the missing scope on the Atlassian console → Permissions tab, or remove it from the connector manifest's upstream_scopes
Consent screen shows, user approves, then lands on AS with generic 400redirect_uri mismatchThe Authorization tab → Callback URL on Atlassian must match the AS's /oauth2/callback byte-for-byte, including scheme, port, and path
Refresh-token requests fail with invalid_grant after ~90 daysAtlassian rotates refresh tokens on every use; stored token is staleForce re-login (clear upstream_identity_token). Also ensure offline_access is in both the app's Permissions tab AND the connector's upstream_scopes
User logs in with Google, Jira tool says "no session", redirects back to Googleresource_type_to_idp mapping missing — Atlassian resource falls back to default_idpAdd resource_type_to_idp["urn:connector:identos:jira-user"] = "atlassian" to data.oauth_config.user.idp_selection. (A general connector-install-time wiring of this mapping is on the roadmap; until then, set manually.)

See also