Skip to content

fix: recover from rejected Canvas refresh tokens and add token admin - #76

Open
Opeyem1a wants to merge 2 commits into
masterfrom
fix/canvas-oauth-invalid-grant
Open

Opeyem1a wants to merge 2 commits into
masterfrom
fix/canvas-oauth-invalid-grant

Conversation

@Opeyem1a

Copy link
Copy Markdown
Member

Problem

Some users (tokens issued 2026-09-08) get refresh_token request failed to get a token: {"error":"invalid_grant","error_description":"refresh_token not found"} at /oauth/initiate. Canvas no longer recognizes their refresh token, and because the dead row is never removed, every launch fails the same way.

Not caused by discarding rotated refresh tokens — Canvas doesn't rotate them ("the same refresh token can be used multiple times"), and the affected tokens were never successfully refreshed even once.

Changes

  • canvas.py: raise InvalidGrantError (subclass of InvalidOAuthReturnError) when Canvas responds 400/401 with invalid_grant.
  • oauth.py: on InvalidGrantError during refresh, delete the token and raise MissingTokenError so the middleware restarts the OAuth flow. Other failures (e.g. Canvas 5xx) still render the error page and keep the token.
  • oauth.py: callback uses update_or_create so re-authorizing can't violate the one-to-one on user.
  • admin.py: register CanvasOAuth2Token (list/search/delete; token values hidden; no add).

Testing

Not yet exercised against Canvas. To verify: delete an affected user's token via admin (or let the new path do it) and relaunch — they should land on the Canvas authorize screen.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NxgCeX8Y1zSgrACqveBrBm

Opeyem1a and others added 2 commits September 18, 2026 02:47
When Canvas rejects a refresh token with invalid_grant, delete the stored
token and restart the OAuth flow instead of rendering a 403 on every
launch. The OAuth callback now uses update_or_create so re-authorizing
can't collide with an existing row. Also registers CanvasOAuth2Token in
the Django admin for viewing and deleting tokens.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxgCeX8Y1zSgrACqveBrBm
It was already in .gitignore but had been committed before that rule.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxgCeX8Y1zSgrACqveBrBm
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