From 8e6eb39c103135275a1e419a9555062f3f371abc Mon Sep 17 00:00:00 2001 From: Mason Williams Date: Mon, 20 Apr 2026 11:53:15 -0400 Subject: [PATCH] Default --credential-auto to true when --credential-provider is set alone auth connections create accepted --credential-provider without --credential-path or --credential-auto and dutifully sent a CredentialReference of { provider } with no auto flag. The server accepted that as valid but never fetched credentials, so managed auth sessions dead-ended in awaiting_input and the user was prompted to enter credentials manually. Match the dashboard's UX (create-managed-auth-dialog.tsx): picking a provider without a specific item always means "look up by domain". An explicit --credential-path still pins the reference, and passing --credential-auto is now redundant but still honored. Covered by four new cases in auth_connections_test.go. Made-with: Cursor --- cmd/auth_connections.go | 10 ++- cmd/auth_connections_test.go | 116 +++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/cmd/auth_connections.go b/cmd/auth_connections.go index 87dd2af..72d5c5d 100644 --- a/cmd/auth_connections.go +++ b/cmd/auth_connections.go @@ -151,6 +151,14 @@ func (c AuthConnectionCmd) Create(ctx context.Context, in AuthConnectionCreateIn } if in.CredentialPath != "" { params.ManagedAuthCreateRequest.Credential.Path = kernel.Opt(in.CredentialPath) + } else { + // Default to domain auto-lookup when no explicit --credential-path is + // given. This matches the dashboard's UX, where picking a provider + // without a specific item always means "look up by domain". Without + // this default, the server receives { provider } with no path or + // auto flag, which is a valid-but-inert credential reference that + // causes the managed auth session to never fetch credentials. + params.ManagedAuthCreateRequest.Credential.Auto = kernel.Opt(true) } if in.CredentialAuto { params.ManagedAuthCreateRequest.Credential.Auto = kernel.Opt(true) @@ -797,7 +805,7 @@ func init() { authConnectionsCreateCmd.Flags().String("credential-name", "", "Kernel credential name to use") authConnectionsCreateCmd.Flags().String("credential-provider", "", "External credential provider name") authConnectionsCreateCmd.Flags().String("credential-path", "", "Provider-specific path (e.g., VaultName/ItemName)") - authConnectionsCreateCmd.Flags().Bool("credential-auto", false, "Lookup by domain from the specified provider") + authConnectionsCreateCmd.Flags().Bool("credential-auto", false, "Lookup by domain from the specified provider (defaults to true when --credential-provider is set without --credential-path)") authConnectionsCreateCmd.Flags().String("proxy-id", "", "Proxy ID to use") authConnectionsCreateCmd.Flags().String("proxy-name", "", "Proxy name to use") authConnectionsCreateCmd.Flags().Bool("no-save-credentials", false, "Disable saving credentials after successful login") diff --git a/cmd/auth_connections_test.go b/cmd/auth_connections_test.go index d6615f7..96bb131 100644 --- a/cmd/auth_connections_test.go +++ b/cmd/auth_connections_test.go @@ -205,6 +205,122 @@ func TestAuthConnectionsList_JSONOutput_PrintsRawResponse(t *testing.T) { assert.Contains(t, out, "\"raf-leaseweb\"") } +// Regression test for the 1Password auto-lookup UX gap: before this fix, +// `kernel auth connections create --credential-provider foo` sent a +// CredentialReference of { provider } with no auto flag, which the API accepted +// as valid-but-inert — the managed auth session would never fetch credentials +// and would prompt the user for manual input. The dashboard already defaults +// to auto: true for this case (see packages/dashboard/src/components/create-managed-auth-dialog.tsx); +// the CLI now matches that UX. +func TestAuthConnectionsCreate_ProviderWithoutPath_DefaultsAutoTrue(t *testing.T) { + var captured kernel.AuthConnectionNewParams + fake := &FakeAuthConnectionService{ + NewFunc: func(ctx context.Context, body kernel.AuthConnectionNewParams, opts ...option.RequestOption) (*kernel.ManagedAuth, error) { + captured = body + return &kernel.ManagedAuth{ID: "conn-new"}, nil + }, + } + + c := AuthConnectionCmd{svc: fake} + err := c.Create(context.Background(), AuthConnectionCreateInput{ + Domain: "google.com", + ProfileName: "my-profile", + CredentialProvider: "my-1p", + Output: "json", + }) + require.NoError(t, err) + + cred := captured.ManagedAuthCreateRequest.Credential + require.True(t, cred.Provider.Valid()) + assert.Equal(t, "my-1p", cred.Provider.Value) + assert.False(t, cred.Path.Valid(), "path should not be set when only --credential-provider is given") + require.True(t, cred.Auto.Valid(), "auto should default to true when provider is set without path") + assert.True(t, cred.Auto.Value) +} + +// Explicit --credential-path should keep the credential reference as a pinned +// path lookup (no implicit auto). +func TestAuthConnectionsCreate_ProviderWithPath_DoesNotSetAuto(t *testing.T) { + var captured kernel.AuthConnectionNewParams + fake := &FakeAuthConnectionService{ + NewFunc: func(ctx context.Context, body kernel.AuthConnectionNewParams, opts ...option.RequestOption) (*kernel.ManagedAuth, error) { + captured = body + return &kernel.ManagedAuth{ID: "conn-new"}, nil + }, + } + + c := AuthConnectionCmd{svc: fake} + err := c.Create(context.Background(), AuthConnectionCreateInput{ + Domain: "google.com", + ProfileName: "my-profile", + CredentialProvider: "my-1p", + CredentialPath: "Employees/Google Workspace", + Output: "json", + }) + require.NoError(t, err) + + cred := captured.ManagedAuthCreateRequest.Credential + require.True(t, cred.Provider.Valid()) + assert.Equal(t, "my-1p", cred.Provider.Value) + require.True(t, cred.Path.Valid()) + assert.Equal(t, "Employees/Google Workspace", cred.Path.Value) + assert.False(t, cred.Auto.Valid(), "auto should remain unset when --credential-path is explicit") +} + +// --credential-auto should still be honored (it was a no-op redundant flag +// before the default changed, but callers may pass it for clarity). +func TestAuthConnectionsCreate_ProviderWithExplicitAuto_SetsAuto(t *testing.T) { + var captured kernel.AuthConnectionNewParams + fake := &FakeAuthConnectionService{ + NewFunc: func(ctx context.Context, body kernel.AuthConnectionNewParams, opts ...option.RequestOption) (*kernel.ManagedAuth, error) { + captured = body + return &kernel.ManagedAuth{ID: "conn-new"}, nil + }, + } + + c := AuthConnectionCmd{svc: fake} + err := c.Create(context.Background(), AuthConnectionCreateInput{ + Domain: "google.com", + ProfileName: "my-profile", + CredentialProvider: "my-1p", + CredentialAuto: true, + Output: "json", + }) + require.NoError(t, err) + + cred := captured.ManagedAuthCreateRequest.Credential + require.True(t, cred.Auto.Valid()) + assert.True(t, cred.Auto.Value) +} + +// --credential-name references a Kernel-managed credential and should never +// carry a provider/auto/path — the default-auto logic must not kick in here. +func TestAuthConnectionsCreate_CredentialName_UnaffectedByAutoDefault(t *testing.T) { + var captured kernel.AuthConnectionNewParams + fake := &FakeAuthConnectionService{ + NewFunc: func(ctx context.Context, body kernel.AuthConnectionNewParams, opts ...option.RequestOption) (*kernel.ManagedAuth, error) { + captured = body + return &kernel.ManagedAuth{ID: "conn-new"}, nil + }, + } + + c := AuthConnectionCmd{svc: fake} + err := c.Create(context.Background(), AuthConnectionCreateInput{ + Domain: "google.com", + ProfileName: "my-profile", + CredentialName: "my-google-creds", + Output: "json", + }) + require.NoError(t, err) + + cred := captured.ManagedAuthCreateRequest.Credential + require.True(t, cred.Name.Valid()) + assert.Equal(t, "my-google-creds", cred.Name.Value) + assert.False(t, cred.Provider.Valid()) + assert.False(t, cred.Auto.Valid()) + assert.False(t, cred.Path.Valid()) +} + func TestAuthConnectionsUpdate_MapsParams(t *testing.T) { var captured kernel.AuthConnectionUpdateParams fake := &FakeAuthConnectionService{