Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ auth_type = databricks-cli

[__settings__]
default_profile = test

[agent]
host = [DATABRICKS_URL]
workspace_id = [WORKSPACE_ID]
auth_type = databricks-cli
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,23 @@ Profile test was successfully saved
{"method": "POST", "path": "/oidc/v1/token", "raw_body": "client_id=databricks-cli&confirmation_code=FTFAQQKY&device_code=device-code-2&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"}
{"method": "POST", "path": "/oidc/v1/device/auth", "raw_body": "client_id=databricks-cli&scope=offline_access+all-apis"}
{"method": "POST", "path": "/oidc/v1/token", "raw_body": "client_id=databricks-cli&confirmation_code=FTFAQQKY&device_code=device-code-3&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"}

=== An AI agent gets notes on passing the login on to the user

>>> AGENT=test-agent [CLI] auth login --host [DATABRICKS_URL] --profile agent --use-device-code
Using a browser on another device, visit:
[DATABRICKS_URL]/device/verification

And enter the code:
WDJB-MJHT

Note for AI agents (test-agent): give the URL and the code above to the user.
Do not open the URL or approve the login yourself: the user must approve it.
Ask the user for the confirmation code their browser shows.

Once finished, complete the login by running the same command with
--user-code WDJB-MJHT and --confirmation-code set to the confirmation code
provided in your browser.

>>> AGENT=test-agent [CLI] auth login --host [DATABRICKS_URL] --profile agent --use-device-code --user-code WDJB-MJHT --confirmation-code FTFA-QQKY
Profile agent was successfully saved
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,9 @@ trace $CLI auth login --profile test --use-device-code --user-code WDJB-MJHT --c
trace cache_keys
trace print_requests.py --oneline //oidc/v1/device/auth //oidc/v1/token

title "An AI agent gets notes on passing the login on to the user\n"
trace AGENT=test-agent $CLI auth login --host $DATABRICKS_HOST --profile agent --use-device-code
trace AGENT=test-agent $CLI auth login --host $DATABRICKS_HOST --profile agent --use-device-code --user-code WDJB-MJHT --confirmation-code FTFA-QQKY

# Track the .databrickscfg file that was created to surface changes.
mv "./home/.databrickscfg" "./out.databrickscfg"
4 changes: 4 additions & 0 deletions cmd/auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ in two steps instead:
flags exchanges the pending device code instead of requesting a new one,
and the rest of the login runs as usual.

Agent detection (`useragent.AgentProvider()`) does not pick the flow. It only
adds a note to the first step's output that tells the agent to pass the login
on to the user.

The pending login is a token store entry with `PendingLogin` set instead of a
token. Its key is the login's cache key (the profile name, or the host without
a profile) with a `#device-code` suffix, so the target's current token keeps
Expand Down
20 changes: 17 additions & 3 deletions cmd/auth/login_device_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/databricks/cli/libs/databrickscfg/profile"
"github.com/databricks/cli/libs/env"
"github.com/databricks/cli/libs/log"
"github.com/databricks/databricks-sdk-go/useragent"
"github.com/spf13/cobra"
"golang.org/x/oauth2"
)
Expand Down Expand Up @@ -126,17 +127,30 @@ func (l nonInteractiveDeviceCodeLogin) start(ctx context.Context) error {
if err != nil {
return fmt.Errorf("store pending login: %w", err)
}
cmdio.LogString(ctx, strings.Join([]string{
lines := []string{
"Using a browser on another device, visit:",
da.VerificationURI,
"",
"And enter the code:",
formatCode(da.UserCode),
"",
}
// An agent passes the login on to the user, who approves it in the
// browser.
if agent := useragent.AgentProvider(); agent != "" {
lines = append(lines,
"Note for AI agents ("+agent+"): give the URL and the code above to the user.",
"Do not open the URL or approve the login yourself: the user must approve it.",
"Ask the user for the confirmation code their browser shows.",
"",
)
}
lines = append(lines,
"Once finished, complete the login by running the same command with",
"--user-code " + formatCode(da.UserCode) + " and --confirmation-code set to the confirmation code",
"--user-code "+formatCode(da.UserCode)+" and --confirmation-code set to the confirmation code",
"provided in your browser.",
}, "\n"))
)
cmdio.LogString(ctx, strings.Join(lines, "\n"))
return nil
}

Expand Down
10 changes: 10 additions & 0 deletions docs/device-code-login.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ Profile my-profile was successfully saved
confirmation code. It saves the profile and the token. Without
`--profile`, it only stores the token for the host.

When the CLI detects an AI agent, it also prints a note that tells the agent to
pass the URL and the code on to you, not to approve the login itself, and to
ask you for the confirmation code:

```console
Note for AI agents (claude-code): give the URL and the code above to the user.
Do not open the URL or approve the login yourself: the user must approve it.
Ask the user for the confirmation code their browser shows.
```

The pending login stays on your machine, so a confirmation code that ends up
somewhere else, such as an agent's conversation, cannot complete the login on
another machine.
Expand Down
Loading