Alibaba Cloud Phone Sign-In (Recommended for China)
Configure Alibaba Cloud Dypnsapi SMS code sign-in
Alibaba Cloud Phone Sign-In
EasyStarter ships with phone sign-in powered by the Better Auth phone-number plugin. The server sends and verifies SMS codes through Alibaba Cloud Dypnsapi, while the clients keep using Better Auth's phoneNumber.sendOtp and phoneNumber.verify APIs.
If your product is deployed primarily in mainland China, phone sign-in should be the preferred, and often the only, sign-in method. SMS-code sign-in is the most familiar flow for local users, while GitHub, Google, Apple, and similar OAuth providers add extra availability, account-coverage, and compliance friction in China. Email/password can stay if your product needs it, but it is not required. For a China-first deployment, configuring Alibaba Cloud phone sign-in alone is enough; the other sign-in methods can remain disabled and unconfigured.
The built-in flow currently supports mainland China phone numbers only:
| Item | Current setup |
|---|---|
| Phone format | +86 E.164 format, for example +8613800138000 |
| Send API | SendSmsVerifyCode |
| Verify API | CheckSmsVerifyCode |
| Server provider | apps/server/src/sms/providers/aliyun.ts |
| Better Auth config | apps/server/src/lib/auth.ts |
Required Environment Variables
ALIBABA_CLOUD_ACCESS_KEY_ID=
ALIBABA_CLOUD_ACCESS_KEY_SECRET=These credentials are used by the server to call Alibaba Cloud OpenAPI. Do not commit them and do not expose them to frontend environment variables.
If you only keep phone sign-in, OAuth variables such as GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GOOGLE_CLIENT_ID, and GOOGLE_CLIENT_SECRET do not need to be configured. In production, keep the base Better Auth session variables plus the Alibaba Cloud AccessKey variables in this guide.
Enable Phone Number Verification Service
First, make sure your Alibaba Cloud account has enabled Phone Number Verification Service and can call the Dypnsapi SMS verification APIs.
Official API doc: SendSmsVerifyCode
Alibaba Cloud documents SendSmsVerifyCode as the SMS verification-code sending API under Dypnsapi. It uses API version 2017-05-25, and the permission action is dypns:SendSmsVerifyCode.
Create and Authorize a RAM User
Use a RAM user AccessKey instead of an Alibaba Cloud root account AccessKey.
- Log in to the Alibaba Cloud RAM Console
- Go to Identities → Users
- Click Create User
- Fill in the logon name and display name
- Select OpenAPI Access as the access mode
- After creating the user, grant it the permissions needed by Phone Number Verification Service
For a narrow policy, allow only the SMS verification APIs used by this project:
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dypns:SendSmsVerifyCode",
"dypns:CheckSmsVerifyCode"
],
"Resource": "*"
}
]
}During initial debugging, you can also use Alibaba Cloud's managed policies for Phone Number Verification Service and narrow the permissions later.
Get AccessKey ID and AccessKey Secret
Official doc: Create an AccessKey pair
- Log in to the Alibaba Cloud RAM Console
- Go to Identities → Users
- Open the RAM user you created
- Open the Authentication or AccessKey tab
- Click Create AccessKey
- Complete the security verification prompts
- Copy and save both values immediately:
AccessKey ID→ALIBABA_CLOUD_ACCESS_KEY_IDAccessKey Secret→ALIBABA_CLOUD_ACCESS_KEY_SECRET
AccessKey Secret is displayed only once when it is created. If you lose it, disable the old key and create a new AccessKey.
Set Local and Production Environment Variables
For local development, add them to apps/server/.dev.vars:
ALIBABA_CLOUD_ACCESS_KEY_ID=your-access-key-id
ALIBABA_CLOUD_ACCESS_KEY_SECRET=your-access-key-secretFor production, add them to apps/server/.env.production:
ALIBABA_CLOUD_ACCESS_KEY_ID=your-access-key-id
ALIBABA_CLOUD_ACCESS_KEY_SECRET=your-access-key-secret.env.production is only used to bulk-push Cloudflare Workers Secrets. It does not participate in frontend builds and should not be committed.
Push Production Secrets
Before deploying to Cloudflare Workers, push the production credentials to Workers Secrets:
pnpm -F server secrets:bulk:productionAfter this succeeds, the Worker runtime can read env.ALIBABA_CLOUD_ACCESS_KEY_ID and env.ALIBABA_CLOUD_ACCESS_KEY_SECRET. Re-run the same command whenever you rotate the credentials.
Keep the Alibaba Cloud Verification Parameters Unchanged
The built-in provider locks these parameters according to Alibaba Cloud's SendSmsVerifyCode documentation:
const ALIYUN_SMS_VERSION = "2017-05-25";
const ALIYUN_SMS_SIGN_NAME = "速通互联验证码";
const ALIYUN_SMS_TEMPLATE_CODE = "100001";Do not change these values:
| Constant | Alibaba Cloud parameter | Why it must stay unchanged |
|---|---|---|
ALIYUN_SMS_VERSION | OpenAPI version | Dypnsapi's SendSmsVerifyCode API version is 2017-05-25 |
ALIYUN_SMS_SIGN_NAME | SignName | The API documentation uses the bundled Phone Number Verification sign name 速通互联验证码; this API does not support ordinary custom SMS signs |
ALIYUN_SMS_TEMPLATE_CODE | TemplateCode | The bundled sign must be used with the bundled template, whose code is 100001 |
This integration uses Dypnsapi's SMS verification API, not the ordinary Dysmsapi SendSms API. Do not replace the template code with an SMS_... code from the ordinary SMS service.
Verify Phone Sign-In Locally
Start the server and web app, then choose phone sign-in on the login page:
pnpm dev:server
pnpm dev:webWhen the user requests a code, the frontend calls:
POST /api/auth/phone-number/send-otpWhen the user submits the code, it calls:
POST /api/auth/phone-number/verifyThe server converts the +86 E.164 number into CountryCode=86 and the local phone number required by Alibaba Cloud. Alibaba Cloud then generates, sends, and verifies the code.
Common Questions
Why not generate the code ourselves?
The current implementation uses TemplateParam={"code":"##code##","min":"5"}, so Alibaba Cloud generates the code. This lets the server verify the submitted code through CheckSmsVerifyCode without storing OTP state itself.
Why can't I use my own SMS sign?
SendSmsVerifyCode belongs to Phone Number Verification Service. Alibaba Cloud's documentation says the bundled sign must be used with the bundled template, and ordinary custom signs are not supported by this API. The built-in values match the official example.
What should I do if the AccessKey leaks?
Disable or delete the leaked AccessKey in the RAM Console immediately, create a new one, and push the updated apps/server/.env.production to Workers Secrets again.