Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: add API endpoint to update token API keys#19983

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
ThomasK33 wants to merge1 commit intothomask33/09-25-resource_scoped_api_keys_in_codersdk
base:thomask33/09-25-resource_scoped_api_keys_in_codersdk
Choose a base branch
Loading
fromthomask33/09-26-add_api_key_patch_endpoint

Conversation

ThomasK33
Copy link
Member

Add API for updating token API keys

This PR adds a new PATCH endpoint for updating token API keys. The endpoint allows updating:

  1. Token scopes (either viascope orscopes field)
  2. Token allow list (resource restrictions)
  3. Token lifetime (expiration)

The implementation includes:

  • NewUpdateTokenRequest type in the SDK
  • NewpatchToken handler in the API
  • Helper functions for normalizing token scopes and allow lists
  • Database query for updating token authorization parameters
  • Tests for token updates and validation

This enables users to modify existing API tokens without having to create new ones, which is particularly useful for adjusting permissions or extending token lifetimes.

@ThomasK33Graphite App
Copy link
MemberAuthor

ThomasK33 commentedSep 26, 2025
edited
Loading

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stackon Graphite.
Learn more

This stack of pull requests is managed byGraphite. Learn more aboutstacking.

@ThomasK33ThomasK33 linked an issueSep 26, 2025 that may beclosed by this pull request
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch from88f66b9 tob0bed7fCompareSeptember 26, 2025 14:00
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from6d17ef1 to6fa5fe1CompareSeptember 26, 2025 14:00
@ThomasK33ThomasK33 marked this pull request as ready for reviewSeptember 26, 2025 14:25
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch fromb0bed7f toacc9e28CompareSeptember 26, 2025 14:27
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch 2 times, most recently from59e7235 to8ab1479CompareSeptember 26, 2025 18:05
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch fromacc9e28 to53815d9CompareSeptember 26, 2025 18:05
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from8ab1479 to4fbe05fCompareSeptember 28, 2025 10:53
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch from53815d9 to326dbdcCompareSeptember 28, 2025 10:53
require.NotEmpty(t,resp.Key)
}

funcTestTokenCreationAllowsElevatedScopes(t*testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

Do these scoped API keys allow creating other API keys? If so, do these API keys inherit the original scope?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Scoped API keys allow the creation of other API keys. The newly created keys do not inherit the original key's scope.

Copy link
Member

Choose a reason for hiding this comment

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

Isn't that basically privilege escalation?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

It depends on one's perspective.

Not inheriting the original scopes allows an admin to use that API key to provision just-in-time API keys for specific use cases and revoke them later. If we enforced inheritance, the issuing API key would need all the permissions required for those actions, which could introduce the risk of creating an overly broad API key.

AWS IAM addresses this withService Control Policies (SCPs)—which act as organization-wide upper limits—andpermission boundaries, which serve as per-identity upper limits. These need to be explicitly applied to prevent this kind of privilege escalation.

For Coder, this could or should be considered as a later addition. Also, once we have the OAuth client credentials flow in place, we can advise users and admins to use that instead.

Comment on lines 86 to 143
// Valid typed allow list should succeed.
resp,err:=client.CreateToken(ctx,codersdk.Me, codersdk.CreateTokenRequest{
Scopes: []codersdk.APIKeyScope{codersdk.APIKeyScopeWorkspaceRead},
AllowList: []codersdk.APIAllowListTarget{codersdk.AllowResourceTarget(codersdk.ResourceWorkspace,uuid.New())},
})
require.NoError(t,err)
require.NotEmpty(t,resp.Key)
}
Copy link
Member

Choose a reason for hiding this comment

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

Are wildcard resource targets allowed here?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

They are supported.

@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from4fbe05f toe1c95e4CompareSeptember 29, 2025 08:25
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch fromfb77dfe toc8a7549CompareSeptember 30, 2025 14:02
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch from3acf64c to790294fCompareSeptember 30, 2025 14:02
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch fromc8a7549 toc50a0acCompareOctober 1, 2025 13:56
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch 2 times, most recently from9ba5e36 to541b300CompareOctober 2, 2025 07:35
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch 2 times, most recently from56cd860 tod38ed5bCompareOctober 2, 2025 17:37
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch from541b300 to2a701edCompareOctober 2, 2025 17:37
Comment on lines +609 to +612
// Default to coder:all for backward compatibility when nothing is provided.
iflen(scopes)==0&&string(scope)=="" {
return database.APIKeyScopes{database.ApiKeyScopeCoderAll},nil
}
Copy link
Member

Choose a reason for hiding this comment

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

We should error if the user tries to set both right?

Suggested change
// Default to coder:all for backward compatibility when nothing is provided.
iflen(scopes)==0&&string(scope)=="" {
return database.APIKeyScopes{database.ApiKeyScopeCoderAll},nil
}
// Default to coder:all for backward compatibility when nothing is provided.
iflen(scopes)==0&&string(scope)=="" {
return database.APIKeyScopes{database.ApiKeyScopeCoderAll},nil
}
iflen(scopes)>0&&string(scope)!="" {
returnnil,xerrors.New("provide either scope or scopes, not both")
}

returnout,nil
}

funcnormalizeTokenAllowList(entries []codersdk.APIAllowListTarget) (database.AllowList,bool,error) {
Copy link
Member

@EmyrkEmyrkOct 2, 2025
edited
Loading

Choose a reason for hiding this comment

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

Do we need thebool return? It just returns if the input list is non-zero right?

It's only used here

ifallowList,provided,err:=normalizeTokenAllowList(createToken.AllowList);err!=nil {
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
Message:"Failed to create API key.",
Detail:err.Error(),
})
return
}elseifprovided {
params.AllowList=allowList
}

But theparams.AllowList is not set ifprovided == false. So the boolean return does not do anything.

Theparams.AllowList defaults tonil, and ifprovided == false, the return value isnil for the returned list.

So this is equivalent

allowList,err:=normalizeTokenAllowList(createToken.AllowList)iferr!=nil {// .. Handle}params.AllowList=allowList

@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch fromd38ed5b to5cb53f7CompareOctober 3, 2025 17:59
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch from2a701ed to29af648CompareOctober 3, 2025 17:59
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from5cb53f7 to6248fffCompareOctober 6, 2025 09:42
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch from29af648 to1a42b23CompareOctober 6, 2025 09:42
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from6248fff to67ed32bCompareOctober 6, 2025 10:09
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch 2 times, most recently from1d1732b to518faffCompareOctober 6, 2025 10:48
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch 2 times, most recently from4beef99 to86f7de9CompareOctober 6, 2025 11:18
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch 2 times, most recently from4de874d tofd7a0fbCompareOctober 6, 2025 11:57
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from86f7de9 to854efb0CompareOctober 6, 2025 11:57
@EmyrkEmyrk self-assigned thisOct 6, 2025
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from854efb0 to87fb51cCompareOctober 6, 2025 21:16
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch fromfd7a0fb tod06529eCompareOctober 6, 2025 21:16
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from87fb51c to3bdb267CompareOctober 6, 2025 21:40
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch fromd06529e toa343213CompareOctober 6, 2025 21:40
r.Get("/tokenconfig",api.tokenConfig)
r.Route("/{keyname}",func(r chi.Router) {
r.Get("/",api.apiKeyByName)
r.Patch("/",api.patchToken)
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need to update api keys?

Is this a common practice elsewhere? Can the user just make a new api key with the new scopes? I feel strange allowing someone to escalate a token after it has been created.

Copy link
Member

Choose a reason for hiding this comment

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

Is this required for oauth, or has product requested it?

I would prefer not to add this if it is not requested/required.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Is this a common practice elsewhere? Can the user just make a new api key with the new scopes? I feel strange allowing someone to escalate a token after it has been created.

It is a common practice. GitHub, for example, allows you to update a personal access token and attach additional permissions to it or remove permissions. This is not only an escalation but also a de-escalation.

Is this required for oauth, or has product requested it?
I would prefer not to add this if it is not requested/required.

It's part of the API key scopes RFC.

Implements RFC-compliant PATCH /users/{user}/keys/tokens/{keyname}endpoint enabling updates to API key authorization parametersincluding scopes, allow lists, and expiration times.Key changes:- Add patchToken handler with comprehensive validation- Extract scope and allow list normalization into reusable functions  - Implement authorization checks preventing non-owners from minting  elevated scopes with wildcard allow lists- Add UpdateAPIKeyAuthorization database query with audit support- Generate OpenAPI documentation and TypeScript client typesThe endpoint supports partial updates with proper authorizationcontext validation and maintains backward compatibility withexisting token creation patterns.
@ThomasK33ThomasK33force-pushed thethomask33/09-25-resource_scoped_api_keys_in_codersdk branch from3bdb267 toc41112aCompareOctober 7, 2025 16:38
@ThomasK33ThomasK33force-pushed thethomask33/09-26-add_api_key_patch_endpoint branch froma343213 to95b0229CompareOctober 7, 2025 16:38
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@johnstcnjohnstcnjohnstcn left review comments

@EmyrkEmyrkEmyrk left review comments

Assignees

@ThomasK33ThomasK33

@EmyrkEmyrk

Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

API: token create/list/update with scopes[] and allow_list[]
3 participants
@ThomasK33@johnstcn@Emyrk

[8]ページ先頭

©2009-2025 Movatter.jp