Application teams Time to first credentials about 10 minutes plus review

Request an OAuth client

You describe the client you need in a small file and open a pull request. Once it is approved and merged, Courier creates the client and places its credentials where only your team can read them. You never receive a secret by email or chat.

Before you start

  • Your team directory. Requests live under requests/<team>/, for example requests/team-alpha/. The directory name is also your identity-provider group. If your team has no directory yet, ask the identity team to add one along with its code owners.
  • Group membership. Anyone who should read the credentials must be in that group in the identity provider.
  • Your redirect URIs (for sign-in flows), on an approved domain such as *.sororlab.dev.

Choose a client type

You are buildingClient typeGrant typesGets a secret
A web app or MCP server that signs users inconfidentialauthorization_code, optionally refresh_tokenyes
A backend job or service calling APIs as itselfconfidentialclient_credentials needs approval labelyes
A desktop app, CLI, IDE plugin or single-page apppublicauthorization_code with PKCEno

If you are unsure, pick confidential for anything that runs on a server and public for anything installed on a user's device.

From Backstage (easiest)

In Backstage, open Create and choose Request an OAuth client. The form asks four things and opens the pull request for you. It writes exactly the files described in the next section.

Backstage Create page listing the Request an OAuth client template with its description and tags oauth, identity and courier
Create → Request an OAuth client.
  1. owner and name

    Pick your team (only Courier teams are offered), a client name and an optional display name.

  2. client

    Choose the client type and grants, and add redirect URIs and scopes.

  3. why

    Say what the client is for. It goes into the pull request for reviewers.

  4. review

    Check the summary and click Create. Backstage opens the pull request and links to it.

Backstage form step 1, Owner and name: owning team group:default/team-alpha, client name orders-portal, display name team-alpha orders portal
Step 1. The team picker lists only Courier teams.
Backstage form step 2, Client: grant types authorization_code and refresh_token checked, client_credentials unchecked with a note that it needs security approval, a redirect URI and the openid scope
Step 2. The form warns that client_credentials needs security approval.

After merge, your client appears on your team's page in Backstage, with its delivery status on the Kubernetes tab and a link to Use your credentials. See pull request #2 for a real run.

Or write the request by hand

Create requests/<team>/<name>.yaml. The file name must match metadata.name, and metadata.namespace must match your team directory.

A service that signs users in

# requests/team-alpha/orders-portal.yaml
apiVersion: courier.sororlab.dev/v1alpha1
kind: OAuthClient
metadata:
  name: orders-portal
  namespace: team-alpha
spec:
  displayName: "Orders portal"
  clientType: confidential
  grantTypes: [authorization_code, refresh_token]
  redirectUris:
    - https://orders.sororlab.dev/oauth/callback
  scopes: [openid, profile, email, offline_access]

A machine-to-machine job

# requests/team-alpha/billing-sync.yaml
apiVersion: courier.sororlab.dev/v1alpha1
kind: OAuthClient
metadata:
  name: billing-sync
  namespace: team-alpha
spec:
  clientType: confidential
  grantTypes: [client_credentials]
  scopes: [openid, profile, groups]

Optional fields: allowGroups lets additional groups sign in through the client (it defaults to your team). The full list is in the reference.

Check it locally (optional)

go run ./cmd/courier validate requests
# 3 request(s) valid

Open the pull request

  1. you

    Push a branch and open a pull request against main.

  2. check

    Client requests / Validate requests runs. Problems appear as annotations on the exact file, and the run summary shows a table of what will change.

  3. you

    Fix anything flagged and push again. The check re-runs automatically.

  4. approvers

    Your team's code owner reviews. If the request uses client_credentials, the identity or security team adds the security-approved label; the check re-runs when the label is added.

  5. you

    Merge once the check is green and approvals are in.

Example check summary

ChangeTeamClientTypeGrantsCredentials pathApproval
added or changedteam-alphabilling-syncconfidentialclient_credentialskv/teams/team-alpha/oauth-clients/team-alpha-billing-syncneeds label security-approved

Common check messages

MessageFix
metadata.name "x" must match the file name "y"Rename the file or the object so they match
metadata.namespace "x" must be the team directory "y"Set namespace to your team directory name
redirect URI ...: must use httpsUse https; plain http is only allowed for localhost on public clients
redirect URI host "x" is not in allowedRedirectHostsUse an approved domain, or ask the identity team to extend the policy
client_credentials requires a confidential clientChange clientType to confidential
needs the "security-approved" labelAsk the identity or security team to review and add the label
invalid OAuthClient: unknown fieldA field name is misspelled; compare with the examples above

After merge

Within a few minutes ArgoCD syncs your file and Courier delivers the credentials. To see the status, check your team's application in ArgoCD, or with cluster access:

kubectl -n team-alpha get oauthclients
NAME           READY   TYPE           CLIENT ID                     SECRET PATH
billing-sync   True    confidential   AVcNRtABgj6SSC8VUkON...      kv/teams/team-alpha/oauth-clients/team-alpha-billing-sync

If READY is False, kubectl -n team-alpha describe oauthclient billing-sync shows the reason. Most failures are retried automatically; NameConflict and InvalidSpec need a change to the request.

Read your credentials

The vault entry contains:

KeyExample
client_idAVcNRtABgj6SSC8VUkON…
client_secretconfidential clients only
issuer, token_endpoint, authorization_endpoint, jwks_uri, userinfo_endpointhttps://auth.sororlab.dev/application/o/team-alpha-billing-sync/
client_type, grant_types, scopes, owner_groupwhat you requested
stateactive when ready. Do not use pending credentials.

As a person, from your laptop

export VAULT_ADDR=https://vault.sororlab.dev
vault login -method=oidc
vault kv get kv/teams/team-alpha/oauth-clients/team-alpha-billing-sync
vault kv get -field=client_secret kv/teams/team-alpha/oauth-clients/team-alpha-billing-sync

From a workload

Log in with the workload's own identity, never with a person's token. Use your credentials covers the Python sample (JWT or Kubernetes service-account login) and External Secrets, which syncs the credentials into a Secret in your namespace using a store that is set up for your team automatically.

Handle it like any secret

Read the secret at runtime rather than copying it into configuration files, tickets or chat. If it is ever exposed, ask the identity team to rotate it; removing and re-adding the request also issues a new one.

Change or retire a client

  • Change it: edit the file and open a pull request. The client is updated in place and the secret stays the same.
  • Retire it: delete the file and open a pull request. After merge, the client is removed from the identity provider and its credentials are destroyed. Anything still using them stops working.

Questions

Can another team read our secret?

No. The vault path is scoped to your identity group. The check rejects requests whose owner is not your team directory, and the controller enforces the same rule.

Someone joined or left our team. What do we change?

Nothing in Courier. Update the group in the identity provider; vault access follows on their next sign-in.

We already have a client that was set up by hand.

Courier will not touch it, and a request with the same name reports NameConflict. Choose a new name; adopting existing clients is on the roadmap.

How fast is it?

In the reference environment the client is ready about four seconds after ArgoCD applies the merged file. ArgoCD itself polls Git every few minutes.