Skip to content

Commit da8eb26

Browse files
authored
Ensure that refresh tokens are returned when using the external-browser credentials strategy (#931)
## What changes are proposed in this pull request? Today, the `external-browser` credentials strategy allows users to dynamically fetch an OAuth token without depending on external tools like the Databricks CLI. However, the requested scope is hard-coded to always be `all-apis`. As a result, after successfully authenticating, the authorization server will return only an access token and no refresh token. The access token will expire after an hour, and attempts to refresh the token will fail. This PR adds the `offline_access` scope to the default requested scopes during this flow. This matches the request made by the CLI in the `databricks auth login` flow. The resulting token includes a refresh token. ## How is this tested? I manually tested this by deleting the token cache at `~/.config/databricks-sdk-py/oauth` and then running the following script: ```py from databricks.sdk import WorkspaceClient w = WorkspaceClient(host="https://adb-2548836972759138.18.azuredatabricks.net", auth_type="external-browser") print(w.current_user.me()) ``` The resulting token is saved to the OAuth cache. This token includes the refresh token. ``` {"token": {"access_token": "eyJraWQiOiIy...", "token_type": "Bearer", "expiry": "2025-03-20T11:00:25.242011", "refresh_token": "doau6c1a..."}} ``` To force a refresh, I manually updated the expiry time to be in the past and reran the script. The token was refreshed and the script succeeded: ``` DEBUG:databricks.sdk.oauth:Retrieving token for databricks-cli DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): adb-2548836972759138.18.azuredatabricks.net:443 DEBUG:urllib3.connectionpool:https://adb-2548836972759138.18.azuredatabricks.net:443 "POST /oidc/v1/token HTTP/1.1" 200 None ```
1 parent cc7c236 commit da8eb26

File tree

2 files changed

+7
-3
lines changed

2 files changed

+7
-3
lines changed

NEXT_CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
### Bug Fixes
88

9+
* Ensure that refresh tokens are returned when using the `external-browser` credentials strategy.
10+
911
### Documentation
1012

1113
### Internal Changes

databricks/sdk/oauth.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,11 @@ def __init__(
629629
):
630630

631631
if not scopes:
632-
scopes = ["all-apis"]
632+
# all-apis ensures that the returned OAuth token can be used with all APIs, aside
633+
# from direct-to-dataplane APIs.
634+
# offline_access ensures that the response from the Authorization server includes
635+
# a refresh token.
636+
scopes = ["all-apis", "offline_access"]
633637

634638
self.redirect_url = redirect_url
635639
self._client_id = client_id
@@ -654,8 +658,6 @@ def noop_credentials(_: any):
654658
return lambda: {}
655659

656660
config = Config(host=host, credentials_strategy=noop_credentials)
657-
if not scopes:
658-
scopes = ["all-apis"]
659661
oidc = config.oidc_endpoints
660662
if not oidc:
661663
raise ValueError(f"{host} does not support OAuth")

0 commit comments

Comments
 (0)