Guideline 4.8 Login Services: có bắt buộc đăng nhập Apple?
Bởi Mehdi Azizi
Đăng ngày , 9 phút
Guideline 4.8: nếu app có đăng nhập Google hay Facebook, hãy thêm một cách đăng nhập bảo vệ e-mail, như Apple. Ngoại lệ, code Expo và xóa tài khoản.
Guideline 4.8 áp dụng ngay khi app của bạn dùng Google, Facebook hay một dịch vụ đăng nhập bên thứ ba khác để tạo tài khoản chính. Khi đó, nó bắt buộc có thêm một lựa chọn đăng nhập tương đương, chỉ giới hạn dữ liệu ở tên và e-mail, cho phép ẩn e-mail và không theo dõi người dùng để quảng cáo khi chưa có sự đồng ý. Từ tháng 1 năm 2024, lựa chọn này không còn nhất thiết phải là "Sign in with Apple", nhưng đó lại là cái mà chính Apple nêu tên trong thư từ chối.
Trong các app của mình, Solys và Nolera có đăng nhập bằng Apple, Google và e-mail. Bài hướng dẫn này đi từ văn bản hiện hành của Apple, rồi chỉ cách mình thêm đăng nhập Apple vào một app Expo kết nối Supabase, và nó thay đổi gì với việc xóa tài khoản. Nếu muốn xem toàn cảnh các lý do bị từ chối, hãy đọc vì sao Apple từ chối app.
Guideline 4.8 Login Services nói gì?
Mục 4.8 nằm trong phần 4, "Design", của App Review Guidelines. Nó nhắm vào các app dùng "a third-party or social login service" để tạo hoặc xác thực tài khoản chính: Facebook Login, Google Sign-In, Log in with X, LinkedIn, Amazon hay WeChat. Những app này phải có thêm, "as an equivalent option", một dịch vụ đăng nhập khác đáp ứng ba điều kiện.
| Điều kiện của Apple | Nói đơn giản |
|---|---|
| Dữ liệu giới hạn | Tên và e-mail, không hơn |
| Có thể giữ e-mail riêng tư | Người dùng có thể ẩn e-mail |
| Không quảng cáo khi chưa đồng ý | Không theo dõi quảng cáo khi chưa đồng ý |
Văn bản cũng định nghĩa tài khoản chính: là tài khoản người dùng tạo trong app của bạn để định danh, đăng nhập và dùng các tính năng. Theo định nghĩa này, một nút Google chỉ dùng để nhập một tệp thì không tạo tài khoản chính. Mục 4.8 nhắm vào màn hình mà người dùng đi qua để vào app.
Điều gì đã thay đổi vào tháng 1 năm 2024
Trước 2024, quy định bắt buộc "Sign in with Apple" với các app dùng đăng nhập bên thứ ba cho tài khoản chính. Ngày 25 tháng 1 năm 2024, Apple nới lỏng điểm này: bạn có thể dùng đăng nhập Apple, hoặc một dịch vụ tương đương bảo vệ quyền riêng tư. Nhiều trang vẫn còn ghi ngược lại. Tài liệu của Expo vẫn viết rằng app có đăng nhập bên thứ ba phải có Apple.
Trên thực tế, thư từ chối 4.8 được đăng trên diễn đàn nhà phát triển của Apple kết thúc như sau: "Note that Sign in with Apple meets the requirements specified in guideline 4.8". Apple không nêu tên dịch vụ hợp lệ nào khác. Để khỏi phải đoán ý reviewer, mình thêm đăng nhập Apple.
Năm ngoại lệ có trong văn bản
Apple liệt kê năm trường hợp không yêu cầu cách đăng nhập nào khác:
- App của bạn chỉ dùng hệ thống tài khoản riêng, ví dụ e-mail kèm mật khẩu hoặc mã gửi qua e-mail.
- App của bạn là một kho app thay thế, hoặc được phân phối qua một kho như vậy, với cách đăng nhập riêng của kho đó.
- App của bạn thuộc lĩnh vực giáo dục, doanh nghiệp hoặc công việc, và yêu cầu một tài khoản trường học hay công ty có sẵn.
- App của bạn dùng hệ thống định danh điện tử do nhà nước hoặc một ngành hỗ trợ.
- App của bạn là client của một dịch vụ bên thứ ba cụ thể: người dùng đăng nhập vào hộp thư hay mạng xã hội của họ để truy cập nội dung của chính mình.
Trước cả các ngoại lệ này, hãy tự hỏi: app của bạn có cần tài khoản không? Nếu không, guideline 5.1.1(v) yêu cầu app phải dùng được mà không cần đăng nhập, như mình giải thích trong bài hướng dẫn guideline 5.1.1.
| Màn hình đăng nhập của bạn | Có áp dụng 4.8? |
|---|---|
| Không có tài khoản | Không |
| Chỉ e-mail hoặc mã | Không |
| Chỉ Google | Có |
| Google và e-mail | Có, về nguyên tắc |
| Google và Apple | Có, và hợp lệ |
| Tài khoản trường học có sẵn | Không |
| Google để nhập tệp | Không, không có tài khoản |
Thêm "Sign in with Apple" vào app Expo
1. Cài module và khai báo capability
npx expo install expo-apple-authentication
Sau đó, tài liệu của Expo yêu cầu bật capability trong cấu hình app:
{
"expo": {
"ios": {
"usesAppleSignIn": true,
"infoPlist": { "CFBundleAllowMixedLocalizations": true }
}
}
}
Dòng thứ hai giúp nút hiển thị theo ngôn ngữ của iPhone. Với EAS Build, capability được bật trên định danh app của bạn lúc build. Đây là thiết lập native: nó đi kèm một build mới, không bao giờ qua cập nhật từ xa.
Một cái bẫy mình phát hiện khi đọc lại code khởi đầu của các kit: capability này bắt buộc phải ký, kể cả khi chỉ chạy app trên simulator. Trên một máy Mac không có chứng chỉ "Apple Development", việc biên dịch local thất bại với lỗi "No code signing certificates are available to use". Cách sửa: chỉ bật đăng nhập Apple khi máy chủ xác thực đã được cấu hình.
2. Hiển thị nút chính thức, nổi bật ngang Google
Quy tắc thiết kế của Apple rất rõ: nút Apple không được nhỏ hơn các nút đăng nhập khác, và người dùng không phải cuộn màn hình mới thấy nó. Component của Expo vẽ đúng nút chính thức, với tiêu đề được Apple cho phép.
import * as AppleAuthentication from "expo-apple-authentication";
import { useEffect, useState } from "react";
export function BoutonApple({ onPress }: { onPress: () => void }) {
const [disponible, setDisponible] = useState(false);
useEffect(() => {
AppleAuthentication.isAvailableAsync().then(setDisponible);
}, []);
// Android và web: không có đăng nhập Apple, không có nút.
if (!disponible) return null;
return (
<AppleAuthentication.AppleAuthenticationButton
buttonType={AppleAuthentication.AppleAuthenticationButtonType.CONTINUE}
buttonStyle={AppleAuthentication.AppleAuthenticationButtonStyle.BLACK}
cornerRadius={12}
style={{ width: "100%", height: 50 }}
onPress={onPress}
/>
);
}
Expo lưu ý rằng nút sẽ không hiện nếu thiếu chiều rộng và chiều cao. Màu và độ bo góc đặt qua buttonStyle và cornerRadius, không qua style.
3. Mở phiên đăng nhập trong Supabase
import * as AppleAuthentication from "expo-apple-authentication";
import { supabase } from "./supabase";
export async function connexionApple(): Promise<"ok" | "annule"> {
try {
const credential = await AppleAuthentication.signInAsync({
requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
AppleAuthentication.AppleAuthenticationScope.EMAIL,
],
});
if (!credential.identityToken) throw new Error("Thiếu token Apple");
const { error } = await supabase.auth.signInWithIdToken({
provider: "apple",
token: credential.identityToken,
});
if (error) throw error;
// Tên chỉ được gửi ở lần cấp quyền đầu tiên: lưu lại ngay.
const prenom = credential.fullName?.givenName;
if (prenom) await supabase.auth.updateUser({ data: { prenom } });
return "ok";
} catch (e) {
if ((e as { code?: string }).code === "ERR_REQUEST_CANCELED")
return "annule";
throw e;
}
}
Có bốn chi tiết quan trọng, lấy từ tài liệu Supabase, tài liệu Expo và quy tắc thiết kế của Apple:
- Trong Supabase, khai báo bundle identifier của bạn trong mục Client IDs của nhà cung cấp Apple. Một app thuần native không cần khóa bí mật để đăng nhập. Thêm
host.exp.Exponentnếu bạn thử trong Expo Go. - Tên và e-mail chỉ được gửi một lần. Apple không gửi lại ở các lần đăng nhập sau: hãy lưu ngay từ lần trả về đầu tiên.
- E-mail có thể là địa chỉ chuyển tiếp (relay). Apple khuyên không nên hỏi lại địa chỉ cá nhân sau đó.
- Hủy không phải là lỗi. Trên Nolera, đóng bảng Apple không hiện thông báo đỏ nào: đó là thao tác chủ động.
Một trường hợp mình gặp thật trên Solys, tháng 8 năm 2026: nút Apple và Google đều có trong app, nhưng chưa nhà cung cấp nào được bật trong Supabase. Code không sai, việc sửa diễn ra ở phía máy chủ, không cần build mới. Một nút Apple bị lỗi trước mặt reviewer sẽ khiến bạn bị từ chối theo 2.1 thay vì 4.8. Chi tiết có trong bài hướng dẫn guideline 2.1.
4. Thử trên iPhone thật
Expo cảnh báo rằng simulator chỉ cho thử nghiệm hạn chế, và thông tin định danh nhận được trong Expo Go khác với app đã phát hành. Hãy thử đăng nhập, đăng xuất rồi đăng nhập lại trên iPhone thật, với một build TestFlight.
Đăng nhập Apple và xóa tài khoản
Guideline 5.1.1(v) yêu cầu tài khoản tạo trong app phải xóa được ngay trong app. Với đăng nhập Apple, trang của Apple về xóa tài khoản thêm một bước: dùng REST API của Sign in with Apple để thu hồi token của người dùng.
Việc thu hồi này cần hai thứ: một token của người dùng, có được bằng cách xác thực một mã ủy quyền, và một secret ký bằng khóa riêng Sign in with Apple của bạn. Dù đăng nhập native không cần khóa bí mật, việc thu hồi lại cần, và khóa đó phải nằm trên máy chủ của bạn. Lý do có trong khóa API bí mật trong app Expo.
Trên Nolera, khi xóa tài khoản, app yêu cầu đăng nhập Apple lại để lấy một mã ủy quyền mới. App gửi mã đó tới một hàm phía máy chủ, hàm này đổi mã với Apple rồi thu hồi token. Nếu người dùng hủy, một thông báo rõ ràng cho biết điều đó và không có gì bị xóa. Phần còn lại của quy trình, gồm dữ liệu, gói đăng ký và việc thử nghiệm, có trong xóa tài khoản iOS.
Trả lời Apple thế nào sau khi bị từ chối theo 4.8
Thư của Apple đưa ra hai lối thoát. Hoặc bạn thêm một lựa chọn tương đương. Hoặc app của bạn đã có sẵn: bạn trả lời trong App Store Connect, nói rõ đó là lựa chọn nào và vì sao nó đáp ứng ba điều kiện. Apple cũng gợi ý cập nhật các ảnh chụp màn hình có màn hình đăng nhập. Quy trình trả lời App Review giống với các quy định khác.
Đây là mẫu bằng tiếng Anh, bạn tự điều chỉnh (thay số build):
Hello,
Thank you for your review.
Build X adds Sign in with Apple as an equivalent login option.
It appears on the same screen as Google Sign-In, with the same
size, and is visible without scrolling.
How to verify: launch the app, open the sign-in screen and
tap "Continue with Apple".
We also updated the screenshots that show the sign-in screen.
Best regards,
Check-list 4.8 trước khi gửi
- Bạn biết app có cần tài khoản hay không. Nếu không, app dùng được mà không cần đăng nhập.
- Nếu Google, Facebook hay X tạo tài khoản, đăng nhập Apple nằm trên cùng màn hình.
- Nút Apple là nút chính thức, to bằng các nút khác, thấy được mà không cần cuộn.
- Nhà cung cấp Apple đã được bật phía máy chủ, với bundle identifier của bạn.
- Hủy thì quay về màn hình đăng nhập, không có thông báo lỗi.
- Tên và e-mail được lưu ngay từ lần đăng nhập đầu tiên.
- Xóa tài khoản sẽ thu hồi token Apple, từ máy chủ của bạn.
- Mọi thứ đã được thử trên iPhone thật, với một tài khoản Apple chưa từng đăng nhập vào app.
- Ảnh chụp màn hình thể hiện đúng màn hình đăng nhập như trong build đã gửi.
Sửa lỗi bị từ chối trước khi gửi lại app
Nếu app của bạn vừa bị từ chối theo 4.8, Apple Review Kit tập hợp những gì mình kiểm tra trước mỗi lần gửi, kèm hai skill đọc lại dự án của bạn trong Claude Code và chuẩn bị câu trả lời nếu Apple từ chối. Nếu cần một người xem giúp, đặt một giờ với mình: mình cùng đọc thư và xem màn hình đăng nhập của bạn. Toàn bộ các bước sau khi bị từ chối có ở trang app bị Apple từ chối.
Nếu bạn đang chuẩn bị phát hành lần đầu, làm bài chẩn đoán miễn phí: nó cho bạn biết nên bắt đầu từ bước nào và gửi bạn check-list chống bị Apple từ chối của mình.
Không ai có thể đảm bảo Apple sẽ duyệt app của bạn. Thêm đăng nhập Apple đúng chỗ ít nhất cũng gạch được lý do này khỏi danh sách.
Câu hỏi thường gặp
Đăng nhập bằng Apple có bắt buộc trên iOS không?
Không phải trong mọi trường hợp. Nó chỉ bắt buộc nếu app của bạn có đăng nhập bên thứ ba, như Google hay Facebook, để tạo tài khoản chính. Từ tháng 1 năm 2024, một dịch vụ tương đương khác có thể thay thế, nhưng Apple chỉ nêu tên đăng nhập Apple là hợp lệ.
"Guideline 4.8 - Design - Login Services" nghĩa là gì?
Đó là tiêu đề lý do từ chối trong thư của Apple. Nó có nghĩa là app của bạn có đăng nhập bên thứ ba mà không có lựa chọn tương đương nào giới hạn dữ liệu ở tên và e-mail, cho phép ẩn e-mail và không dùng cho quảng cáo khi chưa có sự đồng ý.
Đăng ký bằng e-mail bên cạnh Google có đủ không?
Không chắc. Văn bản yêu cầu một dịch vụ cho phép giữ e-mail riêng tư, trong khi một form thông thường lại hỏi e-mail. Apple chưa công bố quan điểm về trường hợp này, và thư từ chối của họ chỉ nêu tên đăng nhập Apple. Mình sẽ không mạo hiểm.
Có cần đăng nhập Apple trên Android không?
Không. 4.8 là quy định của App Store, và module của Expo chỉ chạy trên iOS. Trên Android, isAvailableAsync() trả về false: nút Apple không hiện, và chỉ để mỗi Google cũng được.
Có cần build mới sau khi bị từ chối theo 4.8 không?
Có, trong hầu hết trường hợp. Đăng nhập Apple cần một capability native, được bật lúc build. Cập nhật từ xa không thể thêm nó. Ngoại lệ duy nhất: app của bạn đã có sẵn một lựa chọn hợp lệ, và chỉ cần giải thích cho Apple trong câu trả lời.