Skip to content

Admin Oauth API#1472

Open
3kh0 wants to merge 4 commits into
mainfrom
admin-oauth
Open

Admin Oauth API#1472
3kh0 wants to merge 4 commits into
mainfrom
admin-oauth

Conversation

@3kh0

@3kh0 3kh0 commented Jul 11, 2026

Copy link
Copy Markdown
Member

Summary of the problem

The Hackatime API is great, but juggling API keys is cringe, and frankly, I am on the 7th API key that I lost, so it's time to change that.

Describe your changes

  • Added an OAuth admin scope so internal tools can “Sign in with Hackatime” and call the Admin API with a token instead of minting Admin API keys
  • Only admin+ can attach the scope to an app; viewer+ can authorize it (with a big scary consent warning)
  • Admin API accepts either existing hka_ keys or OAuth tokens with the admin scope

Screenshots / Media

Scary notice when authing apps that request the admin scope

admin-oauth-consent

3kh0 added 4 commits July 11, 2026 00:55
@greptile-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds OAuth access to the Admin API. The main changes are:

  • Adds an admin OAuth scope for confidential applications.
  • Restricts scope assignment and authorization by staff role.
  • Accepts OAuth tokens alongside existing Admin API keys.
  • Adds an elevated-access warning to the consent page.
  • Adds controller tests and OAuth documentation.

Confidence Score: 4/5

Viewer OAuth tokens can reach Admin API write actions and this access path needs to be constrained before merging.

OAuth token validity, scope, and current user role are checked on every request. Existing high-risk actions retain their explicit permission checks. Write actions that rely only on shared authentication can now be called by viewers. Admin API key creation provides a concrete viewer-accessible write path.

app/controllers/api/admin/application_controller.rb and Admin API controllers with write actions

T-Rex T-Rex Logs

What T-Rex did

  • Validated that oauth-admin-consent-01-before.log shows the real server cannot boot.
  • Validated that oauth-admin-consent-02-after.log shows the real controller path cannot execute under the installed Ruby/Bundler.
  • Validated that oauth-admin-ui-02-after.log confirms the warning text, authorize and deny controls, scope context, and controller wiring.
  • Noted that formatting checks passed and Svelte diagnostics indicate the only blocker is a repository-wide missing generated API-client blocker for this component.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
app/controllers/api/admin/application_controller.rb Adds dual API-key and OAuth authentication, but admits viewers to Admin API actions without centrally enforcing read-only access.
app/controllers/api/admin/v1/admin_controller.rb Updates the authentication check response to describe either the API key or OAuth application.
app/controllers/custom_doorkeeper/authorizations_controller.rb Adds an authorization-time role check and consent metadata for the admin scope.
app/controllers/doorkeeper/applications_controller.rb Restricts admin-scope assignment while preserving it during unrelated updates to existing applications.
app/models/oauth_application.rb Defines the admin scope and requires applications carrying it to remain confidential.
app/javascript/pages/OAuthAuthorize/New.svelte Adds a prominent warning when the authorization request includes the admin scope.
test/controllers/api/admin/v1/oauth_admin_auth_test.rb Covers OAuth authentication and role changes, but does not verify that viewer tokens remain read-only across write actions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Bearer token] --> B{Active Admin API key?}
B -->|Yes| C[Load key owner]
B -->|No| D{Valid OAuth token with admin scope?}
D -->|Yes| E[Load resource owner]
D -->|No| F[Return unauthorized]
C --> G{Staff admin level?}
E --> G
G -->|No| F
G -->|Yes, including viewer| H[Run Admin API action]
H --> I{Action has a role-specific guard?}
I -->|Yes| J[Enforce action permission]
I -->|No| K[Viewer can reach action]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Bearer token] --> B{Active Admin API key?}
B -->|Yes| C[Load key owner]
B -->|No| D{Valid OAuth token with admin scope?}
D -->|Yes| E[Load resource owner]
D -->|No| F[Return unauthorized]
C --> G{Staff admin level?}
E --> G
G -->|No| F
G -->|Yes, including viewer| H[Run Admin API action]
H --> I{Action has a role-specific guard?}
I -->|Yes| J[Enforce action permission]
I -->|No| K[Viewer can reach action]
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
app/controllers/api/admin/application_controller.rb:43
**Viewer Tokens Reach Write Actions**

A viewer can authorize the new `admin` scope and pass this shared authentication check, but some Admin API write actions have no separate viewer guard. For example, a viewer token can reach `POST /api/admin/v1/admin_api_keys` and mint an `hka_` credential, violating the viewer role's read-only contract. Enforce viewer-safe actions centrally or add role checks to every write endpoint.

Reviews (1): Last reviewed commit: "Fix flaky dashboard weekly stats test ti..." | Re-trigger Greptile

Comment thread app/controllers/api/admin/application_controller.rb
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.

1 participant