Personal access tokens for programatic API access#176
Conversation
|
Hello @mfcarroll I'd like to get this feature included in the upcoming version 0.7. In order for me to fully review it, I'd need you to do a couple of things first:
I promise I'll take a look as soon as you do that to avoid having to to additional rebases / version bumps on the migrations. Thanks in advance |
ce9d4e8 to
ff2b567
Compare
|
Hi @piffio. I think that's all cleaned up now. I bumped to 026 as that was open, I assume you'd left that open intentionally for this feature as I don't see it in any other branches. If not feel free to rename too, the branch is open to edits by maintainers. Thanks again. |
piffio
left a comment
There was a problem hiding this comment.
Thanks for your contribution, really appreciated!
I've left a few comments here and there but nothing blocking.
There will be time to review some of those decisions in the future, none of them is a one-way door
| stmt.bind(&[ | ||
| key_id.clone().into(), | ||
| user_ctx.user_id.into(), | ||
| user_ctx.org_id.into(), |
There was a problem hiding this comment.
I'll need to review this logic later as a user can in theory belong to multiple organizations.
So I guess we should scope the API key to specific organization(s) upon creation, depending on which orgs the user has access to.
The scoping should be editable.
Nothing blocking here, more of a note to self to evolve the logic in the near future
There was a problem hiding this comment.
Yes, that makes sense, just wasn't needed for my use (self hosted for a nonprofit organization).
|
|
||
| // 5. Update the 'last_used_at' timestamp inline | ||
| let _ = | ||
| crate::db::queries::update_api_key_last_used(&db, &api_key.id, now_timestamp()).await; |
There was a problem hiding this comment.
I understand why you're doing this, but not sure it's worth it as it means a new DB write for every API request, even when it's just fetching data.
Similarly, I'll keep it for now but I might review the decusion in the future.
There was a problem hiding this comment.
Very good point. Maybe the usage timestamp isn't truly needed, especially in high-traffic environments.
| # Environment variables and secrets | ||
| .env | ||
| .dev.vars | ||
| repo-config/config/user.sh |
Feature: Personal Access Tokens (API Keys)
Description
This PR implements a secure Personal Access Token (PAT) system, allowing users to interact with the Rushomon API programmatically.
Tokens follow the industry-standard "Prefix + Secret" format (
ro_pat_...) and are stored using SHA-256 hashing. This ensures that even in the event of a database leak, raw tokens remain unrecoverable. Users are shown the raw token exactly once upon creation.Key Changes
🔑 Backend (Rust)
api_keystable with support for names, expiration, and last-used tracking.Authorization: Bearer ro_pat_...headers, validate against the database, and automatically update thelast_used_attimestamp.Create,List, andRevokeoperations.🎨 Frontend (SvelteKit)
🧪 Testing
tests/api_keys_test.rscovering the full lifecycle:Security Checklist
POSTrequest.user_idandorg_idof the creator.