Skip to content

feat!: new api key system#3636

Merged
ThibaudDauce merged 23 commits intomainfrom
new_api_key_system
Mar 23, 2026
Merged

feat!: new api key system#3636
ThibaudDauce merged 23 commits intomainfrom
new_api_key_system

Conversation

@ThibaudDauce
Copy link
Copy Markdown
Contributor

@ThibaudDauce ThibaudDauce commented Jan 28, 2026

  • Replace the single User.apikey (JWS token stored on the user document) with a dedicated ApiToken collection supporting multiple tokens per user, HMAC-SHA256 hashed storage, revocation, expiration, and tracking
  • New API endpoints: POST /api/1/me/tokens/ (create), GET /api/1/me/tokens/ (list active), DELETE /api/1/me/tokens// (revoke) — the plaintext token is returned only once at creation
  • Remove the apikey field from the User model and the me_fields / apikey_fields API serializers, along with the old /me/apikey/ endpoint
  • Add an idempotent migration that hashes existing JWS apikeys with HMAC-SHA256 into the new api_token collection, preserving backward compatibility for existing consumers
  • Introduce API_TOKEN_SECRET and API_TOKEN_PREFIX settings for token hashing and secret-scanning tool integration

@ThibaudDauce ThibaudDauce marked this pull request as ready for review February 5, 2026 12:41
@ThibaudDauce ThibaudDauce requested review from maudetes and nicolaskempf57 and removed request for maudetes February 5, 2026 12:41
Comment thread udata/core/user/api.py Outdated
Comment thread udata/tests/api/__init__.py Outdated
Comment thread udata/api/__init__.py
Copy link
Copy Markdown
Contributor

@nicolaskempf57 nicolaskempf57 left a comment

Choose a reason for hiding this comment

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

Thanks for this PR ! I think we are ready on udata side, but it will require some changes in cdata and maybe other projects like front-kit if they also have an interface for the api key

@ThibaudDauce
Copy link
Copy Markdown
Contributor Author

Thanks for this PR ! I think we are ready on udata side, but it will require some changes in cdata and maybe other projects like front-kit if they also have an interface for the api key

Done in datagouv/cdata#962

Copy link
Copy Markdown
Contributor

@maudetes maudetes left a comment

Choose a reason for hiding this comment

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

🎉 I think it will be a very nice improvement for security and usability !

Comment thread docs/api-tokens.md Outdated
Comment thread udata/auth/__init__.py Outdated
Comment thread udata/core/user/api.py Outdated
Comment on lines +206 to +207
@me.route("/tokens/", endpoint="my_tokens")
class TokenListAPI(API):
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.

Can we use the wording api key instead of vague token?
In my understanding, other potential token usage would have distinct routes anyway?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I used api_token instead of just token. As discussed I prefer to keep one code for all the tokens since it's the same technical thing with the same operations on it.

Comment thread udata/core/user/api.py Outdated
Comment thread udata/core/user/api.py Outdated
Comment thread udata/core/user/models.py
Comment thread udata/api/__init__.py
Comment thread udata/tests/api/test_auth_api.py
Comment thread udata/core/user/api_tokens.py Outdated
Comment thread udata/core/user/api_tokens.py Outdated
Comment thread udata/core/user/models.py
Comment on lines +303 to +307
from udata.core.api_token.models import ApiToken

ApiToken.objects(user=self, revoked_at=None).update(
set__revoked_at=datetime.now(timezone.utc)
)
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.

Should we delete api keys in the case of a user deletion?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think revoking is safer to not loose the keys if the user is restored?

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.

Hmm we don't have user restoration. They need to recreate an account if they want to come back

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I was thinking of a wrong deletion, for exemple Geoffrey miss click :-)

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.

ahah even if Geoffrey double-miss clicks, I would recommend recreating an account and contacting us, if needed, to get back any old dataset & co

Comment thread udata/core/api_token/models.py Outdated
Comment thread udata/core/user/api.py Outdated
@ThibaudDauce ThibaudDauce merged commit 8bfbcc8 into main Mar 23, 2026
1 check passed
@ThibaudDauce ThibaudDauce deleted the new_api_key_system branch March 23, 2026 10:36
ThibaudDauce added a commit to datagouv/cdata that referenced this pull request Mar 23, 2026
Following the merge of opendatateam/udata#3636

(just because it's faster to merge this than
#962)
ThibaudDauce added a commit to datagouv/cdata that referenced this pull request Mar 24, 2026
@maudetes maudetes moved this to ✅ Done in 🚀 Produit data.gouv.fr Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants