Skip to content

feat: Docs for client secret rotation#2424

Open
SamuelDev wants to merge 7 commits into
ory:masterfrom
SamuelDev:client-secret-rotation-docs
Open

feat: Docs for client secret rotation#2424
SamuelDev wants to merge 7 commits into
ory:masterfrom
SamuelDev:client-secret-rotation-docs

Conversation

@SamuelDev

Copy link
Copy Markdown

Related Issue or Design Document

Docs updates for client secret rotation

Checklist

  • I have read the contributing guidelines and signed the CLA.
  • I have referenced an issue containing the design document if my change introduces a new feature.
  • I have read the security policy.
  • I confirm that this pull request does not address a security vulnerability.
    If this pull request addresses a security vulnerability,
    I confirm that I got approval (please contact security@ory.com) from the maintainers to push the changes.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added the necessary documentation within the code base (if appropriate).

Further comments

@SamuelDev

Copy link
Copy Markdown
Author

Javascript integration test failure seems like a CI issue and unrelated to these changes

@vinckr vinckr added the upstream Issue is caused by an upstream dependency. label Jan 23, 2026
@alnr alnr added the area/docs This issue affects Ory's documentation. label Feb 10, 2026
@alnr

alnr commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@wassimoo @unatasha8 would you kindly take a look at this pls?

@vinckr vinckr force-pushed the client-secret-rotation-docs branch from 19afb45 to 29299a0 Compare February 11, 2026 23:14

@vinckr vinckr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm :) fixed some layout issues

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
## Rotate OAuth2 client secret

OAuth2 client secret rotation allows you to change a client's secret without downtime. When you rotate a secret, the old secret
remains valid until you explicitly clean it up, allowing you to update all services using the client credentials without service

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
remains valid until you explicitly clean it up, allowing you to update all services using the client credentials without service
remains valid until you remove it, allowing you to update all your services without service

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated

##### How secret rotation works

1. Rotate the secret: Generate a new secret for the client

@unatasha8 unatasha8 Feb 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
1. Rotate the secret: Generate a new secret for the client
1. Generate a new secret for the client service

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
##### How secret rotation works

1. Rotate the secret: Generate a new secret for the client
2. Both secrets work: Old and new secrets both authenticate until cleanup

@unatasha8 unatasha8 Feb 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be #3 not #2. The new secret won't work until you update the client application, right?
Move position and change to: "Both old and new secrets authenticate until you remove the old secret."

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated

1. Rotate the secret: Generate a new secret for the client
2. Both secrets work: Old and new secrets both authenticate until cleanup
3. Update services: Update your applications to use the new secret

@unatasha8 unatasha8 Feb 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
3. Update services: Update your applications to use the new secret
3. Update your client services to use the new secret

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
1. Rotate the secret: Generate a new secret for the client
2. Both secrets work: Old and new secrets both authenticate until cleanup
3. Update services: Update your applications to use the new secret
4. Cleanup: Manually remove old rotated secrets once all services are updated

@unatasha8 unatasha8 Feb 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
4. Cleanup: Manually remove old rotated secrets once all services are updated
4. After you test the client services can authenticate with the new secret, manually remove the old secret.

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated

##### Clear rotated secrets

Once all services have been updated to use the new secret, you can remove the old rotated secrets to revoke access using the old

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
Once all services have been updated to use the new secret, you can remove the old rotated secrets to revoke access using the old
Once all services are updated to use the new secret, remove the old secret to revoke access using the old

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
##### Clear rotated secrets

