Skip to content

feat(credentials): add Atlassian service account credentials#4432

Open
TheodoreSpeaks wants to merge 60 commits intostagingfrom
feat/atlassian-service-account
Open

feat(credentials): add Atlassian service account credentials#4432
TheodoreSpeaks wants to merge 60 commits intostagingfrom
feat/atlassian-service-account

Conversation

@TheodoreSpeaks
Copy link
Copy Markdown
Collaborator

Summary

  • Add atlassian-service-account credential type backed by a scoped Atlassian API token, surfaced in Jira and Confluence credential dropdowns alongside OAuth
  • Validate via the gateway flow: _edge/tenant_info (unauth) to discover cloudId, then api.atlassian.com/ex/jira/{cloudId}/rest/api/3/myself with Bearer to verify the token works
  • Plumb cloudId from the token route through tools and selectors so blocks skip the runtime accessible-resources call (which 401s for scoped service-account tokens)
  • Extract reusable ServiceAccountForm (Google JSON-key paste/upload) and new AtlassianServiceAccountForm (token + domain) from integrations-manager; map typed server error codes to friendly inline copy
  • Lift code from error response bodies into ApiClientError.code so any form/hook can switch on it without re-parsing

Type of Change

  • New feature

Testing

Tested manually end-to-end (credential creation, project picker, runtime block call). bun run lint and bun run check:api-validation:strict both pass.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

waleedlatif1 and others added 30 commits April 3, 2026 23:30
…ership workflow edits via sockets, ui improvements
…ration, signup method feature flags, SSO improvements
* feat(posthog): Add tracking on mothership abort (#4023)

Co-authored-by: Theodore Li <theo@sim.ai>

* fix(login): fix captcha headers for manual login  (#4025)

* fix(signup): fix turnstile key loading

* fix(login): fix captcha header passing

* Catch user already exists, remove login form captcha
…nts, secrets performance, polling refactors, drag resources in mothership
…endar triggers, docs updates, integrations/models pages improvements
…mat, logs performance improvements

fix(csp): add missing analytics domains, remove unsafe-eval, fix workspace CSP gap (#4179)
fix(landing): return 404 for invalid dynamic route slugs (#4182)
improvement(seo): optimize sitemaps, robots.txt, and core web vitals across sim and docs (#4170)
fix(gemini): support structured output with tools on Gemini 3 models (#4184)
feat(brightdata): add Bright Data integration with 8 tools (#4183)
fix(mothership): fix superagent credentials (#4185)
fix(logs): close sidebar when selected log disappears from filtered list; cleanup (#4186)
v0.6.46: mothership streaming fixes, brightdata integration
Comment thread apps/sim/lib/oauth/oauth.ts Outdated
Comment thread apps/sim/app/api/auth/atlassian-service-account/route.ts Outdated
Comment thread apps/sim/app/api/auth/atlassian-service-account/route.ts Outdated
- Collapse fetchOAuthTokenBundle into fetchOAuthToken (returns the bundle)
- Reuse serviceAccountJsonSchema in the JSON form instead of hand-rolled checks
- Use parseAtlassianErrorMessage for log details; drop one-line bearer helper
- Extract ATLASSIAN_SERVICE_ACCOUNT_PROVIDER_ID/_SECRET_TYPE constants
- Use Drizzle .returning() instead of post-insert SELECT
- Helper for the duplicated 401/403 + non-OK pattern in the validator
Comment thread apps/sim/lib/oauth/oauth.ts
- New /integrations/atlassian-service-account doc covers token creation,
  scope selection, and adding the credential to Sim
- Form's "View setup guide" link now points at the doc
- Fix the existing Google form link that pointed to the wrong path

Screenshot TODOs left inline as MDX comments for the docs team.
Comment thread apps/sim/app/api/auth/atlassian-service-account/route.ts Outdated
- Auth type picker, Sim add-credential modal, Jira block credential dropdown
- Scope-picker screenshot still TODO
- Drop stale 'email and API token' copy from the service description
  (we only collect a token + domain, no email field)
- Move duplicate display-name check inside the create transaction so
  concurrent POSTs can't both pass the check and insert duplicates
Docs site serves /static/* from apps/docs/public, not apps/sim/public —
matches the existing google-service-account screenshot convention.
…e-account

# Conflicts:
#	scripts/check-api-validation-contracts.ts
- SSRF: only accept *.atlassian.net / *.jira-dev.com hosts before fetching
  tenant_info, blocking probes against localhost/internal IPs
- Confluence spaces selector: pull cloudId from the SA secret instead of
  calling accessible-resources, which 401s for scoped service-account tokens
- Case-insensitive https?:// strip so HTTPS://team.atlassian.net normalizes
  correctly
@gitguardian
Copy link
Copy Markdown

gitguardian Bot commented May 5, 2026

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
29606901 Triggered Generic High Entropy Secret a54dcbe apps/sim/providers/utils.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Comment thread apps/sim/app/api/auth/atlassian-service-account/route.ts Outdated
Comment thread apps/sim/app/api/tools/confluence/selector-spaces/route.ts Outdated
Atlassian SAs were hitting resolveOAuthAccountId twice (once via
refreshAccessTokenIfNeeded, once directly to read cloudId) and
decrypting the secret twice (via getAtlassianServiceAccountToken
inside refresh, then again via getAtlassianServiceAccountSecret).

Resolve once up front and branch the whole flow on the result —
SA path skips refresh entirely and pulls token+cloudId from a
single secret read.
Comment thread apps/sim/app/api/tools/confluence/selector-spaces/route.ts
…edentials

Atlassian service-account creation lived in its own route, contract, and
mutation hook, copy-pasting ~140 lines of insert/membership/audit/posthog
boilerplate from /api/credentials. Two endpoints means two authz paths,
two audit shapes, two TOCTOU stories — they will drift.

Fold Atlassian into the existing service_account branch of /api/credentials,
dispatching by providerId. The Atlassian validator (tenant_info + Bearer
/myself, SSRF host allowlist, typed error codes) lives in
lib/credentials/atlassian-service-account.ts and is the only Atlassian-
specific piece left. AtlassianValidationError maps to a {code, error} 400
in the existing catch block; the rest of the flow (transaction, members,
audit, posthog, dup-check) is now shared with Google SA + env credentials.

Delete:
- /api/auth/atlassian-service-account route
- contracts/atlassian-service-account.ts + barrel export
- useCreateAtlassianServiceAccount hook
- API audit baseline 727 → 726

Both forms (Google JSON-key, Atlassian token+domain) now call
useCreateWorkspaceCredential with the appropriate body shape.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e017f19. Configure here.

"We couldn't authenticate with that API token. Double-check the token and that the service account has access to this site.",
site_not_found:
"We couldn't find an Atlassian site at that domain. Check the spelling — it should look like your-team.atlassian.net.",
duplicate_display_name: 'A credential with that name already exists in this workspace.',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreachable duplicate_display_name error code mapping is dead code

Low Severity

The duplicate_display_name key in ERROR_MESSAGES can never be matched. The server's AtlassianValidationError handler in the credentials route returns { code: error.code } where error.code is typed as AtlassianValidationCode, which only includes invalid_credentials, site_not_found, and atlassian_unavailable. The existing duplicate-credential detection paths (findExistingCredentialBySource returning 409, or the 23505 DB constraint handler) return responses without a code field, so codeFromErrorBody yields undefined on the client. Users who hit a duplicate see the generic fallback message instead of the intended friendly copy.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e017f19. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants