OAuth Token Enterprise
Clients use the /oauth/token
endpoint to request OAuth access tokens for creating connections to Dremio. Users can create tokens using one of the following methods:
- Their username and password, if they are authenticated locally in Dremio or with an enterprise LDAP
- An external JWT obtained from an OIDC identity provider
- A personal access token (PAT)
The Dremio OAuth authorization server is located at {hostname}/oauth/token
. This endpoint does not use the base URL of {hostname}/api/v3
.
After a valid request, Dremio returns an OAuth access token in a JSON object, along with the token lifetime and other metadata.
OAuth Token Object{
"access_token": "eyJz93a...k4laUWw",
"expires_in": 3599,
"token_type": "Bearer",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"scope": "dremio.all offline_access",
"refresh_token": "ism9f1nf68lre2salj0tq0btor"
}
Object Attributes
access_token String
The returned access token. A client application passes this token when connecting with Dremio.
Example: eyJz93a...k4laUWw
expires_in Integer
The access token lifetime in seconds. The default lifetime is 3600 seconds (1 hour).
Example: 3599
token_type String
Bearer
for all access tokens.
issued_token_type String
urn:ietf:params:oauth:token-type:access_token
for access tokens.
scope String
A space-separated list of case-sensitive scopes associated with the OAuth access token. If the value contains multiple space-delimited strings, their order does not matter, and each scope adds an access range to the requested scope.
Example: dremio.all offline_access
refresh_token String Optional
An optional OAuth refresh token is a credential for obtaining a new access token when the current one expires. The refresh token field is included when the request scope
includes offline_access
.
Example: ism9f1nf68lre2salj0tq0btor
Exchanging a Username and Password
For users authenticated locally or with an enterprise LDAP server, Dremio can provide OAuth access tokens using your username and password.
Method and URLPOST /{hostname}/oauth/token
Parameters
username Body String
The username that will be embedded in the token.
Example: dremio_user
password Body String
The user's password.
Example: dremio123
grant_type Body String
The type of authentication method. For this method, the grant_type is password
.
scope Body String
Must contain dremio.all
. If the scope also contains offline_access
, Dremio will return a refresh token with the access token.
Example: dremio.all offline_access
- Python
- cURL
import requests
form_data = {
"username": "dremio_user",
"password": "dremio123",
"grant_type": "password",
"scope": "dremio.all offline_access"
}
request_header = {"Content-Type": "application/x-www-form-urlencoded"}
token_exchange_response = requests.post(
"https://{hostname}/oauth/token", headers=request_header, data=form_data)
if token_exchange_response.status_code == 200:
token_exchange_response_json = token_exchange_response.json()
dremio_access_token = token_exchange_response_json["access_token"]
dremio_access_token_expires_in_sec = token_exchange_response_json["expires_in"]
dremio_refresh_token = token_exchange_response_json["refresh_token"]
else:
print("Error: " + str(token_exchange_response.status_code))
curl -X POST 'https://{hostname}/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=dremio' \
--data-urlencode 'password=dremio123' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=dremio.all offline_access'
{
"access_token": "eyJz93a...k4laUWw",
"expires_in": 3599,
"token_type": "Bearer",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"scope": "dremio.all offline_access",
"refresh_token": "ism9f1nf68lre2salj0tq0btor"
}
The lifetime of this token is one hour.
Response Status Codes
200 OK
400 Bad Request
401 Unauthorized
403 Forbidden
500 Internal Server Error
Exchanging a Refresh Token
If a refresh token was requested with the OAuth access token using the offline_access
scope, the refresh token can be exchanged for fresh access tokens until the refresh token expires. Each refresh token has a lifetime of 30 days.
POST /{hostname}/oauth/token
Parameters
grant_type Body String
The type of token being exchanged. For a token refresh, the grant_type isrefresh_token
.
client_id Body String
The username in the original token request.
Example: dremio_user
refresh_token Body String
The refresh token returned with the original token request.
Example: ism9f1nf68lre2salj0tq0btor
- Python
- cURL
import requests
form_data = {
"grant_type": "refresh_token",
"client_id": "dremio",
"refresh_token": "ism9f1nf68lre2salj0tq0btor"
}
request_header = {"Content-Type": "application/x-www-form-urlencoded"}
token_exchange_response = requests.post(
"https://{hostname}/oauth/token", headers=request_header, data=form_data)
if token_exchange_response.status_code == 200:
token_exchange_response_json = token_exchange_response.json()
dremio_access_token = token_exchange_response_json["access_token"]
dremio_access_token_expires_in_sec = token_exchange_response_json["expires_in"]
else:
print("Error: " + str(token_exchange_response.status_code))
curl -X POST 'https://{hostname}/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'client_id=dremio' \
--data-urlencode 'refresh_token=ism9f1nf68lre2salj0tq0btor'
{
"access_token": "eyJz93a...k4laUWw",
"expires_in": 3599,
"token_type": "Bearer",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"scope": "dremio.all offline_access"
}
The lifetime of this token is one hour.
Response Status Codes
200 OK
400 Bad Request
401 Unauthorized
403 Forbidden
500 Internal Server Error
Exchanging an External JWT
Clients who authenticate with an OIDC external token provider can exchange their JWT for an OAuth access that can be used to create connections to Dremio.
Method and URLPOST /{hostname}/oauth/token
Parameters
subject_token Body String
The external JWT obtained from an OIDC provider like Microsoft Entra ID.
Example: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz... DYynR2lK6xB8xrAprgPA
subject_token_type Body String
The type of subject token used. For an external JWT, the subject_token_type is urn:ietf:params:oauth:token-type:jwt
.
grant_type Body String
The type being granted. For a token exchange, the grant_type is urn:ietf:params:oauth:grant-type:token-exchange
.
scope Body String
The scope of the request. For a token exchange, the scope is dremio.all
.
- Python
- cURL
import requests
form_data = {
"subject_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz...DYynR2lK6xB8xrAprgPA",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"scope": "dremio.all"
}
request_header = {"Content-Type": "application/x-www-form-urlencoded"}
token_exchange_response = requests.post(
"https://{hostname}/oauth/token", headers=request_header, data=form_data)
if token_exchange_response.status_code == 200:
token_exchange_response_json = token_exchange_response.json()
dremio_access_token = token_exchange_response_json["access_token"]
dremio_access_token_expires_in = token_exchange_response_json["expires_in"]
else:
print("Error: " + str(token_exchange_response.status_code))
curl -X POST 'https://{hostname}/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'subject_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz...DYynR2lK6xB8xrAprgPA' \
--data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:jwt' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'scope=dremio.all'
{
"access_token": "eyJz93a...k4laUWw",
"expires_in": 3599,
"token_type": "Bearer",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"scope": "dremio.all"
}
The lifetime of this token is the time remaining on the external JWT, up to one hour.
Response Status Codes
200 OK
400 Bad Request
401 Unauthorized
403 Forbidden
500 Internal Server Error
Exchanging a PAT
Exchanging a personal access token (PAT) for an OAuth access token provides the security benefit of a shorter token lifetime while allowing a client application to access protected resources with a more controlled access mechanism. OAuth access tokens also perform better due to faster validation time than PATs.
Method and URLPOST /{hostname}/oauth/token
Parameters
subject_token Body String
The personal access token to be exchanged.
Example: wPTsz2YrTVWQ7fw436Ec...911rJzUm6Xs1XrvU+w==
subject_token_type Body String
The type of subject token used. For a PAT, the subject_token_type is urn:ietf:params:oauth:token-type:dremio:personal-access-token
.
grant_type Body String
The type being granted. For a token exchange, the grant_type is urn:ietf:params:oauth:grant-type:token-exchange
.
scope Body String
The scope of the request. For a token exchange, the scope is dremio.all
.
- Python
- cURL
import requests
form_data = {
"subject_token": "wPTsz2YrTVWQ7fw436Ec...911rJzUm6Xs1XrvU+w==",
"subject_token_type": "urn:ietf:params:oauth:token-type:dremio:personal-access-token",
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"scope": "dremio.all"
}
request_header = {"Content-Type": "application/x-www-form-urlencoded"}
token_exchange_response = requests.post(
"https://{hostname}/oauth/token", headers=request_header, data=form_data)
if token_exchange_response.status_code == 200:
token_exchange_response_json = token_exchange_response.json()
dremio_access_token = token_exchange_response_json["access_token"]
dremio_access_token_expires_in_sec = token_exchange_response_json["expires_in"]
else:
print("Error: " + str(token_exchange_response.status_code))
curl -X POST 'https://{hostname}/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'subject_token=wPTsz2YrTVWQ7fw436Ec7Vs16TAWeRyojniYNXED1THt911rJzUm6Xs1XrvU+w==' \
--data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:dremio:personal-access-token' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'scope=dremio.all'
{
"access_token": "eyJz93a...k4laUWw",
"expires_in": 3599,
"token_type": "Bearer",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"scope": "dremio.all"
}
The lifetime of this token is the remaining lifetime of the PAT used in the exchange, up to one hour.
Response Status Codes
200 OK
400 Bad Request
401 Unauthorized
403 Forbidden
500 Internal Server Error
Exchanging a PAT with User Impersonation
Dremio’s inbound user impersonation feature allows a privileged user, called a proxy user, to run queries on Dremio as a second target user using the target user’s privileges. The privileged user obtains the necessary privileges to impersonate a second target user from an inbound impersonation policy created by the Dremio administrator. Once the inbound impersonation policy is in place, the proxy user runs queries as the target user as allowed by the target user’s privileges.
Example: Inbound Impersonation PolicyALTER SYSTEM SET "exec.impersonation.inbound_policies"='[
{
proxy_principals:{
users:["mark"]
},
target_principals:{
users:["sharedaccessuser"]
}
}
]'
POST /{hostname}/oauth/token
Parameters
subject_token Body String
The target_principal's username.
Example: sharedaccessuser
subject_token_type Body String
The type of subject token used. For a target principal, the subject_token_type is urn:ietf:params:oauth:token-type:dremio:subject
.
actor_token Body String
The proxy principal's personal access token.
Example: S0ilZcxyQCeH6m8hoNeCdVYwc...BjsxFsJfvCVhHsQ==
actor_token_type Body String
The type of actor token. For a PAT, the actor_token_type is urn:ietf:params:oauth:token-type:dremio:personal-access-token
.
grant_type Body String
The type being granted. For a token exchange, the grant_type is urn:ietf:params:oauth:grant-type:token-exchange
.
scope Body String
The scope of the request. For a token exchange, the scope is dremio.all
.
- Python
- cURL
import requests
form_data = {
"subject_token": "sharedaccessuser",
"subject_token_type": "urn:ietf:params:oauth:token-type:dremio:subject",
"actor_token": "wPTsz2YrTVWQ7fw436Ec7Vs16TAWeRyojniYNXED1THt911rJzUm6Xs1XrvU+w==",
"actor_token_type": "urn:ietf:params:oauth:token-type:dremio:personal-access-token",
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"scope": "dremio.all"
}
request_header = {"Content-Type": "application/x-www-form-urlencoded"}
token_exchange_response = requests.post(
"https://{hostname}/oauth/token", headers=request_header, data=form_data)
if token_exchange_response.status_code == 200:
token_exchange_response_json = token_exchange_response.json()
dremio_access_token = token_exchange_response_json["access_token"]
dremio_access_token_expires_in_sec = token_exchange_response_json["expires_in"]
else:
print("Error: " + str(token_exchange_response.status_code))
curl -X POST 'http://localhost:9047/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Accept: application/json' \
--data-urlencode 'subject_token=sharedaccessuser' \
--data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:dremio:subject' \
--data-urlencode 'actor_token=wPTsz2YrTVWQ7fw436Ec7Vs16TAWeRyojniYNXED1THt911rJzUm6Xs1XrvU+w==' \
--data-urlencode 'actor_token_type=urn:ietf:params:oauth:token-type:dremio:personal-access-token' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'scope=dremio.all'
{
"access_token": "eyJz93a...k4laUWw",
"expires_in": 3599,
"token_type": "Bearer",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"scope": "dremio.all"
}
The lifetime of this token is the remaining lifetime of the PAT used in the exchange, up to one hour.
Response Status Codes
200 OK
400 Bad Request
401 Unauthorized
403 Forbidden
500 Internal Server Error