A Jira tracker can authenticate through a Marketplace app, Atlassian OAuth, or a user-supplied API token. Those models expose different systems and revoke differently. Atlassian’s token management docs treat an API token as a personal credential, while OAuth uses an explicit app consent. The useful security question is no longer just “where did the pasted token go?” It is “which long-lived credential exists, who can use it, and which infrastructure sees it during sign-in and sync?”
We built one of the trackers in this list, Planim Time, around device-held long-lived credentials. Version 0.4 added Sign in with Atlassian as the default while keeping API-token auth as a local fallback. The goal here is to put the actual auth model each tracker uses on the table, including the short-lived broker involved in our OAuth flow, so the trade-offs are visible.
The threat model, in one paragraph
A Jira API token is a bearer credential: anyone holding the cleartext can act as you against the Jira REST API. The interesting question for any tracker isn’t “is the token encrypted?” It always is, in transit and at rest. The interesting question is who else holds the cleartext, and under what circumstances does it become reachable? A token in your OS keychain is reachable to processes running as you, on this machine. A token in a vendor’s cloud is reachable to that vendor’s infrastructure, their on-call engineers, anyone who breaches them, and any subpoena that lands on their doorstep. Both are defensible designs. They just have very different blast radii.
Four auth models in this category
Every Jira time tracker authenticates with Jira using one of four shapes:
1. Atlassian Marketplace app (Connect or Forge). A Jira admin installs the app into the tenant, but the two frameworks have different trust boundaries. A Connect app exchanges an installation secret and typically authenticates from vendor infrastructure with signed JWTs. A Forge app runs in Atlassian’s isolated runtime, uses declared scopes and platform-managed API access, and can only reach external domains allowed by its manifest. Forge Remotes can still involve vendor infrastructure, so “Marketplace app” alone does not tell you where every component or credential lives.
2. Atlassian OAuth 3LO. The user approves an app in Atlassian’s browser flow. The app receives scoped access and refresh credentials instead of a manually copied API token. A web app normally stores those credentials on its backend. A desktop app can keep them in the OS keychain, although it may still use a backend broker for the confidential code exchange or token refresh.
3. User-supplied API token, vendor-stored. The user generates a personal Atlassian API token, pastes it into a vendor signup form, and the vendor uses it to call Jira on the user’s behalf. The token sits in the vendor’s database, encrypted at rest.
4. User-supplied API token, locally stored. The user pastes a token into a desktop app, and the app saves it to the OS credential vault: Keychain on macOS, Credential Manager on Windows, Secret Service on Linux. The vendor’s servers never see the token.
Each model trades a different thing. Marketplace apps centralise install and revoke through Jira, but Connect and Forge do not share one credential architecture. OAuth provides scoped consent but may introduce a token broker or vendor credential store. Vendor-stored API tokens expand the vendor’s breach surface. Locally stored tokens reduce that surface but are per-machine by design.
Tempo Timesheets
Tempo Timesheets is a Marketplace plugin that is actively migrating from Connect to Forge. The rollout is gradual, so a tenant can still be on the legacy Connect version or already on Forge. A Jira admin installs the app and users do not paste a Jira API token for the core integration, but the exact runtime and authentication boundary now depends on the installed app version.
Tempo also issues its own personal API tokens for Tempo’s REST APIs. These are separate from Jira tokens and only authenticate calls to Tempo, not to Jira. They’re shown once and stored on Tempo’s side. There’s a known administrative gap here: only the user who created a Tempo API key can view or revoke it, which becomes uncomfortable during offboarding. If a developer leaves and IT doesn’t think to ask them to revoke their Tempo key first, that key can outlive their employment. Tempo’s product team has acknowledged the request for centralised admin; check the linked idea for current status.
Where the credential state lives: the Atlassian platform and, depending on the installed Connect/Forge architecture, Tempo infrastructure. For Tempo API users, Tempo’s own API token remains a separate Tempo-side credential.
Clockwork (HeroCoders)
Clockwork is a Marketplace plugin installed and authorised by a Jira admin. HeroCoders completed Clockwork’s move to Forge in March 2026. Forge puts the app inside Atlassian’s runtime and platform-managed authorization model, though that does not automatically mean every component and stored record stays within Atlassian: HeroCoders says Clockwork does not yet carry the stricter Runs on Atlassian badge. HeroCoders is also a Cloud Fortified vendor.
Clockwork also publishes its own REST API with user-generated API tokens, used for scripting against Clockwork itself. Same shape as Tempo: tokens issued in Clockwork’s UI, stored in HeroCoders’ backend, scoped to that user’s Jira permissions.
Where the credential state lives: Atlassian’s Forge authorization and runtime, plus the Clockwork service where its architecture uses vendor infrastructure. Clockwork’s own user-generated API tokens are separate credentials managed by HeroCoders.
Everhour
Everhour is a hybrid: a Marketplace add-on that surfaces the timer inside Jira, plus an Everhour cloud account that holds time data, projects, budgets, and integrations. The Jira side uses the Marketplace install path; the Everhour side requires an Everhour account. With worklog sync enabled, Everhour entries are written to native Jira worklogs and later edits to those linked worklogs can flow back to Everhour. Historical worklogs and new entries created directly in Jira are not imported into Everhour, so this is not a complete two-way mirror.
If you also use Everhour for non-Jira tools (GitHub, Trello, Asana, etc.), each of those integrations stores its credentials in your Everhour cloud account. None of those credentials live on your machine.
Where the credential and integration state lives: Atlassian’s tenant (Marketplace install) + Everhour’s backend (Everhour account, integration state, and any non-Jira integration credentials).
Clockify
Clockify’s current Jira Cloud integration is a free Atlassian Marketplace app. A Jira admin installs it and each user connects a Clockify account. Clockify documents two-way sync between Jira worklogs and Clockify entries. That Cloud path should not be described as “paste a personal Jira API token into Clockify”; the relevant trust boundary is the Marketplace app plus Clockify’s cloud account and integration state.
Clockify’s own API uses an X-Api-Key HTTP header containing a key generated in your Clockify profile. That key authenticates against Clockify, not Jira; same storage location.
Where the cleartext lives: no user-supplied Jira API token in the documented Jira Cloud path; Atlassian Marketplace authorization and Clockify account/integration credentials span Atlassian and Clockify infrastructure. Clockify API keys remain separate Clockify credentials.
Planim Time
Planim Time is a native desktop app for macOS, Windows, and Linux. Sign in with Atlassian is the default. Long-lived OAuth access and refresh credentials are stored in the OS keychain. A short-lived backend broker handles the OAuth code exchange and refresh response, then passes the result to the app; it does not remain the long-term token store. The optional API-token fallback is simpler: that Jira token never leaves the machine.
The local storage implementation is small enough to print:
use keyring::Entry;
const SERVICE: &str = "planim-time-tracker";
pub fn set_secret(key: &str, value: &str) -> Result<(), String> {
Entry::new(SERVICE, key)
.map_err(|e| format!("Keyring entry error: {e}"))?
.set_password(value)
.map_err(|e| format!("Failed to save to keyring: {e}"))
}
pub fn get_secret(key: &str) -> Result<Option<String>, String> {
match Entry::new(SERVICE, key)
.map_err(|e| format!("Keyring entry error: {e}"))?
.get_password()
{
Ok(v) => Ok(Some(v)),
Err(keyring::Error::NoEntry) => Ok(None),
Err(e) => Err(format!("Failed to read from keyring: {e}")),
}
}
That’s the entire storage layer. The keyring crate wraps three platform APIs:
- macOS: Keychain Services, the same vault Safari uses for saved passwords
- Windows: Credential Manager, accessed via the Win32 Credential Vault APIs
- Linux: Secret Service over D-Bus, which is what GNOME Keyring and KWallet implement
For OAuth, the broker sees token material transiently during sign-in and refresh, while the desktop app holds the long-lived copy in the keychain and talks to Jira directly. For the API-token fallback, our backend never sees the Jira token at all. License checks are a separate flow. Credentials can be removed from the app or the system vault. For example, on macOS:
security find-generic-password -s planim-time-tracker
security delete-generic-password -s planim-time-tracker
I wrote a longer technical post on the implementation if you want the rationale at code-review depth.
Where the cleartext lives: long-lived copy in the OS keychain; OAuth broker memory and short-lived handshake state during exchange/refresh; API-token fallback only in the OS keychain.
Quick comparison
| Tracker | Auth model for Jira | Where cleartext lives | Admin revoke |
|---|---|---|---|
| Tempo Timesheets | Connect or Forge, depending on rollout state | Atlassian platform + Tempo infrastructure, boundary depends on installed version | Jira admin for the app; user only for Tempo API tokens |
| Clockwork | Atlassian Forge | Atlassian runtime + Clockwork service | Jira admin (Forge); user only (Clockwork API) |
| Everhour | Marketplace install + Everhour account | Atlassian tenant + Everhour backend | Jira admin + Everhour admin |
| Clockify | Marketplace app + Clockify account (Jira Cloud) | Atlassian + Clockify integration infrastructure | Jira admin / Clockify admin and user disconnect controls |
| Planim Time | Atlassian OAuth 3LO; local API-token fallback | OS keychain long-term; OAuth broker transiently | Atlassian app revoke or local delete; token revoke for fallback |
What your IT team should ask
When the security review form lands on someone’s desk, the questions worth asking are concrete, not generic:
- Where, exactly, is the cleartext credential stored? “Encrypted at rest” is necessary but not interesting; you want a name (vendor backend / Atlassian tenant / OS keychain).
- Who can revoke it without involving the user? A token only the original user can revoke is a problem at offboarding.
- What happens if the vendor is breached? Map your token’s blast radius the same way you’d map any other credential.
- Does the vendor decrypt the token in the request lifecycle? Some vendors decrypt server-side to make the API call; others act as opaque proxies. The first model means cleartext is reachable to vendor on-call engineers.
- Is the integration Cloud Fortified or Forge-published? For Marketplace plugins this is the closest thing to a default certification.
What we ended up choosing, and why
Picking the OS keychain as the long-term store means accepting a few constraints. Credentials are per-machine, so a laptop and desktop each need a sign-in. There is no Planim admin panel holding Jira refresh tokens for the whole team. OAuth makes onboarding easier than the old paste-token path while preserving device-held long-lived credentials.
What we got back: our database, backups, and support tooling are not the long-term store for Jira credentials. The important qualification is that the OAuth broker handles token material transiently during exchange and refresh. For teams whose review asks “does the vendor retain our Jira credentials?” the answer is no; for “does vendor infrastructure ever process OAuth tokens?” the answer is yes, briefly and for that purpose.
That trade-off only makes sense for a desktop-first product. If we’d built a web dashboard, we couldn’t have made it; the auth model and the product shape are the same decision. We wrote separately about why we shipped a desktop binary instead of a Marketplace plugin; this is the half of the rationale that lives in your security questionnaire.
If the storage side matters to your team, download Planim Time, sign in to a test site, and inspect Keychain Access on macOS (or Credential Manager on Windows, or seahorse on Linux). You will see the long-lived credential entry under planim-time-tracker; the security review should record the transient OAuth broker separately.