āĻāύā§āĻĄ-āĻā§-āĻāύā§āĻĄ OAuth 2.0 āϏāĻžāĻāύ-āĻāύ āĻĢā§āϞ⧠āĻāĻžāϞāĻžāύā§āϰ āĻāύā§āϝ āĻāĻĒāύāĻŋ Firebase SDK āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻāĻĒāύāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āϤāĻžāĻĻā§āϰ Apple ID āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠Firebase-āĻāϰ āϏāĻžāĻĨā§ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖ āĻāϰāϤ⧠āĻĻāĻŋāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
āĻāĻĒāύāĻŋ āĻļā§āϰ⧠āĻāϰāĻžāϰ āĻāĻā§
Apple āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āϏāĻžāĻāύ āĻāύ āĻāϰāϤā§, āĻĒā§āϰāĻĨāĻŽā§ Apple āĻāϰ āĻŦāĻŋāĻāĻžāĻļāĻāĻžāϰ⧠āϏāĻžāĻāĻā§ Apple āĻāϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰā§āύ, āϤāĻžāϰāĻĒāϰ āĻāĻĒāύāĻžāϰ Firebase āĻĒā§āϰāĻāϞā§āĻĒā§āϰ āĻāύā§āϝ āĻāĻāĻāĻŋ āϏāĻžāĻāύ-āĻāύ āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰ⧠āĻšāĻŋāϏāĻžāĻŦā§ Apple āϏāĻā§āώāĻŽ āĻāϰā§āύ⧎
āĻ ā§āϝāĻžāĻĒāϞ āĻĄā§āĻā§āϞāĻĒāĻžāϰ āĻĒā§āϰā§āĻā§āϰāĻžāĻŽā§ āϝā§āĻ āĻĻāĻŋāύ
Apple āĻāϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ āĻļā§āϧā§āĻŽāĻžāϤā§āϰ Apple āĻŦāĻŋāĻāĻžāĻļāĻāĻžāϰ⧠āĻĒā§āϰā§āĻā§āϰāĻžāĻŽā§āϰ āϏāĻĻāϏā§āϝāĻĻā§āϰ āĻĻā§āĻŦāĻžāϰāĻž āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§ā§ˇ
āĻ ā§āϝāĻžāĻĒāϞ āĻĻāĻŋāϝāĻŧā§ āϏāĻžāĻāύ āĻāύ āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰā§āύ
- Apple āĻāϰ āĻĄā§āĻā§āϞāĻĒāĻžāϰ āϏāĻžāĻāĻā§āϰ āϏāĻžāϰā§āĻāĻŋāĻĢāĻŋāĻā§āĻ, āĻļāύāĻžāĻā§āϤāĻāĻžāϰ⧠āĻāĻŦāĻ āĻĒā§āϰā§āĻĢāĻžāĻāϞ āĻĒā§āώā§āĻ āĻžāϝāĻŧ āĻāĻĒāύāĻžāϰ āĻ ā§āϝāĻžāĻĒā§āϰ āĻāύā§āϝ Apple āĻĻāĻŋāϝāĻŧā§ āϏāĻžāĻāύ āĻāύ āϏāĻā§āώāĻŽ āĻāϰā§āύ⧎
- āĻāϝāĻŧā§āĻŦā§āϰ āĻāύā§āϝ Apple āĻāϰ āϏāĻžāĻĨā§ āĻāύāĻĢāĻŋāĻāĻžāϰ āϏāĻžāĻāύ āĻāύā§āϰ āĻĒā§āϰāĻĨāĻŽ āĻŦāĻŋāĻāĻžāĻā§ āĻŦāϰā§āĻŖāĻŋāϤ āĻšāĻŋāϏāĻžāĻŦā§ āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒā§āϰ āϏāĻžāĻĨā§ āĻāĻĒāύāĻžāϰ āĻāϝāĻŧā§āĻŦāϏāĻžāĻāĻ āϝā§āĻā§āϤ āĻāϰā§āύ⧎ āĻ
āύā§āϰā§āϧ āĻāϰāĻž āĻšāϞā§, āĻāĻāĻāĻŋ āϰāĻŋāĻāĻžāϰā§āύ āĻāĻāĻāϰāĻāϞ āĻšāĻŋāϏāĻžāĻŦā§ āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤ URL āύāĻŋāĻŦāύā§āϧāύ āĻāϰā§āύ:
āĻāĻĒāύāĻŋ Firebase āĻāύāϏā§āϞ āϏā§āĻāĻŋāĻāϏ āĻĒā§āώā§āĻ āĻžāϝāĻŧ āĻāĻĒāύāĻžāϰ Firebase āĻĒā§āϰāĻāϞā§āĻĒ āĻāĻāĻĄāĻŋ āĻĒā§āϤ⧠āĻĒāĻžāϰā§āύāĨ¤ āĻāĻĒāύāĻžāϰ āĻšāϝāĻŧā§ āĻā§āϞā§, āĻāĻĒāύāĻžāϰ āύāϤā§āύ āĻĒāϰāĻŋāώā§āĻŦāĻž āĻāĻāĻĄāĻŋ āύā§āĻ āĻāϰā§āύ, āϝāĻž āĻāĻĒāύāĻžāĻā§ āĻĒāϰāĻŦāϰā§āϤ⧠āĻŦāĻŋāĻāĻžāĻā§ āĻĒā§āϰāϝāĻŧā§āĻāύ āĻšāĻŦā§ā§ˇhttps://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
- āĻ ā§āϝāĻžāĻĒāϞ āĻŦā§āϝāĻā§āϤāĻŋāĻāϤ āĻā§ āĻĻāĻŋāϝāĻŧā§ āĻāĻāĻāĻŋ āϏāĻžāĻāύ āĻāύ āϤā§āϰāĻŋ āĻāϰā§āύ āĨ¤ āĻĒāϰāĻŦāϰā§āϤ⧠āĻŦāĻŋāĻāĻžāĻā§ āĻāĻĒāύāĻžāϰ āύāϤā§āύ āĻŦā§āϝāĻā§āϤāĻŋāĻāϤ āĻā§ āĻāĻŦāĻ āĻā§ āĻāĻāĻĄāĻŋāϰ āĻĒā§āϰāϝāĻŧā§āĻāύ āĻšāĻŦā§ā§ˇ
- āĻāĻĒāύāĻŋ āϝāĻĻāĻŋ Firebase Authentication āĻā§āύ⧠āĻŦā§āĻļāĻŋāώā§āĻā§āϝ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ āϝāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āĻāĻŽā§āϞ āĻĒāĻžāĻ āĻžāϝāĻŧ, āϝāĻžāϰ āĻŽāϧā§āϝ⧠āĻāĻŽā§āϞ āϞāĻŋāĻā§āĻ āϏāĻžāĻāύ-āĻāύ, āĻāĻŽā§āϞ āĻ āĻŋāĻāĻžāύāĻž āϝāĻžāĻāĻžāĻāĻāϰāĻŖ, āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻĒā§āϰāϤā§āϝāĻžāĻšāĻžāϰ, āĻāĻŦāĻ āĻ
āύā§āϝāĻžāύā§āϝ āϏāĻš, Apple āĻĒā§āϰāĻžāĻāĻā§āĻ āĻāĻŽā§āϞ āϰāĻŋāϞ⧠āĻĒāϰāĻŋāώā§āĻŦāĻž āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰā§āύ āĻāĻŦāĻ
noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com
(āĻŦāĻž āĻāĻĒāύāĻžāϰ āĻāĻžāϏā§āĻāĻŽāĻžāĻāĻāĻĄ āĻāĻŽā§āϞ āĻā§āĻŽāĻĒā§āϞā§āĻ āĻĻā§āĻŦāĻžāϰāĻž āĻ ā§āϝāĻžāĻĒāϞ āĻāĻŽā§āϞ Firebase Authentication āĻĒāĻžāĻ āĻžāύā§āϰ āĻāύā§āϝ āĻ ā§āϝāĻžāĻĒāϞ āĻŦā§āϝāĻā§āϤāĻŋāĻāϤ āĻāĻŽā§āϞ āϰāĻŋāϞ⧠āĻĒāϰāĻŋāώā§āĻŦāĻž āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰā§āύ) āĻŦā§āύāĻžāĻŽā§ āĻ ā§āϝāĻžāĻĒāϞ āĻāĻŽā§āϞ āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ.
āĻāĻāĻāĻŋ āϏāĻžāĻāύ-āĻāύ āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰ⧠āĻšāĻŋāϏāĻžāĻŦā§ Apple āϏāĻā§āώāĻŽ āĻāϰā§āύ⧎
- āĻāĻĒāύāĻžāϰ Apple āĻĒā§āϰāĻāϞā§āĻĒā§ Firebase āϝā§āĻ āĻāϰā§āύ āĨ¤ āĻāĻĒāύāĻŋ Firebase āĻāύāϏā§āϞ⧠āĻāĻĒāύāĻžāϰ āĻ ā§āϝāĻžāĻĒ āϏā§āĻ āĻāĻĒ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻĒāύāĻžāϰ āĻ ā§āϝāĻžāĻĒā§āϰ āĻŦāĻžāύā§āĻĄā§āϞ āĻāĻāĻĄāĻŋ āύāĻŋāĻŦāύā§āϧāύ āĻāϰāϤ⧠āĻā§āϞāĻŦā§āύ āύāĻžāĨ¤
- Firebase āĻāύāϏā§āϞ⧠, Auth āĻŦāĻŋāĻāĻžāĻāĻāĻŋ āĻā§āϞā§āύāĨ¤ āϏāĻžāĻāύ āĻāύ āĻĒāĻĻā§āϧāϤāĻŋ āĻā§āϝāĻžāĻŦā§, āĻ ā§āϝāĻžāĻĒāϞ āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰ⧠āϏāĻā§āώāĻŽ āĻāϰā§āύāĨ¤ āĻĒā§āϰā§āĻŦāĻŦāϰā§āϤ⧠āĻŦāĻŋāĻāĻžāĻā§ āĻāĻĒāύāĻŋ āϝ⧠āĻĒāϰāĻŋāώā§āĻŦāĻž āĻāĻāĻĄāĻŋ āϤā§āϰāĻŋ āĻāϰā§āĻā§āύ āϤāĻž āĻāϞā§āϞā§āĻ āĻāϰā§āύāĨ¤ āĻāĻāĻžāĻĄāĻŧāĻžāĻ, OAuth āĻā§āĻĄ āĻĢā§āϞ⧠āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύ āĻŦāĻŋāĻāĻžāĻā§ , āĻāĻĒāύāĻžāϰ Apple āĻāĻŋāĻŽ āĻāĻāĻĄāĻŋ āĻāĻŦāĻ āĻĒā§āϰā§āĻŦāĻŦāϰā§āϤ⧠āĻŦāĻŋāĻāĻžāĻā§ āĻāĻĒāύāĻžāϰ āϤā§āϰāĻŋ āĻāϰāĻž āĻŦā§āϝāĻā§āϤāĻŋāĻāϤ āĻā§ āĻāĻŦāĻ āĻā§ āĻāĻāĻĄāĻŋ āĻāϞā§āϞā§āĻ āĻāϰā§āύāĨ¤
āĻ ā§āϝāĻžāĻĒāϞ āĻŦā§āύāĻžāĻŽā§ āĻĄā§āĻāĻž āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧāϤāĻž āĻŽā§āύ⧠āĻāϞā§āύ
āĻ
ā§āϝāĻžāĻĒāϞā§āϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āϏāĻžāĻāύ āĻāύ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āϤāĻžāĻĻā§āϰ āĻāĻŽā§āϞ āĻ āĻŋāĻāĻžāύāĻž āϏāĻš āϤāĻžāĻĻā§āϰ āĻĄā§āĻāĻž āĻŦā§āύāĻžāĻŽā§ āĻāϰāĻžāϰ āĻŦāĻŋāĻāϞā§āĻĒ āĻĻā§āϝāĻŧ⧎ āϝ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰāĻž āĻāĻ āĻŦāĻŋāĻāϞā§āĻĒāĻāĻŋ āĻŦā§āĻā§ āύā§āύ āϤāĻžāĻĻā§āϰ āĻāĻžāĻā§ privaterelay.appleid.com
āĻĄā§āĻŽā§āύā§āϰ āĻāĻŽā§āϞ āĻ āĻŋāĻāĻžāύāĻž āϰāϝāĻŧā§āĻā§ā§ˇ āĻāĻĒāύāĻŋ āϝāĻāύ āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒā§ Apple āĻāϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ, āϤāĻāύ āĻāĻĒāύāĻžāĻā§ āĻ
āĻŦāĻļā§āϝāĻ āĻāĻ āĻŦā§āύāĻžāĻŽā§ Apple ID āϏāĻāĻā§āϰāĻžāύā§āϤ āϝā§āĻā§āύ āĻĒā§āϰāϝā§āĻā§āϝ āĻŦāĻŋāĻāĻžāĻļāĻāĻžāϰ⧠āύā§āϤāĻŋ āĻŦāĻž Apple āĻĨā§āĻā§ āĻļāϰā§āϤāĻžāĻŦāϞ⧠āĻŽā§āύ⧠āĻāϞāϤ⧠āĻšāĻŦā§āĨ¤
āĻāĻĒāύāĻŋ āĻāĻāĻāĻŋ āĻŦā§āύāĻžāĻŽā§ āĻ ā§āϝāĻžāĻĒāϞ āĻāĻāĻĄāĻŋāϰ āϏāĻžāĻĨā§ āϏāϰāĻžāϏāϰāĻŋ āϏāύāĻžāĻā§āϤāĻāĻžāϰ⧠āĻŦā§āϝāĻā§āϤāĻŋāĻāϤ āϤāĻĨā§āϝ āϏāĻāϝā§āĻā§āϤ āĻāϰāĻžāϰ āĻāĻā§ āϝā§āĻā§āύ āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āϏāĻŽā§āĻŽāϤāĻŋ āĻĒā§āϰāĻžāĻĒā§āϤ āĻāϰāĻž āĻāϰ āĻŽāϧā§āϝ⧠āϰāϝāĻŧā§āĻā§āĨ¤ āĻĢāĻžāϝāĻŧāĻžāϰāĻŦā§āϏ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻāϤ⧠āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤ āĻā§āϰāĻŋāϝāĻŧāĻžāĻā§āϞāĻŋ āĻ āύā§āϤāϰā§āĻā§āĻā§āϤ āĻĨāĻžāĻāϤ⧠āĻĒāĻžāϰā§:
- āĻāĻāĻāĻŋ āĻŦā§āύāĻžāĻŽā§ āĻ ā§āϝāĻžāĻĒāϞ āĻāĻāĻĄāĻŋ āĻŦāĻž āĻŦāĻŋāĻĒāϰā§āϤ⧠āĻāĻāĻāĻŋ āĻāĻŽā§āϞ āĻ āĻŋāĻāĻžāύāĻž āϞāĻŋāĻā§āĻ āĻāϰā§āύ.
- āĻāĻāĻāĻŋ āĻŦā§āύāĻžāĻŽā§ āĻ ā§āϝāĻžāĻĒāϞ āĻāĻāĻĄāĻŋāϤ⧠āĻāĻāĻāĻŋ āĻĢā§āύ āύāĻŽā§āĻŦāϰ āϞāĻŋāĻā§āĻ āĻāϰā§āύ āĻŦāĻž āĻāϰ āĻŦāĻŋāĻĒāϰā§āϤā§
- āĻāĻāĻāĻŋ āĻŦā§āύāĻžāĻŽā§ āϏāĻžāĻŽāĻžāĻāĻŋāĻ āĻļāĻāϏāĻžāĻĒāϤā§āϰ (āĻĢā§āϏāĻŦā§āĻ, āĻā§āĻāϞ, āĻāϤā§āϝāĻžāĻĻāĻŋ) āĻāĻāĻāĻŋ āĻŦā§āύāĻžāĻŽā§ āĻ ā§āϝāĻžāĻĒāϞ āĻāĻāĻĄāĻŋāϤ⧠āĻŦāĻž āĻāϰ āĻŦāĻŋāĻĒāϰā§āϤ⧠āϞāĻŋāĻā§āĻ āĻāϰā§āύ⧎
āĻāĻĒāϰā§āϰ āϤāĻžāϞāĻŋāĻāĻžāĻāĻŋ āϏāĻŽā§āĻĒā§āϰā§āĻŖ āύāϝāĻŧāĨ¤ āĻāĻĒāύāĻžāϰ āĻ ā§āϝāĻžāĻĒ āĻ ā§āϝāĻžāĻĒāϞā§āϰ āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧāϤāĻž āĻĒā§āϰāĻŖ āĻāϰāĻā§ āϤāĻž āύāĻŋāĻļā§āĻāĻŋāϤ āĻāϰāϤ⧠āĻāĻĒāύāĻžāϰ āĻĄā§āĻā§āϞāĻĒāĻžāϰ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āϏāĻĻāϏā§āϝāĻĒāĻĻ āĻŦāĻŋāĻāĻžāĻā§ āĻ ā§āϝāĻžāĻĒāϞ āĻĄā§āĻā§āϞāĻĒāĻžāϰ āĻĒā§āϰā§āĻā§āϰāĻžāĻŽ āϞāĻžāĻāϏā§āύā§āϏ āĻā§āĻā§āϤāĻŋ āĻĒāĻĄāĻŧā§āύāĨ¤
Apple āĻāϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ āĻāϰā§āύ āĻāĻŦāĻ Firebase āĻāϰ āϏāĻžāĻĨā§ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖ āĻāϰā§āύ⧎
āĻāĻāĻāĻŋ Apple āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āϏāĻžāĻĨā§ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖ āĻāϰāϤā§, āĻĒā§āϰāĻĨāĻŽā§ Apple āĻāϰ AuthenticationServices
āĻĢā§āϰā§āĻŽāĻāϝāĻŧāĻžāϰā§āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻā§ āϤāĻžāĻĻā§āϰ Apple āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§ āϏāĻžāĻāύ āĻāύ āĻāϰā§āύ āĻāĻŦāĻ āϤāĻžāϰāĻĒāϰ⧠āĻāĻāĻāĻŋ Firebase AuthCredential
āĻ
āĻŦāĻā§āĻā§āĻ āϤā§āϰāĻŋ āĻāϰāϤ⧠Apple āĻāϰ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž āĻĨā§āĻā§ āĻāĻāĻĄāĻŋ āĻā§āĻā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ:
āĻĒā§āϰāϤāĻŋāĻāĻŋ āϏāĻžāĻāύ-āĻāύ āĻ āύā§āϰā§āϧā§āϰ āĻāύā§āϝ, āĻāĻāĻāĻŋ āĻāϞā§āĻŽā§āϞ⧠āϏā§āĻā§āϰāĻŋāĻ āϤā§āϰāĻŋ āĻāϰā§āύâāĻāĻāĻāĻŋ "āύāύāϏ"âāϝāĻž āĻāĻĒāύāĻŋ āύāĻŋāĻļā§āĻāĻŋāϤ āĻāϰāϤ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŦā§āύ āϝ⧠āĻāĻĒāύāĻŋ āϝ⧠āĻāĻāĻĄāĻŋ āĻā§āĻā§āύāĻāĻŋ āĻĒā§āϝāĻŧā§āĻā§āύ āϤāĻž āĻāĻĒāύāĻžāϰ āĻ ā§āϝāĻžāĻĒā§āϰ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖ āĻ āύā§āϰā§āϧā§āϰ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž āĻšāĻŋāϏāĻžāĻŦā§ āĻŦāĻŋāĻļā§āώāĻāĻžāĻŦā§ āĻŽāĻā§āĻā§āϰ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤ āϰāĻŋāĻĒā§āϞ⧠āĻāĻā§āϰāĻŽāĻŖ āĻĒā§āϰāϤāĻŋāϰā§āϧ āĻāϰāĻžāϰ āĻāύā§āϝ āĻāĻ āĻĒāĻĻāĻā§āώā§āĻĒāĻāĻŋ āĻā§āϰā§āϤā§āĻŦāĻĒā§āϰā§āĻŖāĨ¤
āĻāĻĒāύāĻŋ āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤ āĻāĻĻāĻžāĻšāϰāĻŖā§āϰ āĻŽāϤā§
SecRandomCopyBytes(_:_:_)
āĻĻāĻŋāϝāĻŧā§ āĻāĻāĻāĻŋ āĻā§āϰāĻŋāĻĒā§āĻā§āĻā§āϰāĻžāĻĢāĻŋāĻāĻāĻžāĻŦā§ āϏā§āϰāĻā§āώāĻŋāϤ āύāύā§āϏ āϤā§āϰāĻŋ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ:āϏā§āĻāĻĢāĻ
private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) var randomBytes = [UInt8](repeating: 0, count: length) let errorCode = SecRandomCopyBytes(kSecRandomDefault, randomBytes.count, &randomBytes) if errorCode != errSecSuccess { fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") let nonce = randomBytes.map { byte in // Pick a random character from the set, wrapping around if needed. charset[Int(byte) % charset.count] } return String(nonce) }
āĻāĻĻā§āĻĻā§āĻļā§āϝ-C
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce - (NSString *)randomNonce:(NSInteger)length { NSAssert(length > 0, @"Expected nonce to have positive length"); NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._"; NSMutableString *result = [NSMutableString string]; NSInteger remainingLength = length; while (remainingLength > 0) { NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16]; for (NSInteger i = 0; i < 16; i++) { uint8_t random = 0; int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random); NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode); [randoms addObject:@(random)]; } for (NSNumber *random in randoms) { if (remainingLength == 0) { break; } if (random.unsignedIntValue < characterSet.length) { unichar character = [characterSet characterAtIndex:random.unsignedIntValue]; [result appendFormat:@"%C", character]; remainingLength--; } } } return [result copy]; }
āĻāĻĒāύāĻŋ āĻāĻĒāύāĻžāϰ āϏāĻžāĻāύ-āĻāύ āĻ āύā§āϰā§āϧā§āϰ āϏāĻžāĻĨā§ āύāύāϏā§āϰ SHA256 āĻšā§āϝāĻžāĻļ āĻĒāĻžāĻ āĻžāĻŦā§āύ, āϝāĻž Apple āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻžāϝāĻŧ āĻ āĻĒāϰāĻŋāĻŦāϰā§āϤāĻŋāϤ āĻĒāĻžāϏ āĻāϰāĻŦā§āĨ¤ Firebase āĻāϏāϞ āύāύā§āϏ āĻšā§āϝāĻžāĻļ āĻāϰ⧠āĻāĻŦāĻ Apple āĻĻā§āĻŦāĻžāϰāĻž āĻĒāĻžāϏ āĻāϰāĻž āĻŽāĻžāύā§āϰ āϏāĻžāĻĨā§ āϤā§āϞāύāĻž āĻāϰ⧠āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž āϝāĻžāĻāĻžāĻ āĻāϰā§āĨ¤
āϏā§āĻāĻĢāĻ
@available(iOS 13, *) private func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { String(format: "%02x", $0) }.joined() return hashString }
āĻāĻĻā§āĻĻā§āĻļā§āϝ-C
- (NSString *)stringBySha256HashingString:(NSString *)input { const char *string = [input UTF8String]; unsigned char result[CC_SHA256_DIGEST_LENGTH]; CC_SHA256(string, (CC_LONG)strlen(string), result); NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { [hashed appendFormat:@"%02x", result[i]]; } return hashed; }
Apple-āĻāϰ āϏāĻžāĻāύ-āĻāύ āĻĢā§āϞ⧠āĻļā§āϰ⧠āĻāϰā§āύ, āĻāĻĒāύāĻžāϰ āĻ āύā§āϰā§āϧ⧠āύāύāϏā§āϰ SHA256 āĻšā§āϝāĻžāĻļ āĻāĻŦāĻ āĻ ā§āϝāĻžāĻĒāϞā§āϰ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž āĻĒāϰāĻŋāĻāĻžāϞāύāĻž āĻāϰāĻŦā§ āĻāĻŽāύ āĻĒā§āϰāϤāĻŋāύāĻŋāϧāĻŋ āĻā§āϞāĻžāϏ āϏāĻš (āĻĒāϰāĻŦāϰā§āϤ⧠āϧāĻžāĻĒāĻāĻŋ āĻĻā§āĻā§āύ):
āϏā§āĻāĻĢāĻ
import CryptoKit // Unhashed nonce. fileprivate var currentNonce: String? @available(iOS 13, *) func startSignInWithAppleFlow() { let nonce = randomNonceString() currentNonce = nonce let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() request.requestedScopes = [.fullName, .email] request.nonce = sha256(nonce) let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() }
āĻāĻĻā§āĻĻā§āĻļā§āϝ-C
@import CommonCrypto; - (void)startSignInWithAppleFlow { NSString *nonce = [self randomNonce:32]; self.currentNonce = nonce; ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init]; ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest]; request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; request.nonce = [self stringBySha256HashingString:nonce]; ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]]; authorizationController.delegate = self; authorizationController.presentationContextProvider = self; [authorizationController performRequests]; }
ASAuthorizationControllerDelegate
āĻāĻĒāύāĻžāϰ āĻŦāĻžāϏā§āϤāĻŦāĻžāϝāĻŧāύ⧠āĻ ā§āϝāĻžāĻĒāϞā§āϰ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž āĻĒāϰāĻŋāĻāĻžāϞāύāĻž āĻāϰā§āύāĨ¤ āϏāĻžāĻāύ-āĻāύ āϏāĻĢāϞ āĻšāϞā§, āĻĢāĻžāϝāĻŧāĻžāϰāĻŦā§āϏā§āϰ āϏāĻžāĻĨā§ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖā§āϰ āĻāύā§āϝ āĻāύāĻšā§āϝāĻžāĻļāĻĄ āύāύā§āϏ āϏāĻš āĻ ā§āϝāĻžāĻĒāϞā§āϰ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž āĻĨā§āĻā§ āĻāĻāĻĄāĻŋ āĻā§āĻā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ:āϏā§āĻāĻĢāĻ
@available(iOS 13.0, *) extension MainViewController: ASAuthorizationControllerDelegate { func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential { guard let nonce = currentNonce else { fatalError("Invalid state: A login callback was received, but no login request was sent.") } guard let appleIDToken = appleIDCredential.identityToken else { print("Unable to fetch identity token") return } guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else { print("Unable to serialize token string from data: \(appleIDToken.debugDescription)") return } // Initialize a Firebase credential, including the user's full name. let credential = OAuthProvider.appleCredential(withIDToken: idTokenString, rawNonce: nonce, fullName: appleIDCredential.fullName) // Sign in with Firebase. Auth.auth().signIn(with: credential) { (authResult, error) in if error { // Error. If error.code == .MissingOrInvalidNonce, make sure // you're sending the SHA256-hashed nonce as a hex string with // your request to Apple. print(error.localizedDescription) return } // User is signed in to Firebase with Apple. // ... } } } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { // Handle error. print("Sign in with Apple errored: \(error)") } }
āĻāĻĻā§āĻĻā§āĻļā§āϝ-C
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) { if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) { ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential; NSString *rawNonce = self.currentNonce; NSAssert(rawNonce != nil, @"Invalid state: A login callback was received, but no login request was sent."); if (appleIDCredential.identityToken == nil) { NSLog(@"Unable to fetch identity token."); return; } NSString *idToken = [[NSString alloc] initWithData:appleIDCredential.identityToken encoding:NSUTF8StringEncoding]; if (idToken == nil) { NSLog(@"Unable to serialize id token from data: %@", appleIDCredential.identityToken); } // Initialize a Firebase credential, including the user's full name. FIROAuthCredential *credential = [FIROAuthProvider appleCredentialWithIDToken:IDToken rawNonce:self.appleRawNonce fullName:appleIDCredential.fullName]; // Sign in with Firebase. [[FIRAuth auth] signInWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error != nil) { // Error. If error.code == FIRAuthErrorCodeMissingOrInvalidNonce, // make sure you're sending the SHA256-hashed nonce as a hex string // with your request to Apple. return; } // Sign-in succeeded! }]; } } - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) { NSLog(@"Sign in with Apple errored: %@", error); }
Firebase Auth āĻĻā§āĻŦāĻžāϰāĻž āϏāĻŽāϰā§āĻĨāĻŋāϤ āĻ āύā§āϝāĻžāύā§āϝ āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰā§āĻĻā§āϰ āĻĨā§āĻā§ āĻāĻŋāύā§āύ, Apple āĻāĻāĻāĻŋ āĻĢāĻā§ URL āĻĒā§āϰāĻĻāĻžāύ āĻāϰ⧠āύāĻžāĨ¤
āĻāĻāĻžāĻĄāĻŧāĻžāĻ, āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āϝāĻāύ āĻ
ā§āϝāĻžāĻĒā§āϰ āϏāĻžāĻĨā§ āϤāĻžāĻĻā§āϰ āĻāĻŽā§āϞ āĻļā§āϝāĻŧāĻžāϰ āύāĻž āĻāϰāĻž āĻŦā§āĻā§ āύā§āϝāĻŧ, āϤāĻāύ āĻ
ā§āϝāĻžāĻĒāϞ āϏā§āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻāύā§āϝ āĻāĻāĻāĻŋ āĻ
āύāύā§āϝ āĻāĻŽā§āϞ āĻ āĻŋāĻāĻžāύāĻžāϰ āĻŦā§āϝāĻŦāϏā§āĻĨāĻž āĻāϰ⧠(āĻĢāϰā§āĻŽ xyz@privaterelay.appleid.com
), āϝāĻž āĻāĻāĻŋ āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒā§āϰ āϏāĻžāĻĨā§ āĻļā§āϝāĻŧāĻžāϰ āĻāϰā§āĨ¤ āĻāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻŦā§āϝāĻā§āϤāĻŋāĻāϤ āĻāĻŽā§āϞ āϰāĻŋāϞ⧠āĻĒāϰāĻŋāώā§āĻŦāĻž āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰā§āύ, āĻ
ā§āϝāĻžāĻĒāϞ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻāϏāϞ āĻāĻŽā§āϞ āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ āĻŦā§āύāĻžāĻŽā§ āĻ āĻŋāĻāĻžāύāĻžāϝāĻŧ āĻĒāĻžāĻ āĻžāύ⧠āĻāĻŽā§āϞāĻā§āϞāĻŋ āĻĢāϰāĻāϝāĻŧāĻžāϰā§āĻĄ āĻāϰā§āĨ¤
āĻĒā§āύāϰāĻžāϝāĻŧ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖ āĻāĻŦāĻ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻ āϞāĻŋāĻā§āĻāĻŋāĻ
āĻāĻāĻ āĻĒā§āϝāĻžāĻāĻžāϰā§āύāĻāĻŋ reauthenticateWithCredential()
āĻāϰ āϏāĻžāĻĨā§ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§, āϝāĻž āĻāĻĒāύāĻŋ āϏāĻžāĻŽā§āĻĒā§āϰāϤāĻŋāĻ āϏāĻžāĻāύ-āĻāύ āĻĒā§āϰāϝāĻŧā§āĻāύ āĻāĻŽāύ āϏāĻāĻŦā§āĻĻāύāĻļā§āϞ āĻ
āĻĒāĻžāϰā§āĻļāύāĻā§āϞāĻŋāϰ āĻāύā§āϝ āĻāĻāĻāĻŋ āύāϤā§āύ āĻļāĻāϏāĻžāĻĒāϤā§āϰ āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰāϤ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ:
āϏā§āĻāĻĢāĻ
// Initialize a fresh Apple credential with Firebase.
let credential = OAuthProvider.credential(
withProviderID: "apple.com",
IDToken: appleIdToken,
rawNonce: rawNonce
)
// Reauthenticate current Apple user with fresh Apple credential.
Auth.auth().currentUser.reauthenticate(with: credential) { (authResult, error) in
guard error != nil else { return }
// Apple user successfully re-authenticated.
// ...
}
āĻāĻĻā§āĻĻā§āĻļā§āϝ-C
FIRAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"apple.com",
IDToken:appleIdToken,
rawNonce:rawNonce];
[[FIRAuth auth].currentUser
reauthenticateWithCredential:credential
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error) {
// Handle error.
}
// Apple user successfully re-authenticated.
// ...
}];
āĻāĻŦāĻ, āĻāĻĒāύāĻŋ āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§ āĻŦāĻŋāĻāĻŋāύā§āύ āĻĒāϰāĻŋāĻāϝāĻŧ āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰā§āĻā§ āϞāĻŋāĻā§āĻ āĻāϰāϤ⧠linkWithCredential()
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
āĻŽāύ⧠āϰāĻžāĻāĻŦā§āύ āϝ⧠āĻ ā§āϝāĻžāĻĒāϞ āĻāĻĒāύāĻžāĻā§ āϤāĻžāĻĻā§āϰ āĻ ā§āϝāĻžāĻĒāϞ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻāĻā§āϞāĻŋāĻā§ āĻ āύā§āϝ āĻĄā§āĻāĻžāϰ āϏāĻžāĻĨā§ āϞāĻŋāĻā§āĻ āĻāϰāĻžāϰ āĻāĻā§ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āĻāĻžāĻ āĻĨā§āĻā§ āϏā§āĻĒāώā§āĻ āϏāĻŽā§āĻŽāϤāĻŋ āύāĻŋāϤ⧠āĻšāĻŦā§āĨ¤
Apple āĻāϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ āĻāϰāϞ⧠āĻāĻĒāύāĻŋ āĻāĻāĻāĻŋ āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āϏāĻžāĻĨā§ āϞāĻŋāĻā§āĻ āĻāϰāĻžāϰ āĻāύā§āϝ āĻāĻāĻāĻŋ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖ āĻļāĻāϏāĻžāĻĒāϤā§āϰ āĻĒā§āύāϰāĻžāϝāĻŧ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āύ āύāĻžā§ˇ āĻāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻ
āύā§āϝ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§ Apple āĻļāĻāϏāĻžāĻĒāϤā§āϰā§āϰ āϏāĻžāĻĨā§ āĻāĻāĻāĻŋ āϏāĻžāĻāύ āĻāύ āϞāĻŋāĻā§āĻ āĻāϰāϤ⧠āĻāĻžāύ, āϤāĻžāĻšāϞ⧠āĻāĻĒāύāĻžāĻā§ āĻĒā§āϰāĻĨāĻŽā§ Apple āĻļāĻāϏāĻžāĻĒāϤā§āϰā§āϰ āϏāĻžāĻĨā§ āĻĒā§āϰāĻžāύ⧠āϏāĻžāĻāύ āĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻāĻā§āϞāĻŋ āϞāĻŋāĻā§āĻ āĻāϰāĻžāϰ āĻā§āώā§āĻāĻž āĻāϰāϤ⧠āĻšāĻŦā§ āĻāĻŦāĻ āϤāĻžāϰāĻĒāϰ⧠āĻāĻāĻāĻŋ āύāϤā§āύ āĻļāĻāϏāĻžāĻĒāϤā§āϰ āĻā§āĻāĻā§ āĻĒā§āϤ⧠āϤā§āϰā§āĻāĻŋāĻāĻŋ āĻĒāϰā§āĻā§āώāĻž āĻāϰāϤ⧠āĻšāĻŦā§ā§ˇ āύāϤā§āύ āĻļāĻāϏāĻžāĻĒāϤā§āϰāĻāĻŋ āϤā§āϰā§āĻāĻŋāϰ userInfo
āĻ
āĻāĻŋāϧāĻžāύ⧠āĻ
āĻŦāϏā§āĻĨāĻŋāϤ āĻšāĻŦā§ āĻāĻŦāĻ AuthErrorUserInfoUpdatedCredentialKey
āĻā§ āĻāϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§āĨ¤
āĻāĻĻāĻžāĻšāϰāĻŖāϏā§āĻŦāϰā§āĻĒ, āĻŦāϰā§āϤāĻŽāĻžāύ āĻĢāĻžāϝāĻŧāĻžāϰāĻŦā§āϏ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āϏāĻžāĻĨā§ āĻāĻāĻāĻŋ Facebook āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻ āϞāĻŋāĻā§āĻ āĻāϰāϤā§, āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻā§ Facebook-āĻ āϏāĻžāĻāύ āĻāύ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻĒāύāĻŋ āϝ⧠āĻ ā§āϝāĻžāĻā§āϏā§āϏ āĻā§āĻā§āύ āĻĒā§āϝāĻŧā§āĻā§āύ āϤāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ:
āϏā§āĻāĻĢāĻ
// Initialize a Facebook credential with Firebase.
let credential = FacebookAuthProvider.credential(
withAccessToken: AccessToken.current!.tokenString
)
// Assuming the current user is an Apple user linking a Facebook provider.
Auth.auth().currentUser.link(with: credential) { (authResult, error) in
// Facebook credential is linked to the current Apple user.
// The user can now sign in with Facebook or Apple to the same Firebase
// account.
// ...
}
āĻāĻĻā§āĻĻā§āĻļā§āϝ-C
// Initialize a Facebook credential with Firebase.
FacebookAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:accessToken];
// Assuming the current user is an Apple user linking a Facebook provider.
[FIRAuth.auth linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
// Facebook credential is linked to the current Apple user.
// The user can now sign in with Facebook or Apple to the same Firebase
// account.
// ...
}];
āĻā§āĻā§āύ āĻĒā§āϰāϤā§āϝāĻžāĻšāĻžāϰ
āĻ ā§āϝāĻžāĻĒāϞā§āϰ āĻĒā§āϰāϝāĻŧā§āĻāύ āϝ⧠āĻ ā§āϝāĻžāĻĒāĻā§āϞāĻŋ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻ āϤā§āϰāĻŋāĻā§ āϏāĻŽāϰā§āĻĨāύ āĻāϰ⧠āϏā§āĻā§āϞāĻŋāĻā§ āĻ āĻŦāĻļā§āϝāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āĻ ā§āϝāĻžāĻĒā§āϰ āĻŽāϧā§āϝ⧠āϤāĻžāĻĻā§āϰ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻ āĻŽā§āĻā§ āĻĢā§āϞāĻž āĻļā§āϰ⧠āĻāϰāϤ⧠āĻĻāĻŋāϤ⧠āĻšāĻŦā§, āϝā§āĻŽāύ āĻ ā§āϝāĻžāĻĒ āϏā§āĻā§āϰ āĻĒāϰā§āϝāĻžāϞā§āĻāύāĻž āύāĻŋāϰā§āĻĻā§āĻļāĻŋāĻāĻžāϤ⧠āĻŦāϰā§āĻŖāĻŋāϤ āĻšāϝāĻŧā§āĻā§
āĻāĻ āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧāϤāĻž āĻĒā§āϰāĻŖ āĻāϰāϤā§, āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤ āĻĒāĻĻāĻā§āώā§āĻĒāĻā§āϞāĻŋ āĻŦāĻžāϏā§āϤāĻŦāĻžāϝāĻŧāύ āĻāϰā§āύ:
āύāĻŋāĻļā§āĻāĻŋāϤ āĻāϰā§āύ āϝ⧠āĻāĻĒāύāĻŋ āĻ ā§āϝāĻžāĻĒāϞ āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰ⧠āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύā§āϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ-āĻāϰ āĻĒāϰāĻŋāώā§āĻŦāĻž āĻāĻāĻĄāĻŋ āĻāĻŦāĻ OAuth āĻā§āĻĄ āĻĢā§āϞ⧠āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύ āĻŦāĻŋāĻāĻžāĻāĻāĻŋ āĻĒā§āϰāĻŖ āĻāϰā§āĻā§āύ, āϝā§āĻŽāύāĻāĻŋ āĻ ā§āϝāĻžāĻĒāϞā§āϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰā§āύ āĻŦāĻŋāĻāĻžāĻā§ āĻŦāϰā§āĻŖāĻŋāϤ āĻšāϝāĻŧā§āĻā§āĨ¤
āϝā§āĻšā§āϤ⧠Firebase āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻā§āĻā§āύ āϏāĻāϰāĻā§āώāĻŖ āĻāϰ⧠āύāĻž āϝāĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰāĻž āĻ ā§āϝāĻžāĻĒāϞā§āϰ āϏāĻžāĻĨā§ āϏāĻžāĻāύ āĻāύ āĻāϰ⧠āϤā§āϰāĻŋ āĻāϰāĻž āĻšāϝāĻŧ, āϤāĻžāĻ āĻāĻĒāύāĻžāĻā§ āĻ āĻŦāĻļā§āϝāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻā§ āϤāĻžāĻĻā§āϰ āĻā§āĻā§āύ āĻĒā§āϰāϤā§āϝāĻžāĻšāĻžāϰ āĻāĻŦāĻ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻ āĻŽā§āĻā§ āĻĢā§āϞāĻžāϰ āĻāĻā§ āĻāĻŦāĻžāϰ āϏāĻžāĻāύ āĻāύ āĻāϰāϤ⧠āĻŦāϞāϤ⧠āĻšāĻŦā§āĨ¤
āϏā§āĻāĻĢāĻ
private func deleteCurrentUser() { do { let nonce = try CryptoUtils.randomNonceString() currentNonce = nonce let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() request.requestedScopes = [.fullName, .email] request.nonce = CryptoUtils.sha256(nonce) let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() } catch { // In the unlikely case that nonce generation fails, show error view. displayError(error) } }
ASAuthorizationAppleIDCredential
āĻĨā§āĻā§ āĻ āύā§āĻŽā§āĻĻāύ āĻā§āĻĄāĻāĻŋ āĻĒāĻžāύ āĻāĻŦāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻā§āĻā§āύ āĻĒā§āϰāϤā§āϝāĻžāĻšāĻžāϰ āĻāϰāϤā§Auth.auth().revokeToken(withAuthorizationCode:)
āĻāϞ āĻāϰāϤ⧠āĻāĻāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύāĨ¤āϏā§āĻāĻĢāĻ
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else { print("Unable to retrieve AppleIDCredential") return } guard let _ = currentNonce else { fatalError("Invalid state: A login callback was received, but no login request was sent.") } guard let appleAuthCode = appleIDCredential.authorizationCode else { print("Unable to fetch authorization code") return } guard let authCodeString = String(data: appleAuthCode, encoding: .utf8) else { print("Unable to serialize auth code string from data: \(appleAuthCode.debugDescription)") return } Task { do { try await Auth.auth().revokeToken(withAuthorizationCode: authCodeString) try await user?.delete() self.updateUI() } catch { self.displayError(error) } } }
āĻ āĻŦāĻļā§āώā§, āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻ (āĻāĻŦāĻ āϏāĻŽāϏā§āϤ āϏāĻŽā§āĻĒāϰā§āĻāĻŋāϤ āĻĄā§āĻāĻž) āĻŽā§āĻā§āύ
āĻĒāϰāĻŦāϰā§āϤ⧠āĻĒāĻĻāĻā§āώā§āĻĒ
āĻāĻāĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āĻĒā§āϰāĻĨāĻŽāĻŦāĻžāϰ āϏāĻžāĻāύ āĻāύ āĻāϰāĻžāϰ āĻĒāϰā§, āĻāĻāĻāĻŋ āύāϤā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻ āϤā§āϰāĻŋ āĻāϰāĻž āĻšāϝāĻŧ āĻāĻŦāĻ āĻļāĻāϏāĻžāĻĒāϤā§āϰāĻā§āϞāĻŋāϰ āϏāĻžāĻĨā§ āϞāĻŋāĻā§āĻ āĻāϰāĻž āĻšāϝāĻŧâāĻ āϰā§āĻĨāĻžā§, āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āύāĻžāĻŽ āĻāĻŦāĻ āĻĒāĻžāϏāĻāϝāĻŧāĻžāϰā§āĻĄ, āĻĢā§āύ āύāĻŽā§āĻŦāϰ, āĻŦāĻž āĻĒā§āϰāĻŽāĻžāĻŖ āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰā§āϰ āϤāĻĨā§āϝ â āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āϏāĻžāĻāύ āĻāύ āĻāϰā§āĻā§āύāĨ¤ āĻāĻ āύāϤā§āύ āĻ ā§āϝāĻžāĻāĻžāĻāύā§āĻāĻāĻŋ āĻāĻĒāύāĻžāϰ āĻĢāĻžāϝāĻŧāĻžāϰāĻŦā§āϏ āĻĒā§āϰāĻāϞā§āĻĒā§āϰ āĻ āĻāĻļ āĻšāĻŋāϏāĻžāĻŦā§ āϏāĻāϰāĻā§āώāĻŖ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§ āĻāĻŦāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āĻā§āĻāĻžāĻŦā§ āϏāĻžāĻāύ āĻāύ āĻāϰā§āύ āύāĻž āĻā§āύ, āĻāĻĒāύāĻžāϰ āĻĒā§āϰāĻāϞā§āĻĒā§āϰ āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻ ā§āϝāĻžāĻĒ āĻā§āĻĄāĻŧā§ āĻāĻāĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻā§ āĻļāύāĻžāĻā§āϤ āĻāϰāϤ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§āĨ¤
āĻāĻĒāύāĻžāϰ āĻ ā§āϝāĻžāĻĒā§, āĻāĻĒāύāĻŋ
User
āĻ āĻŦāĻā§āĻā§āĻ āĻĨā§āĻā§ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻŽā§āϞāĻŋāĻ āĻĒā§āϰā§āĻĢāĻžāĻāϞ āϤāĻĨā§āϝ āĻĒā§āϤ⧠āĻĒāĻžāϰā§āύāĨ¤ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āĻĒāϰāĻŋāĻāĻžāϞāύāĻž āĻĻā§āĻā§āύāĨ¤āĻāĻĒāύāĻžāϰ Firebase Realtime Database āĻāĻŦāĻ Cloud Storage āϏā§āϰāĻā§āώāĻž āύāĻŋāϝāĻŧāĻŽā§ , āĻāĻĒāύāĻŋ
auth
āĻā§āϰāĻŋāϝāĻŧā§āĻŦāϞ āĻĨā§āĻā§ āϏāĻžāĻāύ-āĻāύ āĻāϰāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻ āύāύā§āϝ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āĻāĻāĻĄāĻŋ āĻĒā§āϤ⧠āĻĒāĻžāϰā§āύ āĻāĻŦāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āĻā§āύ āĻĄā§āĻāĻž āĻ ā§āϝāĻžāĻā§āϏā§āϏ āĻāϰāϤ⧠āĻĒāĻžāϰ⧠āϤāĻž āύāĻŋāϝāĻŧāύā§āϤā§āϰāĻŖ āĻāϰāϤ⧠āĻāĻāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
āĻāĻāĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻā§ āϏāĻžāĻāύ āĻāĻāĻ āĻāϰāϤā§, signOut:
āϏā§āĻāĻĢāĻ
let firebaseAuth = Auth.auth() do { try firebaseAuth.signOut() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) }
āĻāĻĻā§āĻĻā§āĻļā§āϝ-C
NSError *signOutError; BOOL status = [[FIRAuth auth] signOut:&signOutError]; if (!status) { NSLog(@"Error signing out: %@", signOutError); return; }
āĻāĻĒāύāĻŋ āĻĒā§āϰāĻŽāĻžāĻŖā§āĻāϰāĻŖ āϤā§āϰā§āĻāĻŋāϰ āϏāĻŽā§āĻĒā§āϰā§āĻŖ āĻĒāϰāĻŋāϏāϰā§āϰ āĻāύā§āϝ āϤā§āϰā§āĻāĻŋ āĻšā§āϝāĻžāύā§āĻĄāϞāĻŋāĻ āĻā§āĻĄ āϝā§āĻ āĻāϰāϤ⧠āĻāĻžāĻāϤ⧠āĻĒāĻžāϰā§āύāĨ¤ āĻšā§āϝāĻžāύā§āĻĄā§āϞ āϤā§āϰā§āĻāĻŋ āĻĻā§āĻā§āύ.