Conversation
Introduced `deviceFlowEnabled` to `Application` model and repository. Updated migration, mapping functions, and SQL queries to support the new property. Signed-off-by: karo <karolin.kostial@gmail.com>
Added `OidcDeviceCodeTokenType` and `OidcUserCodeTokenType` to token types. Introduced `StoreToken` method for token service and `DeviceCodeInfo` structure for managing device code flow data. Updated `LoginInfo` to include `deviceCode`. Signed-off-by: karo <karolin.kostial@gmail.com>
Added support for updating the `deviceFlowEnabled` property in the `PatchApplication` command and HTTP handler. Updated DTO and application update logic accordingly. Signed-off-by: karo <karolin.kostial@gmail.com>
Registered new OIDC routes for initiating device flow, handling activation pages, and success handling. Signed-off-by: karo <karolin.kostial@gmail.com>
Added `DeviceAuthorizationEndpoint` to OpenID configuration. Introduced support for the device code grant type and accompanying OIDC endpoints, including device flow initiation, activation, and token issuance. Updated `DeviceCodeInfo` structure and validation logic. Signed-off-by: karo <karolin.kostial@gmail.com>
Implemented `OidcClient` to handle the device code flow, including initiating the device authorization and polling for tokens. Extended `Transport` with `NewOidcRequest` and `DoRaw` methods to support OIDC-related HTTP requests. Updated the main client interface to expose the `Oidc` client. Signed-off-by: karo <karolin.kostial@gmail.com>
…ation Added `PostActivate`, `VerifyPassword`, and `FinishLogin` methods to `OidcClient`. Updated `Transport` with `DoNoRedirect` to support requests without redirections. Refactored e2e tests to utilize new client methods for device flow and activation scenarios. Signed-off-by: karo <karolin.kostial@gmail.com>
… server commands Extended DTOs, handlers, commands, and configuration to include the `deviceFlowEnabled` property for applications. Signed-off-by: karo <karolin.kostial@gmail.com>
…mapping Updated audit log mapping to use `sql.NullString` for nullable string fields. Removed reliance on `pq.ByteaArray` and introduced helper functions for wrapping and unwrapping nullable values. Signed-off-by: karo <karolin.kostial@gmail.com>
…` calls in OIDC client Signed-off-by: karo <karolin.kostial@gmail.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds OAuth2/OIDC Device Authorization Grant (“device flow”) support to Keyline, including server endpoints, persistence/config wiring, and client + E2E coverage to exercise the full approval/polling flow.
Changes:
- Introduces
/oidc/{vs}/deviceinitiation, activation redirects (/activate,/activate/success), and device_code token exchange via the existing/tokenendpoint. - Adds
device_flow_enabledapplication flag (DB migration + repository/entity/command/handler/config plumbing) to gate device flow per application. - Adds a Go client OIDC helper for device flow plus E2E and unit tests.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/e2e/harness.go | Exposes the DI scope from the E2E harness for fixture setup. |
| tests/e2e/deviceflow_test.go | New E2E coverage for device flow initiation, activation, polling, and one-time use semantics. |
| internal/services/tokens.go | Adds device/user code token types and a new token storage method. |
| internal/server/server.go | Registers new OIDC device/activation routes. |
| internal/repositories/postgres/auditlogs.go | Fixes/adjusts audit log DB mapping (response/allowReasonType) and insert columns. |
| internal/repositories/postgres/applications.go | Persists and updates the new device_flow_enabled application column. |
| internal/repositories/applications.go | Adds domain field + change tracking for DeviceFlowEnabled. |
| internal/jsonTypes/LoginInfo.go | Adds DeviceCode to login session payload to link login completion to device flow authorization. |
| internal/jsonTypes/DeviceCodeInfo.go | Introduces KV-stored device_code metadata (status, scopes, user linkage, etc.). |
| internal/handlers/oidc.go | Implements device flow initiation, activation redirect handlers, and device_code grant handling on /token. |
| internal/handlers/login.go | Marks device_code as authorized during FinishLogin when login was initiated from activation. |
| internal/handlers/applications.go | Exposes device flow enabled flag in create/patch application APIs. |
| internal/database/postgres/migrations/18_deviceFlow.sql | Adds device_flow_enabled column to applications. |
| internal/config/config.go | Adds DeviceFlowEnabled to initial project application config. |
| internal/commands/PatchApplication.go | Allows patching DeviceFlowEnabled via command handler. |
| internal/commands/CreateVirtualServer.go | Applies DeviceFlowEnabled when seeding applications for a virtual server. |
| internal/commands/CreateApplication.go | Sets DeviceFlowEnabled on application creation. |
| cmd/api/main.go | Maps config DeviceFlowEnabled into app seed command payload. |
| client/transport.go | Adds OIDC request helper + raw/no-redirect request execution helpers. |
| client/oidc_test.go | Unit tests for the new client device flow methods. |
| client/oidc.go | Implements client-side device flow calls (begin, poll, activate, login steps). |
| client/client.go | Exposes Oidc() client surface. |
| if application == nil { | ||
| utils.HandleHttpError(w, fmt.Errorf("application not found")) | ||
| return | ||
| } |
Comment on lines
+128
to
+133
| noRedirectClient := &http.Client{ | ||
| Transport: t.client.Transport, | ||
| CheckRedirect: func(_ *http.Request, _ []*http.Request) error { | ||
| return http.ErrUseLastResponse | ||
| }, | ||
| } |
Comment on lines
+2019
to
+2025
| http.Error(w, "Invalid or expired device code. Please request a new one.", http.StatusNotFound) | ||
| return | ||
| } | ||
|
|
||
| deviceCodeInfoString, err := tokenService.GetToken(ctx, services.OidcDeviceCodeTokenType, deviceCode) | ||
| if err != nil { | ||
| http.Error(w, "Invalid or expired device code. Please request a new one.", http.StatusNotFound) |
Comment on lines
34
to
+38
| GenerateAndStoreToken(ctx context.Context, tokenType TokenType, value string, expiration time.Duration) (string, error) | ||
| UpdateToken(ctx context.Context, tokenType TokenType, token string, value string, expiration time.Duration) error | ||
| GetToken(ctx context.Context, tokenType TokenType, token string) (string, error) | ||
| DeleteToken(ctx context.Context, tokenType TokenType, token string) error | ||
| StoreToken(ctx context.Context, tokenType TokenType, token string, value string, expiration time.Duration) error |
| } | ||
| return string(result) | ||
| } | ||
|
|
Comment on lines
+1883
to
+1887
| err = tokenService.DeleteToken(ctx, services.OidcDeviceCodeTokenType, deviceCode) | ||
| if err != nil { | ||
| utils.HandleHttpError(w, fmt.Errorf("deleting device code: %w", err)) | ||
| return | ||
| } |
Comment on lines
+65
to
+67
| oidcRouter.HandleFunc("/activate", handlers.GetActivatePage).Methods(http.MethodGet) | ||
| oidcRouter.HandleFunc("/activate", handlers.PostActivatePage).Methods(http.MethodPost) | ||
| oidcRouter.HandleFunc("/activate/success", handlers.ActivateSuccess).Methods(http.MethodGet) |
Comment on lines
+1714
to
+1718
| func BeginDeviceFlow(w http.ResponseWriter, r *http.Request) { | ||
| ctx := r.Context() | ||
| scope := middlewares.GetScope(ctx) | ||
|
|
||
| err := r.ParseForm() |
Comment on lines
+568
to
+572
| } | ||
|
|
||
| if err := tokenService.UpdateToken(ctx, services.OidcDeviceCodeTokenType, loginInfo.DeviceCode, string(updatedInfoJson), 10*time.Minute); err != nil { | ||
| utils.HandleHttpError(w, fmt.Errorf("updating device code info: %w", err)) | ||
| return |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
No description provided.