Aliyun CDN is an independent download adapter. It can be paired with OSS or any other supported storage provider. CDN URL authentication uses its own key, not the OSS AccessKey secret.
config :my_app, MyApp.Storage,
provider: :aliyun,
region: "cn-hangzhou",
access_key_id: System.fetch_env!("OSS_ACCESS_KEY_ID"),
secret_access_key: System.fetch_env!("OSS_ACCESS_KEY_SECRET"),
cdn: [
provider: :aliyun,
endpoint: "https://cdn.example.com",
aliyun_auth_key: System.fetch_env!("CDN_AUTH_KEY"),
aliyun_auth_type: :a,
aliyun_auth_ttl: 1800
]The endpoint must be an HTTP(S) origin without a path or query. Configure the same authentication type, key and TTL on the CDN domain. The key is redacted from client inspection. Use either the domain's primary or secondary key.
Authentication types
| Type | Configuration | Signed URL |
|---|---|---|
| A (default) | aliyun_auth_type: :a | /file?auth_key=timestamp-rand-0-hash |
| B | aliyun_auth_type: :b | /YYYYMMDDHHMM/hash/file |
| C path (default C format) | aliyun_auth_type: :c | /hash/HEX_TIMESTAMP/file |
| C query | aliyun_auth_type: :c, aliyun_auth_format: :query | /file?sign=hash&time=HEX_TIMESTAMP |
| F | aliyun_auth_type: :f | /file?sign=hash&time=timestamp |
For C query/F, set aliyun_sign_param and aliyun_time_param to the domain's
configured parameter names (defaults "sign" and "time"). For F,
aliyun_time_format accepts :decimal (default) or :hex. C always uses
hexadecimal timestamps. A generates a random 32-character hexadecimal nonce;
opts[:rand] can supply an alphanumeric value for reproducible signing.
All types hash the encoded resource path, excluding query parameters. Object
keys are raw strings: do not pre-encode them. Slash separators are preserved.
A/B/C accept query_params; these parameters are not authenticated by the CDN
path-signing formula. Authentication parameter collisions are rejected. F
rejects existing query parameters, as required by its documented contract.
Expiration semantics
The domain expires a URL at timestamp + console TTL. Set aliyun_auth_ttl
to that console value, not to the requested URL lifetime. The library calculates
timestamp = now + expires_in - aliyun_auth_ttl, so expires_in retains its
meaning of remaining lifetime. The default console TTL assumed is 1800 seconds.
A mismatch between library and domain TTL changes the actual lifetime.
B uses UTC+8 timestamps with minute precision, rounded down, so links can expire up to 59 seconds earlier than requested. Avoid very short B lifetimes.
MyApp.Storage.authorize_download_url("my-bucket", "images/avatar.png", 3600)headers cannot be bound by CDN URL authentication and nonempty values are
rejected on this adapter. att_name is also rejected: set Content-Disposition
on the object or configure the origin/CDN response instead.
Uploads and origin access
With Aliyun CDN configured, upload_credential always returns the underlying
storage provider's presigned PUT URL, including its required headers, even when
cdn_upload is true. CDN download authentication alone does not authorize OSS
writes. Server-side storage operations also use the storage endpoint.
cdn_download: false returns direct storage download URLs. public_url returns
an unsigned CDN URL when CDN download is enabled; on an authenticated domain,
use authorize_download_url for actual access.
Configure the CDN origin and private-OSS origin authorization separately in Alibaba Cloud. Client-to-CDN authentication and CDN-to-OSS authentication are separate checks. This library does not create CDN domains, configure origin permissions, CORS, cache rules or refresh jobs.
Console setup and live test
For an initial test, use type A authentication with a private OSS bucket in the same Alibaba Cloud account:
- In the CDN console, open Domain Names (域名管理) and add or manage your
acceleration domain, for example
cdn.example.com. Select OSS domain as the origin type and the same bucket used byOSS_TEST_BUCKET. Point the domain's DNS CNAME at the address assigned by CDN. For HTTPS, configure a certificate on the CDN domain; HTTP endpoints are also supported by ExOss. - On that domain, open Origin Settings (回源配置) and locate Private OSS Bucket Origin (阿里云OSS私有Bucket回源). Complete the authorization prompt if shown, then enable the switch and choose same-account origin access. Account authorization and enabling the domain's switch are separate steps. Keep the bucket private. Cross-account buckets require the corresponding cross-account origin authorization instead.
- Open Access Control (访问控制) > URL Authentication (URL鉴权), click Modify Configuration (修改配置) and enable authentication. Select A, set a primary key (6–128 letters/digits), set the validity period to 1800 seconds, and leave rule conditions unused so all paths are protected. The authentication key is independent of the OSS AccessKey secret.
- Save and allow the domain/DNS settings to take effect. The test uses the acceleration domain itself, not the CDN-assigned CNAME target or OSS endpoint.
Keep the OSS environment variables from the OSS live test and add:
export OSS_TEST_CDN_ENDPOINT='http://cdn.example.com'
export OSS_TEST_CDN_AUTH_KEY='your-cdn-authentication-key'
export OSS_TEST_CDN_AUTH_TYPE='a'
export OSS_TEST_CDN_TTL='1800'
OSS_TEST_KEEP_OBJECTS=1 mix test test/ex_oss/aliyun_integration_test.exs --include aliyun_integration --only cdn_live --trace
Use https:// when HTTPS is configured. The test uploads cdn-test directly to
OSS, downloads it through the signed CDN URL, and checks its contents. The URL
is valid for 300 seconds even though the console TTL is 1800: ExOss adjusts the
signature timestamp as described above. OSS_TEST_CDN_TTL must match the console.
With OSS_TEST_KEEP_OBJECTS=1, the test prints the signed URL before requesting
it and retains the object for manual checking. Open the link, then remove the
auth_key query parameter and verify that access is rejected with HTTP 403.
Delete the printed OSS object after testing. Omit the retention flag to restore
automatic cleanup. This test verifies the selected authentication type only.
Diagnosing HTTP 403
Failures include selected response headers and the response body:
| Evidence | What to check |
|---|---|
X-Tengine-Error reports invalid md5hash | Authentication type, key and signed path |
X-Tengine-Error reports expired timestamp | Console TTL, OSS_TEST_CDN_TTL and system clock |
x-swift-error: orig response 4XX error, OSS XML AccessDenied, and because of bucket acl | Private OSS origin authorization and the domain's private-bucket origin switch |
| Referer or IP access-rule error | The domain's access rules must allow the test request |
An OSS-origin 403 does not by itself indicate a CDN URL signature error. After correcting the settings, rerun the test to get a new object path and URL.