Skip to main content
OAuth apps let you build integrations that act on behalf of other fsckmsft users — without ever handling their passwords. When a user installs your app, they grant it specific permissions through a standard OAuth 2.0 authorization flow. Use OAuth apps whenever your integration needs to access data across multiple workspaces or be distributed to third parties.
If you only need to call the API from your own backend scripts, use API keys instead. OAuth apps are the right choice when your integration acts on behalf of other users.

When to use an OAuth app

Multi-tenant integrations

Build a product that connects to many different fsckmsft workspaces, with each workspace owner authorizing your app independently.

Marketplace listings

List your integration in the fsckmsft Marketplace. Only OAuth apps are eligible for Marketplace distribution.

User-context actions

Perform actions that appear in audit logs as the authorizing user rather than a service account.

Scoped, revocable access

Users can revoke your app’s access at any time from their account settings, without affecting other integrations.

Register an OAuth app

1

Open OAuth Apps settings

Navigate to Settings → Developer → OAuth Apps and click New OAuth App.
2

Fill in the application details

name
string
required
A human-readable name for your app. Users see this name on the authorization consent screen.
description
string
A brief description of what your app does and why it needs access.
homepage_url
string
required
The URL of your application’s home page or documentation.
redirect_uris
string[]
required
One or more fully-qualified HTTPS URIs that fsckmsft redirects the user to after authorization. Wildcards are not allowed — each URI must be an exact match.
scopes
string[]
required
The permission scopes your app will request. You can only request scopes you declare here. Request the minimum set your app requires.
3

Save your credentials

After creating the app, fsckmsft displays your Client ID and Client Secret.
The client secret is shown only once. Store it immediately in a secrets manager. If you lose it, go to your app’s settings and generate a new secret — all existing tokens issued with the old secret will be invalidated.

Authorization code flow

fsckmsft uses the OAuth 2.0 Authorization Code flow. Never use the Implicit flow — it is not supported and considered insecure.

Step 1 — Redirect the user to the authorization endpoint

Construct an authorization URL and redirect the user’s browser to it:
https://auth.fsckmsft.org/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.example.com/callback
  &response_type=code
  &scope=read:projects write:tasks
  &state=RANDOM_CSRF_TOKEN
client_id
string
required
Your app’s Client ID.
redirect_uri
string
required
Must exactly match one of the redirect URIs registered with your app.
response_type
string
required
Always code.
scope
string
required
Space-separated list of scopes your app is requesting.
state
string
required
A random, unguessable string you generate. fsckmsft echoes it back in the redirect. Verify it matches to prevent CSRF attacks.

Step 2 — Handle the callback

After the user approves (or denies) the request, fsckmsft redirects them to your redirect_uri:
https://yourapp.example.com/callback?code=AUTH_CODE&state=RANDOM_CSRF_TOKEN
Verify the state parameter matches what you generated. Extract the code value.

Step 3 — Exchange the code for an access token

Make a server-side POST request to exchange the authorization code for tokens:
curl -X POST https://auth.fsckmsft.org/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTH_CODE" \
  -d "redirect_uri=https://yourapp.example.com/callback" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"
A successful response returns:
{
  "access_token": "act_xxxxxxxxxxxxxxxxxxxx",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "rft_xxxxxxxxxxxxxxxxxxxx",
  "scope": "read:projects write:tasks"
}
Never exchange the authorization code from the browser. This request must be made from your backend server where the client secret is stored securely.

Step 4 — Call the API with the access token

Use the access token exactly like an API key — include it in the Authorization header:
curl -H "Authorization: Bearer act_xxxxxxxxxxxxxxxxxxxx" \
     https://api.fsckmsft.org/v1/projects

Refresh token flow

Access tokens expire after 60 minutes. Use the refresh token to obtain a new access token without requiring the user to re-authorize:
curl -X POST https://auth.fsckmsft.org/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=rft_xxxxxxxxxxxxxxxxxxxx" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"
The response includes a new access_token and a new refresh_token. Replace both in your token store — each refresh token can only be used once.
Refresh tokens expire after 90 days of inactivity. If a refresh token expires, the user must re-authorize your app.

Manage your OAuth app

From Settings → Developer → OAuth Apps, you can:
  • Edit your app’s name, description, homepage URL, redirect URIs, and scopes at any time.
  • Rotate the client secret — generates a new secret and immediately invalidates the old one. All previously issued access tokens remain valid until they expire.
  • View authorized workspaces — see how many workspaces have active authorizations for your app.
  • Delete the app — permanently removes the app and revokes all active tokens. This action cannot be undone.

Security best practices

Always validate state

Check that the state parameter in the callback exactly matches what you sent. Skip this check and your app is vulnerable to CSRF attacks.

Store tokens securely

Store access and refresh tokens with the same care as passwords — encrypted at rest, never in browser localStorage for sensitive apps.

Request minimal scopes

Request only the scopes your app actively uses. Users are more likely to authorize apps with narrow, clearly justified permissions.

Handle token expiry gracefully

Build automatic token refresh into your API client so users never encounter unexpected 401 errors mid-session.