Repository navigation
Add OAuth device sign-in, sign-out/revoke, and at-rest credential encryption #47
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
20b136b
Add OAuth device sign-in to the mobile tunnel client
claude 7195230
Review follow-up: fix OAuth device-id binding and lifecycle
claude 603afcd
Resume interrupted OAuth sign-in after process death
claude 3b44114
Handle revoked credentials, add sign-out, encrypt credential at rest
claude 0493ab9
Merge remote-tracking branch 'origin/main' into claude/oauth-mobile-a…
claude File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -94,9 +94,29 @@ per-file limit, and 32 MiB total virtual filesystem limit. | |||||
| ./gradlew testDebugUnitTest # run JVM unit tests | ||||||
| ./gradlew installDebug # install on a connected device/emulator | ||||||
| ``` | ||||||
| 2. Run the app, fill in the gateway WebSocket URL and your SealGate API key | ||||||
| (from the dashboard), and tap **Start tunnel**. Settings persist across | ||||||
| restarts; the ongoing notification shows the live connection state. | ||||||
| 2. Run the app, confirm (or edit) the gateway WebSocket URL, and tap | ||||||
| **Sign in with SealGate**. The app runs the OAuth 2.0 device-authorization | ||||||
| flow (RFC 8628, with PKCE): it shows a short code and opens the dashboard's | ||||||
| device page, where you approve the phone with one click. On approval the app | ||||||
| receives a scoped `ewc_` tunnel credential (never a human API key) bound to a | ||||||
| backend-issued device id, stores it, and starts the tunnel. Settings persist | ||||||
| across restarts; the ongoing notification shows the live connection state. | ||||||
|
|
||||||
| Pasting a SealGate API key under **Or connect with an API key** and tapping | ||||||
| **Connect** still works as an alternative to signing in. | ||||||
|
|
||||||
| Sign-in reuses the shared device-auth flow the desktop daemon uses, under a | ||||||
| dedicated `mobile` client id; the backend side lives in `edison-watch` | ||||||
| (`src/api/v1/routes/device_auth.py`, `dev-docs/architecture/mobile-hardware-gateway-design.md`). | ||||||
|
|
||||||
| The credential (and the in-flight PKCE verifier of an interrupted sign-in) is | ||||||
| stored encrypted at rest with an AES-256-GCM key held in the AndroidKeyStore | ||||||
| (`SecretCipher`), so a prefs dump or a backup restored to another phone cannot | ||||||
| lift it. To disconnect, open settings and tap **Sign out**: the app stops the | ||||||
| tunnel, forgets the local credential, and revokes the installation in the | ||||||
| dashboard (`POST /api/v1/auth/device/revoke`). If the gateway later revokes the | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Sign out does not always revoke an installation: API-key sign-out skips the revoke endpoint, and OAuth revocation is best-effort. Qualify this as a best-effort revoke for OAuth credentials so the fallback behavior and failure case are documented accurately. Prompt for AI agents
Suggested change
|
||||||
| credential itself, the tunnel stops reconnecting and the app asks you to sign | ||||||
| in again instead of looping. | ||||||
|
|
||||||
| While the tunnel is running, pull down from the top of the app screen to | ||||||
| close the current socket and reconnect immediately with the saved settings. | ||||||
|
|
||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: For users upgrading with an existing API key, this statement is false until the settings are saved again: legacy plaintext is read unchanged and is not re-encrypted during load. Document the migration caveat so users do not assume the credential is already protected immediately after upgrading.
Prompt for AI agents