Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

How do you handle rotating OAuth 2.0 (3LO) refresh tokens in Bitbucket Pipelines?

Konrad
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
July 6, 2026

Hi everyone,

I'm running into an issue with OAuth 2.0 (3LO) authentication in our E2E tests and I'm wondering how others have solved it.

Our Playwright E2E tests use our app's REST API, which authenticates via Atlassian OAuth 2.0 (3LO). The authentication flow relies on a refresh token to obtain a new access token. As expected, every refresh request returns a new refresh token, so the token needs to be persisted for the next execution.

This works fine locally, but I'm struggling with running the tests in Bitbucket Pipelines.

The problem is that after each pipeline run I need to persist the newly returned refresh token somewhere. Bitbucket repository variables are read-only from the pipeline's perspective (at least they don't seem intended to be used as mutable storage), so I can't simply update the stored refresh token for the next pipeline run.

Has anyone faced a similar problem?

Some questions I have:

  • How do you handle rotating refresh tokens in CI/CD?

  • Is there a recommended approach for Atlassian 3LO authentication in automated pipelines?

  • Do you use an external secret store (AWS Secrets Manager, Vault, etc.), or is there another approach I'm missing?

  • Is there a better authentication mechanism for automated E2E tests that avoids this problem altogether?

I'd really appreciate hearing how others have implemented this.

Thanks!

2 answers

0 votes
Viswanathan Ramachandran
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Champions.
July 6, 2026

hi @Konrad 

I think the root cause is that 3LO isn’t really designed for unattended CI/CD workloads it’s built around delegated user authentication, so refresh token rotation is expected.

A few approaches you can consider to work well:

  • Don’t use 3LO in CI unless you’re specifically testing the OAuth flow. If your E2E tests are validating your application’s functionality rather than Atlassian’s authentication, it’s often better to isolate the auth layer or use an alternative authentication mechanism where possible.
  • Store the refresh token in an external secrets manager. This is probably the cleanest production-grade solution. Services like AWS Secrets Manager, HashiCorp Vault, Azure Key Vault, or GCP Secret Manager are all suitable for this.
  • Introduce a small token broker/auth service. Instead of every pipeline managing refresh token rotation, a lightweight internal service can own the OAuth lifecycle and simply return a valid access token to your tests. That keeps token rotation logic in one place and avoids pipeline state management entirely.

One thing I’d avoid is trying to use Bitbucket repository variables as mutable storage. They’re intended for configuration rather than runtime state, and updating them from pipelines can become problematic, if multiple pipeline runs overlap and race to update the latest refresh token.

Out of curiosity, are your playwright tests validating the OAuth flow itself, or are they primarily testing your app after authentication? That distinction would influence the recommended approach. If it’s the latter, I’d lean towards abstracting authentication away from the tests and letting the pipeline consume a valid access token rather than owning the refresh token lifecycle.

The documentation below clearly explains how rotating refresh tokens work and that applications must always persist the newly returned refresh token, but it doesn’t describe a recommended CI/CD strategy or where that token should be stored.

https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/?utm_source 

0 votes
Gabriela
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Champions.
July 6, 2026

Hi @Konrad, welcome to the community. For E2E tests that just hit the REST API as a user, drop 3LO in CI and the rotating-token problem disappears. Use Basic auth with an Atlassian API token — `Authorization: Basic base64("email:api_token")` — it doesn't rotate, so it sits fine in a secured Bitbucket repository variable. One caveat: API tokens now carry a max 1-year expiry, so you swap it yearly, not per run. If you truly need 3LO (per-user scoped tokens, or testing the flow itself), your instinct's right: each refresh returns a new single-use token and a pipeline can't rewrite its own repo variable, so an external store like Secrets Manager is the move. Basic auth for REST APIs

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
FREE
PERMISSIONS LEVEL
Product Admin Site Admin
TAGS
AUG Leaders

Atlassian Community Events