Once all services have been updated to use the new secret, you can remove the old rotated secrets to revoke access using the old
credentials:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
credentials:
secret:

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
-H "Authorization: Bearer ory_pat_..."
```

After cleanup, only the current secret will be valid. Old secrets will no longer authenticate.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
After cleanup, only the current secret will be valid. Old secrets will no longer authenticate.
After removing the old secret, only the current (new) secret is valid. The old secret can no longer authenticate.

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
id: clientId
})

// Old secrets are now revoked

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Old secrets are now revoked
// Old secret is now revoked.

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated

echo "New secret: $NEW_SECRET"

# 3. Update your applications with the new secret

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
# 3. Update your applications with the new secret
# 3. Update your client servcies with the new secret

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
-u "$CLIENT_ID:$NEW_SECRET" \
-d "grant_type=client_credentials"

# 5. Once all services are updated, clean up old secrets

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
# 5. Once all services are updated, clean up old secrets
# 5. Once all client services are updated, remove the old secret

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated

:::tip Zero-downtime credential rotation

Secret rotation enables zero-downtime credential updates. Both the old and new secrets remain valid until you manually clean up

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
Secret rotation enables zero-downtime credential updates. Both the old and new secrets remain valid until you manually clean up
Secret rotation enables zero-downtime credential updates. Both the old and new secrets remain valid until you manually remove

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
:::tip Zero-downtime credential rotation

Secret rotation enables zero-downtime credential updates. Both the old and new secrets remain valid until you manually clean up
the rotated secrets, allowing you to update all your services without service interruption.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
the rotated secrets, allowing you to update all your services without service interruption.
the old secret, allowing you to update all your client services without service interruption.

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated

:::warning Security best practice

Rotated secrets remain valid indefinitely until you explicitly clean them up. Always remove old rotated secrets once your

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
Rotated secrets remain valid indefinitely until you explicitly clean them up. Always remove old rotated secrets once your
Secrets remain valid indefinitely until you explicitly remove them. Always remove old secrets once your

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
:::warning Security best practice

Rotated secrets remain valid indefinitely until you explicitly clean them up. Always remove old rotated secrets once your
migration is complete to ensure that compromised credentials cannot be used.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
migration is complete to ensure that compromised credentials cannot be used.
secret rotation process is complete to ensure that compromised credentials cannot be used.

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated

:::warning Security best practice

Rotated secrets remain valid indefinitely until you explicitly clean them up. Always remove old rotated secrets once your

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"secrets remain valid indefinitely" Are you sure? Don't they have a validity date?

Deepak just added this feature: "The SAML connection includes a valid_to attribute, which is an array of expiry dates for the signing certificates associated". This might not directly link to your code as it's for SAML... but wanted to point it out to you.

3. Update services: Update your applications to use the new secret
4. Cleanup: Manually remove old rotated secrets once all services are updated

##### Rotate client secret

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
##### Rotate client secret
##### Rotate OAuth2 client secret

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
-H "Authorization: Bearer ory_pat_..."
```

The response includes the new `client_secret`. Save this value immediately - it will not be shown again.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Where should this be saved? Is there a secure location it should be saved to?

Comment thread docs/hydra/guides/oauth2-clients.mdx Outdated
</Tabs>
````

##### Clear rotated secrets

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
##### Clear rotated secrets
##### Remove old secret

@unatasha8 unatasha8 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In general, keep to singular for 'secret' if the process is one at a time. Pick one to use client(s), client service(s), service(s), application(s) etc. I tried to change all to client services.

Apply the terminology suggestions from the review: singular "secret", and
"client service" used consistently.

Also fix the rotation endpoint path. All four curl examples used
/admin/clients/{id}/secret/rotate, but the implemented route is
/admin/clients/{id}/secrets/rotate, so every example returned 404.

Answer the two open review questions in the text: say where to store the new
secret, and confirm that secrets do not expire on their own.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alnr

alnr commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Pushed 056df20 to address @unatasha8's review. Summary of what changed, including three places where I did not apply a suggestion literally — flagging those so you can push back.

Applied

  • Singular "secret" throughout, and "client service(s)" used consistently, per the general note.
  • "Clear rotated secrets" → "Remove old secret"; "cleanup" wording removed everywhere.
  • The two admonitions and the workflow example comments now use the agreed terminology.

Bug found while editing

All four curl examples used /admin/clients/{id}/secret/rotate (singular). The implemented route is /admin/clients/{id}/secrets/rotate (plural) — see client/handler.go and the OpenAPI spec in ory-corp/cloud#10632. Every example on this page would have returned 404. Fixed.

Answers to the open questions

  • "Where should this be saved?" (line 160) — the text now says Ory shows the value only once and to store it in the secret store the client services read from (a secrets manager or an encrypted environment configuration).
  • "'Secrets remain valid indefinitely' — are you sure? Don't they have a validity date?" (line 260) — confirmed correct. Rotated secrets are stored in the rotated_secrets column with no expiry field and no TTL; they stay valid until explicitly deleted. That is exactly why the warning admonition exists. This is unlike the SAML valid_to attribute you mentioned, which is a different feature.

Deviations from the literal suggestions

  1. Ordering of "How secret rotation works" — the suggestion moves "Both old and new secrets authenticate" to step 3, after "Update your client services". That would imply the dual-validity window starts once you update your services. It actually starts the moment you rotate. I kept the dual-validity statement attached to step 1 and added your "test before removing" step as step 3:
    1. Generate a new secret for the client service. Both the old and the new secret authenticate from this point on.
    2. Update your client services to use the new secret.
    3. Test that the client services can authenticate with the new secret.
    4. Manually remove the old secret. Only the new secret authenticates from this point on.
  2. ##### Rotate OAuth2 client secret — left as ##### Rotate client secret. The ## heading directly above is already "Rotate OAuth2 client secret", so the suggestion would create two identical headings and an ambiguous #rotate-oauth2-client-secret-1 anchor.
  3. "servcies" in the step-3 suggestion is a typo; used "services".

Happy to take any of these the other way — say the word.

@alnr alnr requested a review from unatasha8 July 9, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docs This issue affects Ory's documentation. upstream Issue is caused by an upstream dependency.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants