Configuring Different Authentication Methods
Choose an authentication method
Set auth_type when initializing flyte-sdk, or select the equivalent CLI value, to choose how the SDK obtains credentials. For example, the public initialization API accepts the authentication settings below:
import flyte
await flyte.init(
endpoint="https://flyte.example.com",
auth_type="Pkce",
)
flyte.init() is asynchronous and its auth_type default is "Pkce". It forwards auth_type, command, client_id, and client_credentials_secret to the endpoint or API-key ClientSet path. The authenticator factory then accepts these canonical values:
| Goal | Canonical auth_type | CLI aliases accepted by sanitize_auth_type() |
|---|---|---|
| Interactive browser login | Pkce | pkce |
| Login without opening a browser on the SDK host | DeviceFlow | headless, device-flow, device_flow |
| Service account / service-to-service credentials | ClientSecret | client-secret, client_secret, clientsecret, app-credential, app_credential |
| Token-producing executable | ExternalCommand | external-command, external_command, externalcommand, command, custom |
The CLI normalizes aliases to the canonical values before the client is initialized. If calling the authenticator factory directly, use the canonical, case-sensitive values; an unrecognized value raises ValueError.
The backend's RemoteClientConfigStore supplies the resolved client configuration used by the OAuth flows. Depending on the selected flow, that configuration contains values such as client_id, scopes, audience, authorization_endpoint, token_endpoint, redirect_uri, and, for device login, device_authorization_endpoint.
All four authenticators inherit from Authenticator. Its refresh_credentials() method serializes refreshes with an asynchronous lock, stores successful credentials in KeyringStore, and deletes the endpoint's keyring entry when refresh raises an exception. Consequently, applications normally configure the method at initialization and let the channel authentication interceptors invoke refreshes as needed.
Use interactive browser login with PKCE
Choose Pkce when the process can complete a browser-based login and the client configuration includes a usable OAuth redirect URI:
import flyte
await flyte.init(
endpoint="https://flyte.example.com",
auth_type="Pkce",
)
PKCEAuthenticator resolves the client configuration and creates an AuthorizationClient. Its setup is equivalent to the following project code:
self._auth_client = AuthorizationClient(
endpoint=self._endpoint,
redirect_uri=cfg.redirect_uri,
client_id=cfg.client_id,
audience=cfg.audience,
scopes=cfg.scopes,
auth_endpoint=cfg.authorization_endpoint,
token_endpoint=cfg.token_endpoint,
verify=self._verify,
http_session=self._http_session,
request_auth_code_params={
"code_challenge": code_challenge,
"code_challenge_method": "S256",
},
request_access_token_params={
"code_verifier": code_verifier,
},
refresh_access_token_params={},
add_request_auth_code_params_to_request_access_token_params=True,
)
Before constructing that client, PKCEAuthenticator._initialize_auth_client() generates a verifier and a SHA-256 challenge. The challenge is sent with the authorization request, while the verifier is sent when the authorization code is exchanged. AuthorizationClient starts the localhost callback server and opens the login URL. If the browser cannot be opened, the URL is printed for manual use.
Configure these client values before selecting PKCE:
redirect_urimust provide the hostname, port, and callback path expected by the localhost callback server.authorization_endpointandtoken_endpointmust be available inClientConfigor through the remote configuration store.scopesand, where applicable,audienceare forwarded to the authorization and token requests.- TLS and proxy settings can be passed through initialization with
insecure_skip_verify,ca_cert_file_path, andhttp_proxy_url.
After a successful login, the authenticator first attempts to refresh existing credentials. If the refresh raises AccessTokenNotFoundError, it logs "Logging in..." and starts a new browser flow. The callback response is state-validated by AuthorizationClient; a mismatched state raises ValueError, a non-200 token exchange raises RuntimeError, and a token response without access_token raises ValueError.
PKCE refresh-token configuration
PKCE can only refresh an existing login when the stored credentials include a refresh token. The PKCEAuthenticator docstring specifically calls out Auth0 deployments: scopes such as offline_access, offline, and openid may be needed to receive and cache a refresh token. The source also distinguishes the scopes in the SDK configuration from the scopes used in FlyteCTL Helm configuration, so use the scopes required by the backend deployment rather than assuming that an access token implies refresh capability.
If there is no refresh token, or the stored token cannot be refreshed, the expected behavior is another browser login.
Use Device Flow for headless login
Select DeviceFlow when the SDK process should not open a browser locally. The user completes authentication on another browser using the URL and code printed by the SDK:
import flyte
await flyte.init(
endpoint="https://flyte.example.com",
auth_type="DeviceFlow",
)
The headless argument is forwarded through initialization, but the four authenticator implementations do not inspect it. Selecting DeviceFlow—or using a CLI alias such as headless that normalizes to DeviceFlow—controls the flow.
The backend must publish device_authorization_endpoint. DeviceCodeAuthenticator._do_refresh_credentials() checks this resolved public-client setting before making any request. If it is absent, authentication stops with:
Device Authentication is not available on the Flyte backend / authentication server
When cached credentials have a refresh token, the authenticator tries the refresh-token grant first. If token_client.get_token() raises AuthenticationError or AuthenticationPending, it logs "Logging in..." and falls back to device login. The fallback obtains a device code and prints a URL formed from the provider's verification_uri and user_code:
resp = await token_client.get_device_code(
cfg.device_authorization_endpoint,
cfg.client_id,
audience=cfg.audience,
scopes=cfg.scopes,
http_session=self._http_session,
)
full_uri = f"{resp.verification_uri}?user_code={resp.user_code}"
click.secho(
f"To Authenticate, navigate in a browser to the following URL: "
f"{click.style(full_uri, fg='blue', underline=True)}"
)
Open the printed URL, enter the displayed user code, and leave the SDK process running. It calls token_client.poll_token_endpoint() with the device response and the resolved token endpoint. Polling honors the provider's interval and expiration values; authorization_pending and slow_down are treated as pending states, and expiry results in an authentication error.
Use Client Credentials for a service account
Use ClientSecret for service-to-service authentication. Supply both client_id and client_credentials_secret:
import flyte
await flyte.init(
endpoint="https://flyte.example.com",
auth_type="ClientSecret",
client_id="my-service-account",
client_credentials_secret="service-account-secret",
)
ClientCredentialsAuthenticator rejects either missing or empty value at construction with:
both client_id and client_credentials_secret are required.
Unlike PKCE and Device Flow, this authenticator uses the explicitly supplied client ID rather than taking the client ID from Admin's public client configuration. It builds an HTTP Basic authorization header and requests a token with the resolved token_endpoint, scopes, audience, proxy, TLS, and HTTP-session settings:
authorization_header = token_client.get_basic_authorization_header(
self._client_id, self._client_credentials_secret
)
token, refresh_token, expires_in = await token_client.get_token(
token_endpoint=cfg.token_endpoint,
authorization_header=authorization_header,
http_proxy_url=self._http_proxy_url,
verify=self._verify,
scopes=cfg.scopes,
audience=cfg.audience,
http_session=self._http_session,
)
The returned Credentials contains the access token, the provider's refresh token value (if any), its expiry, and the endpoint. Client-credentials responses commonly do not include a refresh token, so subsequent refreshes obtain a new token through the client-credentials request.
For configuration-managed secrets, admin.clientSecretLocation points to a mounted secret file. PlatformConfig.auto() strips a trailing newline from a file-mounted secret. admin.clientSecretEnvVar can instead name an environment variable, but the source configuration warns that using an environment variable is less secure than using a mounted secret file.
Use an external command to produce the token
Choose ExternalCommand when an executable already performs token acquisition. Pass an argument list, not a shell command string:
import flyte
await flyte.init(
endpoint="https://flyte.example.com",
auth_type="ExternalCommand",
command=["my-token-command", "--audience", "https://flyte.example.com"],
)
AsyncCommandAuthenticator requires a non-empty List[str]. It invokes asyncio.create_subprocess_exec() with the list elements as separate arguments, captures both streams, and waits asynchronously with process.communicate(). On success, the complete decoded-and-stripped stdout becomes the access token:
process = await asyncio.create_subprocess_exec(
*typing.cast(typing.List[str], self._cmd),
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
stdout, stderr = await process.communicate()
return Credentials(
for_endpoint=self._endpoint,
access_token=stdout.decode().strip(),
)
Keep diagnostics off stdout: any extra stdout text becomes part of the token. A missing command raises AuthenticationError immediately. A non-zero exit status, process-start failure, or other exception is logged and normalized to AuthenticationError; the message tells the user to run the joined command directly for debugging. Avoid placing secrets in command arguments because the joined command is included in logs and error messages.
The same authenticator is also used for proxy-command authentication. When proxy_command is configured, the proxy interceptor factory creates an AsyncCommandAuthenticator with the header key set to proxy-authorization rather than the default authorization. http_proxy_url applies to the OAuth HTTP requests; it is separate from an external proxy-token command.
Verify the selected mode and troubleshoot initialization
Confirm CLI normalization
The CLI's sanitize_auth_type() maps aliases before configuration is passed to Flyte initialization:
def sanitize_auth_type(auth_type: str | None) -> str:
if auth_type is None:
return "pkce"
if auth_type.lower() in _pkce_options:
return "Pkce"
if auth_type.lower() in _device_flow_options:
return "DeviceFlow"
if auth_type.lower() in _client_secret_options:
return "ClientSecret"
if auth_type.lower() in _external_command_options:
return "ExternalCommand"
raise ValueError(f"Unknown auth type: {auth_type}. Supported types are: {ALL_AUTH_OPTIONS}.")
Use --auth-type with one of the listed aliases in the CLI. If a value is passed directly to get_async_authenticator(), use Pkce, DeviceFlow, ClientSecret, or ExternalCommand; the factory's match statement rejects other values.
API-key initialization
The endpoint path and API-key path are both exposed by _initialize_client():
if endpoint:
return await ClientSet.for_endpoint(
endpoint,
auth_type=auth_type,
command=command,
client_id=client_id,
client_credentials_secret=client_credentials_secret,
)
elif api_key:
return await ClientSet.for_api_key(
api_key,
auth_type=auth_type,
command=command,
client_id=client_id,
client_credentials_secret=client_credentials_secret,
)
For API-key authentication, create_channel() decodes the endpoint and credentials embedded in the key and forces ClientSecret authentication, populating the client-secret aliases before the factory is called. An API key therefore does not preserve a different requested OAuth mode.
TLS, cached credentials, and failed refreshes
TLS verification is enabled by default. insecure_skip_verify=True makes the factory pass verify=False; ca_cert_file_path selects custom certificate handling in the channel and session setup. Use the insecure option only when that behavior is appropriate for the deployment.
The base Authenticator loads endpoint credentials from the keyring. On a successful refresh it stores the newly returned Credentials; if a flow fails, it deletes the endpoint's keyring entry and re-raises the error. Concurrent refresh attempts are serialized, and a credential ID lets a caller avoid repeating work when another coroutine has already refreshed the credentials.
For PKCE, check redirect_uri, authorization metadata, and refresh-token scopes. For Device Flow, check that the backend advertises device_authorization_endpoint and that the user completes the printed URL/code flow. For Client Credentials, check both required inputs and the token endpoint. For External Command, run the exact argument list directly and verify that the token is the only content written to stdout.