Implementation:Apache Paimon DLFAuthProvider
| Knowledge Sources | |
|---|---|
| Domains | Authentication, Alibaba Cloud, DLF, Security |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
DLFAuthProvider implements authentication for Alibaba Cloud Data Lake Formation (DLF) using configurable signing algorithms and automatic token refresh.
Description
DLFAuthProvider is a comprehensive authentication provider specifically designed for Alibaba Cloud's Data Lake Formation (DLF) service. It implements the AuthProvider interface to generate authentication headers for REST API requests to DLF endpoints, supporting both the default VPC endpoint signing and the OpenAPI signing protocols.
The provider supports two primary initialization modes: token-based authentication using a DLFTokenLoader for automatic token refresh, and direct access key authentication using an access key ID, secret, and optional security token. The token loader mode is designed for long-running applications that need to automatically refresh credentials before they expire, with a configurable safety margin (TOKEN_EXPIRATION_SAFE_TIME_MILLIS) to ensure tokens are refreshed before actual expiration.
The authentication process involves multiple steps: generating signed headers including timestamps, content hashes, and security tokens; calculating authorization signatures based on the request method, path, query parameters, and body; and combining all authentication headers into the final request. The provider delegates the actual signing logic to a DLFRequestSigner implementation, which can be either DLFDefaultSigner for traditional VPC endpoints or DLFOpenApiSigner for newer OpenAPI endpoints.
The class includes intelligent host extraction logic that properly handles URIs with or without protocols, ports, and path components, ensuring the correct host value is used in signature calculations. Thread safety is maintained through volatile token storage and synchronized token refresh operations.
Usage
Use DLFAuthProvider when connecting to Alibaba Cloud DLF REST catalog endpoints that require signed requests. It handles the complexity of DLF authentication, including automatic token refresh, signature generation, and header construction according to DLF's authentication protocols.
Code Reference
Source Location
- Repository: Apache_Paimon
- File: paimon-api/src/main/java/org/apache/paimon/rest/auth/DLFAuthProvider.java
Signature
public class DLFAuthProvider implements AuthProvider {
public static final String DLF_AUTHORIZATION_HEADER_KEY = "Authorization";
public static final String DLF_CONTENT_MD5_HEADER_KEY = "Content-MD5";
public static final String DLF_CONTENT_TYPE_KEY = "Content-Type";
public static final String DLF_DATE_HEADER_KEY = "x-dlf-date";
public static final String DLF_SECURITY_TOKEN_HEADER_KEY = "x-dlf-security-token";
public static final String DLF_AUTH_VERSION_HEADER_KEY = "x-dlf-version";
public static final String DLF_CONTENT_SHA56_HEADER_KEY = "x-dlf-content-sha256";
@Nullable private final DLFTokenLoader tokenLoader;
private final String uri;
private final String region;
private final String signingAlgorithm;
@Nullable protected volatile DLFToken token;
private final DLFRequestSigner signer;
public static DLFAuthProvider fromTokenLoader(
DLFTokenLoader tokenLoader, String uri, String region, String signingAlgorithm);
public static DLFAuthProvider fromAccessKey(
String accessKeyId,
String accessKeySecret,
@Nullable String securityToken,
String uri,
String region,
String signingAlgorithm);
@Override
public Map<String, String> mergeAuthHeader(
Map<String, String> baseHeader, RESTAuthParameter restAuthParameter);
}
Import
import org.apache.paimon.rest.auth.DLFAuthProvider;
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| tokenLoader | DLFTokenLoader | No | Token loader for automatic refresh (mutually exclusive with access key) |
| token | DLFToken | No | Initial token for access key mode |
| uri | String | Yes | DLF service endpoint URI |
| region | String | Yes | Alibaba Cloud region identifier |
| signingAlgorithm | String | Yes | Signing algorithm: 'default' or 'openapi' |
| accessKeyId | String | No | Access key ID for direct authentication |
| accessKeySecret | String | No | Access key secret for direct authentication |
| securityToken | String | No | Optional security token for temporary credentials |
| baseHeader | Map<String, String> | Yes | Existing headers to merge with auth headers |
| restAuthParameter | RESTAuthParameter | Yes | Request parameters for signature calculation |
Outputs
| Name | Type | Description |
|---|---|---|
| mergeAuthHeader() | Map<String, String> | Returns headers including Authorization, x-dlf-*, and other auth headers |
| fromTokenLoader() | DLFAuthProvider | Static factory method returning token-loader-based provider |
| fromAccessKey() | DLFAuthProvider | Static factory method returning access-key-based provider |
Usage Examples
import org.apache.paimon.rest.auth.DLFAuthProvider;
import org.apache.paimon.rest.auth.DLFTokenLoader;
import org.apache.paimon.rest.auth.RESTAuthParameter;
// Example 1: Create provider with access keys (default signing)
DLFAuthProvider provider = DLFAuthProvider.fromAccessKey(
"LTAI***", // accessKeyId
"secret***", // accessKeySecret
null, // securityToken (optional)
"https://dlf.cn-hangzhou.aliyuncs.com", // uri
"cn-hangzhou", // region
"default" // signingAlgorithm
);
// Example 2: Create provider with access keys (OpenAPI signing)
DLFAuthProvider openapiProvider = DLFAuthProvider.fromAccessKey(
"LTAI***",
"secret***",
null,
"https://dlfnext.cn-hangzhou.aliyuncs.com",
"cn-hangzhou",
"openapi" // Use OpenAPI signing algorithm
);
// Example 3: Create provider with token loader
DLFTokenLoader tokenLoader = new DLFFileTokenLoader("/path/to/token.json");
DLFAuthProvider loaderProvider = DLFAuthProvider.fromTokenLoader(
tokenLoader,
"https://dlf.cn-beijing.aliyuncs.com",
"cn-beijing",
"default"
);
// Example 4: Create provider with temporary credentials
DLFAuthProvider tempProvider = DLFAuthProvider.fromAccessKey(
"STS.***", // temporary access key
"temp_secret***", // temporary secret
"security_token***", // security token (required for STS)
"https://dlf.cn-shanghai.aliyuncs.com",
"cn-shanghai",
"default"
);
// Example 5: Use provider to authenticate requests
Map<String, String> baseHeaders = new HashMap<>();
baseHeaders.put("User-Agent", "PaimonClient/1.0");
RESTAuthParameter authParam = new RESTAuthParameter(
"/api/v1/tables", // resource path
Collections.emptyMap(), // query params
"GET", // method
"" // body
);
Map<String, String> authenticatedHeaders = provider.mergeAuthHeader(
baseHeaders,
authParam
);
// Headers now include:
// - Authorization: DLF4-HMAC-SHA256 Credential=...
// - x-dlf-date: 20260208T120000Z
// - x-dlf-version: v1
// - x-dlf-content-sha256: UNSIGNED-PAYLOAD
// - x-dlf-security-token: (if using temporary credentials)
// Example 6: POST request with body
String requestBody = "{\"name\":\"my_table\",\"schema\":{...}}";
RESTAuthParameter postParam = new RESTAuthParameter(
"/api/v1/tables",
Collections.emptyMap(),
"POST",
requestBody
);
Map<String, String> postHeaders = provider.mergeAuthHeader(
baseHeaders,
postParam
);
// Additional headers for POST:
// - Content-Type: application/json
// - Content-MD5: <base64-encoded-md5>
// Example 7: Request with query parameters
Map<String, String> queryParams = new HashMap<>();
queryParams.put("namespace", "default");
queryParams.put("limit", "100");
RESTAuthParameter queryParam = new RESTAuthParameter(
"/api/v1/tables",
queryParams,
"GET",
""
);
Map<String, String> queryHeaders = provider.mergeAuthHeader(
baseHeaders,
queryParam
);
// Example 8: ECS metadata token loader
DLFTokenLoader ecsLoader = new DLFECSTokenLoader(
"http://100.100.100.200/latest/meta-data/Ram/security-credentials/",
"my-ecs-role"
);
DLFAuthProvider ecsProvider = DLFAuthProvider.fromTokenLoader(
ecsLoader,
"https://dlf.cn-hangzhou.aliyuncs.com",
"cn-hangzhou",
"default"
);
// Token is automatically loaded from ECS metadata service
// and refreshed before expiration
// Example 9: Host extraction (internal utility)
// These are handled automatically by the provider:
// "https://dlf.cn-hangzhou.aliyuncs.com/api" -> "dlf.cn-hangzhou.aliyuncs.com"
// "http://localhost:8080/prefix" -> "localhost:8080"
// "https://example.com" -> "example.com"