These pages describe PrivacyFence 7.0.2. Download it · What changed
Atlassian setup (Jira and Confluence)¶
PrivacyFence connects to Jira Cloud and Confluence Cloud through one Atlassian OAuth 2.0 (3LO) app: a single sign-in covers both connectors.
You need this page only to use your organization's own app instead of the built-in one. An organization server and the Docker image offer Jira and Confluence with PrivacyFence's built-in app, and each person approves it in their browser from PrivacyFence; there is nothing extra to set up.
Do not mark the built-in PrivacyFence app as trusted or pre-approved: that trust would extend to every PrivacyFence server and to anyone using the public app. To trust an app, register your own.
Your own app is a signed connector config uploaded on Admin → Services on an organization
server, and an atlassian section in the bundle on a desktop install (desktop installs have no
built-in app; see moving to organization mode).
PrivacyFence supports Atlassian Cloud (*.atlassian.net sites) only, not Jira or Confluence Data
Center or Server.
What you need¶
- An Atlassian account that can create apps in the developer console.
- Python 3 to run
scripts/sign_connector_config.py(organization server) orscripts/build_org_bundle.py(desktop install), or a browser for the offline signing page. - Which deployment you are building for. An Atlassian app has a single callback URL, so desktop installs and an organization server each need their own app (and their own connector config or bundle). If you run only one kind, you need only one app.
Register the app¶
- In the developer console, Create → OAuth
2.0 integration. Name it (for example
PrivacyFence, orPrivacyFence (server)for the organization server's app) and click Create. - Authorization → OAuth 2.0 (3LO) → Add/Configure: set the Callback URL to the local redirect (desktop installs' app) or the org redirect (the server's app) from the values table.
- Permissions: add the Jira API and Confluence API, then their scopes from the values table. The two products need different kinds of scope:
- Jira: classic scopes. Jira works with them, and Atlassian recommends classic scopes for Jira where they exist. Granular Jira scopes do not map one-to-one and fail with 401 "scope does not match".
- Confluence: granular scopes. The Confluence v2 API that PrivacyFence uses to list spaces accepts only granular-scoped tokens and returns 401 "scope does not match" for classic ones.
Classic and granular scopes are separate per product, so mixing them in one app is fine.
offline_access (which lets PrivacyFence refresh the token without a new sign-in) is not in the
Permissions picker; PrivacyFence adds it to the sign-in request itself.
4. Settings: copy the Client ID and Secret.
5. Distribution → Edit: set Distribution status to Sharing. A new app is in
development, and Atlassian lets only the account that created it sign in; everyone else gets
"You don't have access to this app". Sharing is required, even for an app used only inside
your organization; it publishes nothing, and nobody can sign in without the client ID from your
bundle. Atlassian asks for:
- Vendor name, privacy policy and support contact: your organization's own. Your
organization runs the app and is responsible for the data it handles; PrivacyFence's privacy
policy covers only its website and download service, not the software.
- Personal data declaration: answer that the app stores personal data, and confirm that
it uses the Personal Data Reporting API. PrivacyFence caches the account ids and display
names it shows, and reports them (see Personal data reporting).
Sharing takes effect at once and changes neither the client ID nor the secret, so a bundle built before it keeps working. If you run both kinds of deployment, share both apps.
Changing an app's scopes later does not change existing tokens: each user must Reconnect… Jira or Confluence to get a token with the new scopes.
Values¶
| Item | Value |
|---|---|
| Local redirect (desktop installs' app) | http://127.0.0.1:53684/callback — exactly this; Atlassian matches the string literally, so localhost does not match |
| Org redirect (organization server's app) | https://<server>/oauth/callback/atlassian, with <server> your server's public address (PRIVACYFENCE_ISSUER_URL). The same URL serves both Jira and Confluence. |
| Jira scopes (classic) | read:jira-work, write:jira-work, read:jira-user |
| Confluence scopes (granular) | read:space:confluence, read:page:confluence, write:page:confluence, read:content:confluence, read:content-details:confluence, write:content:confluence, read:attachment:confluence |
| Added automatically | offline_access |
| Bundle flags | --atlassian-client-id <Client ID> and --atlassian-client-secret <Secret> (both required together) |
What the Confluence scopes gate: read:content-details:confluence covers CQL and text search and
content details; write:content:confluence is needed with write:page:confluence to create pages;
read:attachment:confluence covers both listing (confluence_list_attachments) and downloading
(confluence_download_attachment) attachments. PrivacyFence requests no delete scope: no connector
can delete Jira or Confluence content.
Names and mentions¶
Jira's user API (read:jira-user) resolves account ids to names for both products, so no extra
scope is needed. PrivacyFence looks each person up once and keeps the name per user in
atlassian_user_cache.json, fetching it again after 7 days; how long it is kept is under
Personal data reporting. jira_refresh_user_cache and
confluence_refresh_user_cache fetch the cached names again.
Jira and Confluence then show @mentioned people, and Confluence page authors, by name. The agent
mentions someone with @[Name] followed by the account id in parentheses and finds the id with jira_find_users or
confluence_find_users. The approval card names each mentioned or assigned person with
Atlassian's own name.
A Confluence-only site (no Jira product) cannot look names up: page authors show as raw account ids, mentions as "unknown user", and it cannot use mention markup.
Personal data reporting¶
The names cache is Atlassian personal data, so PrivacyFence reports it to Atlassian's personal data reporting API (ADR 0202):
- Each install, or each user of an organization server, reports the account ids in its own cache
with its own sign-in, once per cycle: 7 days, unless Atlassian answers with a different
Cycle-Period. No extra scope or reconnect is needed. Reports start in the background after Jira or Confluence connects, or after a lookup, at most once an hour. - An account Atlassian reports as closed or changed is erased from the cache at once. A changed account's name is fetched again the next time it is needed.
- An entry that has been neither fetched nor reported for a cycle and a day is erased. A sweep at startup and every six hours does this for every user's cache, including organization-server users who are not signed in, so a name never stays on disk unreported.
A failed report is logged as "Atlassian personal data report not sent (will retry)" and tried again an hour later; until a report succeeds, the cached names expire as above. The audit log is not part of this: it records names and account ids from approved requests and is kept under your own retention policy, because rewriting it would break its integrity chain.
Fields¶
jira_list_fields lists the site's fields with their ids and JQL names, so the agent can use the
names you see in Jira. jira_search_issues returns a fixed set of fields without asking. To read
other fields, custom fields included, the agent uses jira_search_issues_with_fields or the
fields parameter of jira_get_issue, and you review the values on the approval card first. No
extra scope is needed. jira_export_issues writes a whole search, up to 10,000 issues, to a CSV or JSON file in one approval, and the same "this project" rule covers it.
Give PrivacyFence the app¶
On an organization server, sign the client ID and secret as a connector config and upload it on Admin → Services (the Atlassian row, Upload a connector config…):
python3 scripts/sign_connector_config.py keygen --out connector_signing_key.pem # once
python3 scripts/sign_connector_config.py sign --provider atlassian --serial 1 \
--client-id abcdef01234567890 --client-secret-file atlassian_secret.txt \
--key connector_signing_key.pem --output atlassian.connector.txt
Uploading asks for a passkey (the first upload also asks you to check the signing key's fingerprint). Remove our own app on the row goes back to the built-in app. Either change makes everyone who connected Jira or Confluence sign in again. The signing tools and the serial rule are described in org-mode-setup-guide.md.
On a desktop install, put them in the bundle:
python3 scripts/build_org_bundle.py \
--atlassian-client-id abcdef01234567890 \
--atlassian-client-secret abcdef0123456789abcdef0123456789 \
-o org_bundle.json --merge
--merge adds Atlassian to an existing bundle; drop it if this is the first service in the bundle.
Install it on Admin → Organization configuration
(connecting-a-service.md).
Jira Assets¶
The optional Jira Assets connector (read-only) lets an agent browse Assets schemas, search objects with AQL, read linked objects and connected tickets, and export objects. It needs a Jira Service Management site with Assets enabled. It is off by default, and the extra permissions are requested only when it is switched on, so Jira and Confluence users who never use it are not asked for anything new.
| Item | Value |
|---|---|
| Assets scopes (granular, under the Jira API) | read:cmdb-schema:jira, read:cmdb-type:jira, read:cmdb-attribute:jira, read:cmdb-object:jira |
| Where it is switched on | Admin → Features → Jira Assets: a switch and an optional workspace id. The bundle flags --atlassian-assets and --atlassian-assets-workspace-id are refused; they moved to the Admin page. |
| Workspace id setting | connectors.assets.workspace_id in a person's own settings, which wins over the Admin page's |
- In the developer console, open the app, go to Permissions, click Configure next to Jira API, and add the four scopes above on the Granular scopes tab.
- Find the site's Assets workspace id: signed in to the site in a browser, open
https://<your-site>.atlassian.net/rest/servicedeskapi/assets/workspaceand copyworkspaceId. Enter it under Admin → Features → Jira Assets, or put it in each user's settings asconnectors.assets.workspace_id. PrivacyFence cannot look it up itself: Atlassian answers that lookup only for the Jira Service Management scoperead:servicedesk-request, which the developer console does not offer every app, and asking for a scope the app lacks fails the whole sign-in. - Switch Assets on: turn on Jira Assets under Admin → Features for everyone, or, on a
desktop install, enable it in Settings → Connectors. An explicit
connectors.assets.enabledsetting wins over the Admin page's switch. - Authenticate again (Authenticate… on Jira Assets, or Reconnect…) so Atlassian shows the
extra consent. Tokens made before Assets was on do not have the permissions.
In org mode, Assets has no sign-in of its own: it uses the Jira and Confluence sign-in on
/connect, where a Jira Assets row says whether that sign-in has the Assets permissions and offers Reconnect when it does not.
Users connect¶
Users click Authenticate… next to Jira or Confluence (desktop install, after the bundle is installed) or Connect (organization server), then sign in and click Accept on Atlassian's page. Either button connects both products. The shared flow is described in connecting-a-service.md. Atlassian-specific points:
- More than one site: a desktop install asks which site to connect; an organization server connects the first site the account can reach. A user who needs a different site on an organization server needs an Atlassian account limited to that site.
- The token refreshes itself; users sign in again only when it is revoked or the app's scopes change.
Troubleshooting¶
"The app's callback URL is invalid" during sign-in — the app's Callback URL does not match the
deployment it is used for: exactly http://127.0.0.1:53684/callback for desktop installs, or
https://<server>/oauth/callback/atlassian for an organization server. An app holds only one, so
check that the connector config or bundle contains the right app's credentials.
"You don't have access to this app. This application is in development" on Atlassian's page — the app is not shared, so only its creator can sign in. Set its Distribution status to Sharing (step 5 of Register the app), then sign in again.
The log shows "Atlassian personal data report not sent (will retry)" — Atlassian refused or could not take the report. Check the error after it; a 401 that a reconnect does not fix means Atlassian did not accept the user's token for reporting. Cached names still expire a cycle and a day after they were last fetched, so nothing is kept unreported.
401 right after connecting — check the Callback URL (above) and that both the Jira API and the Confluence API, with their scopes, are on the app.
Confluence connects, but space or page calls fail with 401 "scope does not match" — the Confluence scopes were added as classic scopes. Add the granular ones listed above, then have users Reconnect….
Jira fails with 401 "scope does not match" — the Jira scopes were added as granular scopes. Switch Jira back to the classic scopes listed above, then have users Reconnect….
confluence_list_attachments or confluence_download_attachment fail with 401 — the
read:attachment:confluence scope is missing from the app, or the user's token predates it. Add
the scope if needed, then have the user Reconnect….
Page authors show raw account ids, mentions show "unknown user" (Confluence) or Jira's own label, or a write fails with "Unknown Atlassian account id" — the site has no Jira product, or the "Browse users and groups" global permission was removed for the user.
403 on specific projects or spaces — the user's Atlassian account has no access to that project or space. Check permissions in Jira or Confluence.
Wrong site connected — on a desktop install, Reconnect… and pick the other site.
Jira Assets says "needs an extra Atlassian permission. Use Authenticate… on Jira Assets in PrivacyFence Settings." — the saved sign-in was made before Assets was switched on, or without the four Assets scopes. Check that Assets is on, that the app has the scopes, then use Authenticate… on Jira Assets.
Jira Assets says "This Atlassian site has no Assets workspace (Jira Service Management Assets is not enabled)." — the connected site has no Assets workspace. Enable Assets on a Jira Service Management site, or connect a site that has it.
Jira Assets says "could not look up this site's Assets workspace id" — no workspace id is configured. Set it as step 2 of the Jira Assets setup describes.
Jira Assets fails with check_connection failed: 404 Error — the configured workspace id is not
this site's. Look it up again on the site the user connected.