SlideShare a Scribd company logo
與 Sign in with Apple 的愛恨情仇
Johnny Sung
#iplayground2020
Mobile devices Developer
https://fb.com/j796160836
https://blog.jks.coffee/
https://www.slideshare.net/j796160836
https://github.com/j796160836
Johnny Sung
⼤綱
• Sign in with Apple 的介紹
• iOS App 端流程
• 網站端流程
• 關於虛擬 E-mail
• 蘋果開發者網站設定
• iOS、網站、後端 實作概念
https://support.apple.com/zh-tw/HT210318
官⽅消息指出,
從 2019 年 9 ⽉ 12 ⽇開始,新上架的 APP 需設置 Sign in with Apple
只要您的 app 有⽀援第三⽅登入
在 2020 年 4 ⽉之後,
就「⼀定要」⽀援 Sign in with Apple
http://www.johnnytimes.com/wp-content/uploads/2016/06/copycat.jpg
否則,
否則?
https://image.cnbcfm.com/api/v1/image/105608434-1543945658496rts28qzc.jpg
https://www.appmachine.com/wp-content/uploads/2015/01/7-Reasons-Why-Apple-Could-Reject-Your-App-b-1.jpg
Sign in with Apple
• 使⽤ Apple ID 登入,強化保護您的隱私權
• 當⽤⼾不願給出⾃⼰的 E-mail 時,蘋果可以⽣成⼀組「虛擬 E-mail」給⽤⼾使⽤。
• 「虛擬 E-mail」收到的資訊,蘋果會代轉給⽤⼾的「真實 E-mail」
Apple Sign In 的原理
App 登入
App 登入
1. 使⽤者按下 Sign in with Apple 按鈕,
呼叫相關 AuthenticationServices framework 的相關函式
2. iOS 系統跳出 AppleId 登入確認,利⽤ TouchId 指紋辨識
或 FaceId 臉部辨識
(可選擇是否隱藏其 E-mail)
3. 當登入授權成功時,系統呼叫
didCompleteWithAuthorization
處理該 Callback 相關參數
4. ⽤ API 傳回⾃⼰伺服器做驗證
https://support.apple.com/library/content/dam/edam/applecare/images/zh_TW/appleid/ios14-iphone-11-pro-sign-in-with-apple.jpg
網站登入
1. 使⽤者按下 Sign in with Apple 按鈕,
呼叫蘋果提供的 JavaScript 帶⼊ Redirect URI(轉址位址)
2. 使⽤者在 Apple 網站進⾏登⼊,輸⼊ AppleId 的帳號密碼,
並授權開發商授權允許(可選擇是否隱藏其 E-mail )
3. 當登⼊授權成功時,轉址回設定之 Redirect URI 並附上參數
4. ⽤ API 傳回⾃⼰伺服器做驗證
網站登入
蘋果開發者網站設定
蘋果開發者網站設定
1. App ID (iOS app 使⽤)
2. Service ID (網站使⽤)
3. Sign Key (後端驗證使⽤)
4. Email 寄件⼈ & 網域 (Email relay service 使⽤)
所需材料 (1/2)
• Service ID
Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
• App ID (Bundle ID)
Certificates, Identifiers & Profiles -> Identifiers -> App IDs
範例值:
- Name: SignAppleDemo
- AppID: com.johnny.signapple
範例值:
- Name: SignAppleDemo
- AppID: com.johnny.websignapple
所需材料 (2/2)
• Sign Key
Certificates, Identifiers & Profiles -> Keys
範例值:
- Name: SignAppleKey
- KeyID: D2XXXXX7KY
- p8 file:
-----BEGIN PRIVATE KEY-----
EGCCqGSM49AwEHBHkwdwIBA
-----END PRIVATE KEY-----
設定 App ID (Bundle ID)
Certificates, Identifiers & Profiles -> Identifiers -> App IDs
設定 App ID (Bundle ID)
Certificates, Identifiers & Profiles -> Identifiers -> App IDs
設定 App ID (Bundle ID)
Certificates, Identifiers & Profiles -> Identifiers -> App IDs
設定 App ID (Bundle ID)
Certificates, Identifiers & Profiles -> Identifiers -> App IDs
設定 App ID (Bundle ID)
Certificates, Identifiers & Profiles -> Identifiers -> App IDs
設定 Service ID
Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
設定 Service ID
Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
設定 Service ID
Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
設定 Service ID
Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
設定 Service ID
Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
設定 Sign Key
Certificates, Identifiers & Profiles -> Keys
設定 Sign Key
Certificates, Identifiers & Profiles -> Keys
設定 Sign Key
Certificates, Identifiers & Profiles -> Keys
材料整理
• Client ID
• iOS App - App ID (Bundle ID)
• 網站 - Service ID
• Redirect URI
• iOS ⽤的 API endpoint
• 網站 API endpoint
• Team ID
• Sign Key & Key ID
Email Relay Service
• 蘋果⽣成⼀組,虛擬 E-mail 給⽤⼾使⽤
• 蘋果會驗證寄件⼈與寄件來源
(需設定寄件⼈&寄件網域)
• 寄件⼈可以設定 Gmail
• ⾃訂網域需設定 SPF (DNS Sender Policy Freamwork)
Email Relay Service
設定寄件⼈、寄件網域
Certificates, Identifiers & Profiles -> More -> Sign in with Apple for Email Communication
設定寄件⼈、寄件網域
Certificates, Identifiers & Profiles -> More -> Sign in with Apple for Email Communication
設定寄件⼈、寄件網域
設定 SPF (DNS Sender Policy Freamwork)
設定 SPF (DNS Sender Policy Freamwork)
"v=spf1 include:_spf.google.com include:sendgrid.net include:amazonses.com ~all"
新增 DNS TXT Record
郵件服務 Email Service Provider (ESP)
• Google Gmail
• SendGrid
• Amazon SES
iOS App 端實作
• 樣式:⿊⾊ vs. ⽩⾊有邊框 vs. ⽩⾊無邊框
• 字樣:Sign in with Apple vs. Continue with Apple vs. 無
• 圓⾓:有圓⾓ vs. 無圓⾓
登入按鈕樣式
https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/
iOS App 部分
1. 使⽤者按下 Sign in with Apple 按鈕,
呼叫相關 AuthenticationServices framework 的相關函式
2. iOS 系統跳出 AppleId 登入確認,利⽤ TouchId 指紋辨識
或 FaceId 臉部辨識
(可選擇是否隱藏其 E-mail)
3. 當登入授權成功時,系統呼叫
didCompleteWithAuthorization
處理該 Callback 將相關參數,⽤ API 傳回⾃⼰的網站
import Foundation
import AuthenticationServices
class AppleSignInManager: NSObject {
var currentView: UIView?
func signIn(currentView: UIView) {
guard #available(iOS 13.0, *) else { return }
self.currentView = currentView
let provider = ASAuthorizationAppleIDProvider()
let request = provider.createRequest()
request.requestedScopes = [.email, .fullName]
request.nonce = "[NONCE]"
request.state = "[STATE]"
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()
}
}
iOS 實作片段 (1/3)
辨識⽤的值,避免 CSRF 攻擊
extension AppleSignInManager: ASAuthorizationControllerDelegate {
@available(iOS 13.0, *)
func authorizationController(controller: ASAuthorizationController,
didCompleteWithError error: Error) {
// Handle error
print(error)
}
@available(iOS 13.0, *)
func authorizationController(controller: ASAuthorizationController,
didCompleteWithAuthorization authorization: ASAuthorization) {
guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return }
// Post identityToken & authorizationCode to your server
print(String(decoding: credential.identityToken ?? Data.init(), as: UTF8.self))
print(String(decoding: credential.authorizationCode ?? Data.init(), as: UTF8.self))
}
}
iOS 實作片段 (2/3)
要處理請求失敗
請求成功,⽤ API
回傳 id_token 與 auth_code 回您的 Server
extension AppleSignInManager: ASAuthorizationControllerPresentationContextProviding {
@available(iOS 13.0, *)
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.currentView?.window ?? UIApplication.shared.keyWindow!
}
}
iOS 實作片段 (3/3)
要放入⽬前所在 ViewController 的 window
網站實作
• 樣式:⿊⾊ vs. ⽩⾊有邊框 vs. ⽩⾊無邊框
• 字樣:Sign in with Apple vs. Continue with Apple vs. 無
• 圓⾓:有圓⾓ vs. 無圓⾓
登入按鈕樣式
https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/
<html>
<head>
</head>
<body>
<script type="text/javascript"
src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div>
<script type="text/javascript">
AppleID.auth.init({
clientId: '[CLIENT_ID]',
scope: 'name email',
redirectURI: '[REDIRECT_URI]',
state: '[STATE]',
nonce: '[NONCE]',
usePopup: false
});
</script>
</body>
</html>
網站實作片段 (1/2)
辨識⽤的值,避免 CSRF 攻擊
設定轉跳的網址
使⽤彈窗模式?
填入 Service ID
async function doAppleSignIn() {
try {
const data = await AppleID.auth.signIn();
console.log(data);
} catch (error) {
//handle error.
}
}
網站實作片段 (2/2)
對稱式加密 & 非對稱式加密
基礎密碼學
對稱式加密 (Symmetric Encryption)
https://medium.com/@RiverChan/%E5%9F%BA%E7%A4%8E%E5%AF%86%E7%A2%BC%E5%AD%B8-%E5%B0%8D%E7%A8%B1%E5%BC%8F%E8%88%87%E9%9D%9E%E5%B0%8D%E7%A8%B1%E5%BC%8F%E5%8A%A0%E5%AF%86%E6%8A%80%E8%A1%93-de25fd5fa537
https://medium.com/@RiverChan/%E5%9F%BA%E7%A4%8E%E5%AF%86%E7%A2%BC%E5%AD%B8-%E5%B0%8D%E7%A8%B1%E5%BC%8F%E8%88%87%E9%9D%9E%E5%B0%8D%E7%A8%B1%E5%BC%8F%E5%8A%A0%E5%AF%86%E6%8A%80%E8%A1%93-de25fd5fa537
非對稱式加密 (Asymmetric Encryption)
Json Web Token
• RFC 7519 - JSON Web Token(JWT)
定義了 header 內容與 claim 內容,以及 token 的相關規範
• RFC 7515 - JSON Web Signature(JWS)
定義如何做帶有簽章的 token
• RFC 7516 - JSON Web Encryption(JWE)
定義內容加密的 token
• RFC 7517 - JSON Web Key(JWK)
定義⾦鑰的格式
• RFC 7518 - JSON Web Algorithms(JWA)
定義加解密的演算法
https://ithelp.ithome.com.tw/articles/10224787
JWT? JWS? JWK? JWA?
- JWS 與 JWE 都是屬於 JWT 的⼀種。
- 如果沒特別說明,則 JWT 皆是指 JWS。
https://hlqft4a0qsn1cy1gi1bevyhj-wpengine.netdna-ssl.com/wp-content/uploads/2019/05/key-types-600x453.jpg
🖖
https://twitter.com/irina_papuc/status/900085165568937984/photo/1
base64UrlEncode({
"alg": "RS256",

"typ": "JWT"
})
base64UrlEncode{{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
})
HMACSHA256(

base64UrlEncode(header)
+ "." +

base64UrlEncode(payload)

, secretKey)
. .
Header
Algorithm & token type
Payload
Data
Signature
Verification
Json Web Token
https://19yw4b240vb03ws8qm25h366-wpengine.netdna-ssl.com/wp-content/uploads/Why-Cant-I-Just-Send-JWTs-Without-OAuth-JWT.png
https://jwt.io/
{
"iss": "https://appleid.apple.com",
"aud": "com.johnny.signapple",
"exp": 1596621649,
"iat": 1596621049,
"sub": "001451.3dc43615849bcf03b2cce4e48048a59f.0447",
"c_hash": "iUqI9RgFbplkcW9Org-CyoA",
"email": "8n4prkdcmew@privaterelay.appleid.com",
"email_verified": "true",
"is_private_email": "true",
"auth_time": 1596621049,
"nonce_supported": true
}
{
"kid": "86D88Kf",
"alg": "RS256"
}
eyJraWQiOiI4NkQ4OEtmIiwiYWxnIjoiUlMyNTYifQ
Header
Algorithm & token type
eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkI
joiY29tLjkxcHUhQ5LCJpYXQiOjE1OTY2MjEwNDksInN1YiI6IjAw
MTQ1MS4zZGM0MzYxNTVmYjA0NjAzYjJjY2U0ZTQ4MDQ4YTU5Zi4wN
Q3lvQSIsImVtYWlsIjoiOkuYXBwbGVpZC5jb20iLCJlbWFpbF92ZX
JpZmllZCI6InRydWUiLCJpc19wcml2YXRlX2VtYWlsIjoidHJ1ZSI
sImF1dGhfdGltZSI6MTU5NjYyMTA0OSwibm9uY2Vfc3VwcG9ydGVk
Ijp0cnVlfQ
Payload
Data
Signature
Verification
KccMlP7OoIctkaEzy09pJK0t-uzwkT-u3UT7BNWJ1mS2mU_FXH-
pKTjnyO7Whd9vh-pBQdVU5vZ7kKeD3rMqGi-
kKkLmNO1yjBse2cnfs7WLthtrhrthnbi1iDxHvedFjBOUhOzfcFfwn4-
CLSUZcb7aukHd0hj0NYzigBWzFAbxDmYtM7hlqQmJaYBh6RzYfwMOxK58
HRcVnx9wy3vzTFfj25x6nqMGxosVXkD0N0PP1b30uem8tyS4wSu3w5zoE
2Bpaos_fhattM_p28WdcrA4Ne89ET8D5GYSe448VlIyXSonfHBveE5-
hSVQAzIjP4B_JOCcRBpM3Q
JWT
• Header
• alg - 加解密演算法 JWA (JSON Web Algorithms)
• "HS256" (HMAC-SHA256)
• "RS256" (RSA-SHA256)
• "ES256" (ECDSA-SHA256)
• typ - JWT 本⾝的媒體類型
⽤預設值 "JWT"
• kid - Sign Key ID
{
"kid": "86D88Kf",
"typ": "JWT"
"alg": "RS256"
}
Header
Algorithm & token type
JWT
• Payload
• iss - 發⾏者 ( Issuer )
• aud - 接收者 ( Audience )
• iat - 發⾏時間 ( Issued at (time) )
⽤ Unix timestamp 表⽰
• exp - 過期時間 ( Expiration (time) )
⽤ Unix timestamp 表⽰
• sub - 主題 ( Subject )
⽤ URI 表⽰唯⼀識別訊息
• Signature
• 非對稱演算法加密(Header + "." + Payload)
{
"iss": "https://appleid.apple.com",
"aud": "com.johnny.signapple",
"iat": 1596621049,
"exp": 1596621649,
"sub": "001451.3dc436158........9f.0447",
"c_hash": "iUqI9RgFbplkcW9Org-CyoA",
"email": "8nmew@privaterelay.appleid.com",
"email_verified": "true",
"is_private_email": "true",
"auth_time": 1596621049,
"nonce_supported": true
}
Payload
Data
驗證⽅式 1: 驗證 IdentityToken
步驟
1. 接收從 client 傳來的 IdentityToken (JWT)
( 蘋果 會⽤它的私鑰加密 IdentityToken 的簽章部分 )
2. 呼叫 /auth/keys 取得 蘋果 公鑰 (JWK)
3. 整理 JWK 成 pem 格式
4. ⽤ 蘋果 公鑰 來驗證 client 傳來的 IdentityToken
5. 從 IdentityToken 的 payload 取得資料
{
"keys": [
{
"kid": "86D88Kf",
"kty": "RSA",
"use": "sig",
"alg": "RS256",
"n": "iGaLqP6y-SJCCBq5H.....Yw-zHLwQ",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "eXaunmL",
"use": "sig",
"alg": "RS256",
"n": "4dGQ7bQK8LgI...........JNdUhxw",
"e": "AQAB"
}
]
}
取得蘋果公鑰
• API Endpoint
GET https://appleid.apple.com/auth/keys
• 內容為標準 JWK (JSON Web Key) 格式
• kid - ⾦鑰 ID
• kty - Key Type ⾦鑰類型
• alg - 演算法
值 "RS256" 為 RSA-SHA256 演算法
• use - ⽤途描述
值 "sig" 意思是 數位簽章
• n - RSA 模數 (Modulus)
為公鑰內容的⼀部分,內容為 base64urlUInt 編碼後的結果
• e - RSA 指數 (Exponent)
為公鑰內容的⼀部分,內容為 base64urlUInt 編碼後的結果
回傳結果
蘋果  API ⽂件:
https://developer.apple.com/documentation/sign_in_with_apple/fetch_apple_s_public_key_for_verifying_token_signature
require_once '../vendor/autoload.php';
function getUserDataFromIdentityToken($idToken)
{
$token = (new LcobucciJWTParser())->parse((string)$idToken);
$applePublicKeysRaw = curlGetAppleAuthKeys();
$applePublicKeys = JWKParseKeySet($applePublicKeysRaw);
$applePublicKey = $applePublicKeys[$token->getHeader('kid')];
$signer = new LcobucciJWTSignerRsaSha256();
$keychain = new LcobucciJWTSignerKeychain();
if (!$token->verify($signer, $keychain->getPublicKey($applePublicKey))) {
throw new RuntimeException("Key validation failed.");
}
if ('https://appleid.apple.com' !== $token->getClaim('iss')) {
throw new RuntimeException("Source incorrect.");
}
$userData = array();
$userData['email'] = $token->getClaim('email');
$userData['id'] = $token->getClaim('sub');
return $userData;
}
驗證 JWT 的 Signature
找到指定的公鑰
擷取 JWT 的 Payload 內容
抓取蘋果的公鑰
function curlGetAppleAuthKeys()
{
$ch = curl_init('https://appleid.apple.com/auth/keys');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result, true);
}
function JWKParseKeySet($keySets)
{
$parsed = FirebaseJWTJWK::parseKeySet($keySets);
$pemKeySets = array();
foreach ($parsed as $keyId => $sslKey) {
$pemKeySets[$keyId] = openssl_pkey_get_details($sslKey)['key'];
}
return $pemKeySets;
}
function JWKVerify($idToken, $publicKeyPem)
{
$signer = new LcobucciJWTSignerRsaSha256();
$keychain = new LcobucciJWTSignerKeychain();
$token = (new LcobucciJWTParser())->parse((string)$idToken);
return $token->verify($signer, $keychain->getPublicKey($publicKeyPem));
}
composer.json
{
"require": {
"firebase/php-jwt": "5.2.0",
"lcobucci/jwt": "3.3.2"
}
}
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiGaLqP6y+
SJCCBq5Hv6p GDbG/
SQ11MNjH7rWHcCFYz4hGwHC4lcSurTlV8u3avoVNM8jXevG1Iu1SY
11qInq UvjJur+
+hghr1b56OPJu6H1iKulSxGjEIyDP6c5BdE1uwprYyr4IO9th8fOw
CPyg
jLFrh44XEGbDIFeImwvBAGOhmMB2AD1n1KviyNsH0bEB7phQtiLk+
ILjv1bORSRl 8AK677+1T8isGfHKXGZ/
ZGtStDe7Lu0Ihp8zoUt59kx2o9uWpROkzF56ypresiIl
4WprClRCjz8x6cPZXU2qNWhu71TQvUFwvIvbkE1oYaJMb0jcOTmBR
ZA2QuYw+zHL wQIDAQAB
-----END PUBLIC KEY-----
{
"kty": "RSA",
"kid": "86D88Kf",
"use": "sig",
"alg": "RS256",
"n": "iGaLqP6y-
SJCCBq5Hv6pGDbG_SQ11MNjH7rWHcCFYz4hGwHC4lcSurTlV8u3av
oVNM8jXevG1Iu1SY11qInqUvjJur--
hghr1b56OPJu6H1iKulSxGjEIyDP6c5BdE1uwprYyr4IO9th8fOwC
PygjLFrh44XEGbDIFeImwvBAGOhmMB2AD1n1KviyNsH0bEB7phQti
Lk-
ILjv1bORSRl8AK677-1T8isGfHKXGZ_ZGtStDe7Lu0Ihp8zoUt59k
x2o9uWpROkzF56ypresiIl4WprClRCjz8x6cPZXU2qNWhu71TQvUF
wvIvbkE1oYaJMb0jcOTmBRZA2QuYw-zHLwQ",
"e": "AQAB"
}
JWKParseKey
驗證⽅式 2: 使⽤ AuthorizationCode
步驟
1. 接收從 client 傳來的 AuthorizationCode
2. ⽤ 您的私鑰 製作 client_secret 也是⼀個 JWT Token
3. 呼叫 /auth/token 的 API,得到 IdentityToken
( 蘋果 會⽤ 您的公鑰 解密驗證 client_secret 的簽章部分 )
( 蘋果 會⽤它的私鑰加密 IdentityToken 的簽章部分 )
4. ⽤ 蘋果 公鑰 來驗證 client 傳來的 IdentityToken(步驟同上述做法)
5. 解開 IdentityToken 的 JWT 取得資料
蘋果  API ⽂件:
https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
• API Endpoint
POST https://appleid.apple.com/auth/token
• 傳送參數
• client_id - 填入 Service ID (網站) 或 App ID (iOS App)
• client_secret - ⼀個 JWT 格式的要求⽂件(詳)
• code - Authorization code
• grant_type - 授權⽅式
填 `authorization_code` 來交換 AccessToken
交換 AuthorizationCode
{
"access_token": "a6cab...........Y1A",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "r9d77fa9..........gfYA",
"id_token": "eyJraW.................jMA"
}
• API Endpoint
POST https://appleid.apple.com/auth/token
• 回傳結果
• access_token - token,⽬前沒作⽤ 😂
• expires_in - 過期時間
• id_token - IdentityToken
• refresh_token - 更新 access_token 時使⽤
交換 AuthorizationCode
回傳結果
蘋果  API ⽂件:
https://developer.apple.com/documentation/sign_in_with_apple/tokenresponse
🤔
• invalid_request
• 通常是連參數都弄錯
• invalid_client
• 可能是 client_id 弄錯
• 可能是 client_secret (JWT 格式) 裡的
sub 參數跟 client_id 參數不吻合
Troubleshooting
• invalid_grant
• 可能是 client_secret (JWT 格式) 加解密算錯 ⚠
• 可能是 Authorization Code 過期 ⚠
(Authorization Code 效期超短,通常只有 1-2 分鐘,不超過 5 分鐘)
• 可能是 Authorization Code 已被使⽤,變成無效的 code ⚠
(API 帶相同參數重複打就會出現)
• 其他錯誤訊息,請參考蘋果  API ⽂件:
https://developer.apple.com/documentation/sign_in_with_apple/errorresponse
Troubleshooting
Server to Server Notification
設定 App ID (Bundle ID)
Certificates, Identifiers & Profiles -> Identifiers -> App IDs
{
"payload":
"eyJraWQxxxxxxxxxxxxxxiUlMyNTYifQ.eyJpcxxxxxxxxx
xxxxc0fSJ9.IUFWxPxxxxxxxxxxxxxxxxxbL3olA"
}
Server notification
我也是⼀個 JWT 哦 ❤
範例值:
- API Endpoint: https://your.awesome.domain/handle_signin_notification.php
接收範例值
註:截稿至現在,
Apple 還沒有⽂件,只有在 WWDC 2020 影⽚上提到
- Introducing Sign In with Apple - WWDC2019
https://developer.apple.com/videos/play/wwdc2019/706/
- Get the most out of Sign in with Apple - WWDC2020
https://developer.apple.com/videos/play/wwdc2020/10173
- JWT 簽名算法 HS256、RS256 及 ES256 及密鑰⽣成
https://www.cnblogs.com/kirito-c/p/12402066.html
- 驗證 JSON Web Token
https://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html
- Sign in with Apple
http://uirate.net/?p=10363
- Ensure mail delivery & prevent spoofing (SPF)
https://support.google.com/a/answer/33786
- DNS 設定 spf 記錄 - Sender Policy Framework
https://blog.xuite.net/tolarku/blog/233356505
- Generate and Validate Tokens
https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
- 簡介 JWK 與 JWA
https://ithelp.ithome.com.tw/articles/10225590
- Sign in with Apple Tutorial, Part 4: Web and Other Platforms
https://sarunw.com/posts/sign-in-with-apple-4/
- JWT 概觀
https://ithelp.ithome.com.tw/articles/10224787
- [Note] OAuth2.0 學習筆記 | PJCHENder 未整理筆記
https://pjchender.github.io/2017/11/16/note-oauth2-0-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98/
參考資料 (1/3)
- 簡單易懂的 OAuth 2.0
https://speakerdeck.com/chitsaou/jian-dan-yi-dong-de-oauth-2-dot-0
- 關於OAuth 2.0-以Facebook為例
https://medium.com/@justinlee_78563/%E9%97%9C%E6%96%BCoauth-2-0-%E4%BB%A5facebook%E7%82%BA%E4%BE%8B-6f78a4a55f52
- [PHP] OAuth / Sign in with Apple JS - 使⽤ Apple JS SDK 讓網站⽀援 Apple ID 登入
http://blog.changyy.org/2019/11/php-jwt-oauth-sign-in-with-apple-js.html
- What the Heck is Sign In with Apple?
https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple
- 如何整合 Sign in with Apple 到⾃⼰的 iOS App 上 (iOS & Backend)
https://medium.com/@tuzaiz/%E5%A6%82%E4%BD%95%E6%95%B4%E5%90%88-sign-in-with-apple-
%E5%88%B0%E8%87%AA%E5%B7%B1%E7%9A%84-ios-app-%E4%B8%8A-ios-backend-e64d9de15410
- Sign in with Apple(蘋果授權登陸)
https://blog.csdn.net/wpf199402076118/article/details/99677412
- Sign in with Apple 登錄詳解
https://ihtcboy.com/2019/09/16/2019-09-16_Sign-in-with-Apple/
- iOS13 Sign In With Apple 適配
http://jerryliu.org/ios%20programming/iOS13-Sign-With-Apple%E6%96%B0%E7%89%B9%E6%80%A7%E9%80%82%E9%85%8D
- 蘋果Sign In with Apple爆可被劫持帳號的漏洞
https://www.ithome.com.tw/news/137972
- 蘋果重磅推出「Sign in with Apple」登入,背後忽略的隱私盲點
https://www.bnext.com.tw/article/53765/what-is-the-meaning-of-sign-in-with-apple
參考資料 (2/3)
- [筆記] 透過 JWT 實作驗證機制
https://medium.com/
%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98-
%E9%80%8F%E9%81%8E-jwt-%E5%AF%A6%E4%BD%9C%E9%A9%97%E8%AD%89%E6%A9%9F%E5%88%B6-2e64d72594f8
- 是誰在敲打我窗?什麼是 JWT ?
https://5xruby.tw/posts/what-is-jwt/
- 基礎密碼學-對稱式與非對稱式加密技術
https://medium.com/@RiverChan/%E5%9F%BA%E7%A4%8E%E5%AF%86%E7%A2%BC%E5%AD%B8-
%E5%B0%8D%E7%A8%B1%E5%BC%8F%E8%88%87%E9%9D%9E%E5%B0%8D%E7%A8%B1%E5%BC%8F%E5%8A%A0%E5%AF%86%E6%8A%80%E8%A1
%93-de25fd5fa537
參考資料 (3/3)
https://www.newaydirections.com/wp-content/uploads/2019/08/Blog-picture.jpg

More Related Content

What's hot

モデリングもしないでアジャイルとは何事だ
モデリングもしないでアジャイルとは何事だモデリングもしないでアジャイルとは何事だ
モデリングもしないでアジャイルとは何事だ
Iwao Harada
 
Expressjs
ExpressjsExpressjs
Express JS
Express JSExpress JS
Express JS
Alok Guha
 
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Johnny Sung
 
Object Oriented Javascript
Object Oriented JavascriptObject Oriented Javascript
Object Oriented Javascript
NexThoughts Technologies
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
Nikolaus Graf
 
React native
React nativeReact native
React native
Vikrant Negi
 
Nestjs MasterClass Slides
Nestjs MasterClass SlidesNestjs MasterClass Slides
Nestjs MasterClass Slides
Nir Kaufman
 
생산성을 높여주는 iOS 개발 방법들.pdf
생산성을 높여주는 iOS 개발 방법들.pdf생산성을 높여주는 iOS 개발 방법들.pdf
생산성을 높여주는 iOS 개발 방법들.pdf
ssuserb942d2
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJS
Rafael Casuso Romate
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
Joshua Long
 
[Flutter] 來體驗 bloc 小方塊的神奇魔法 @Devfest 2022
[Flutter] 來體驗 bloc 小方塊的神奇魔法 @Devfest 2022[Flutter] 來體驗 bloc 小方塊的神奇魔法 @Devfest 2022
[Flutter] 來體驗 bloc 小方塊的神奇魔法 @Devfest 2022
Johnny Sung
 
Clean backends with NestJs
Clean backends with NestJsClean backends with NestJs
Clean backends with NestJs
Aymene Bennour
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
Ignacio Martín
 
[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규ChangKyu Song
 
Kotlinアンチパターン
KotlinアンチパターンKotlinアンチパターン
Kotlinアンチパターン
Recruit Lifestyle Co., Ltd.
 
Flutter & Firebase BootCamp.pdf
Flutter & Firebase BootCamp.pdfFlutter & Firebase BootCamp.pdf
Flutter & Firebase BootCamp.pdf
ShivamShrey1
 
Declarative UIs with Jetpack Compose
Declarative UIs with Jetpack ComposeDeclarative UIs with Jetpack Compose
Declarative UIs with Jetpack Compose
Ramon Ribeiro Rabello
 
20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native
Eric Deng
 
Android jetpack compose | Declarative UI
Android jetpack compose | Declarative UI Android jetpack compose | Declarative UI
Android jetpack compose | Declarative UI
Ajinkya Saswade
 

What's hot (20)

モデリングもしないでアジャイルとは何事だ
モデリングもしないでアジャイルとは何事だモデリングもしないでアジャイルとは何事だ
モデリングもしないでアジャイルとは何事だ
 
Expressjs
ExpressjsExpressjs
Expressjs
 
Express JS
Express JSExpress JS
Express JS
 
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
Flutter 是什麼?用 Flutter 會省到時間嗎? @ GDG Devfest2020
 
Object Oriented Javascript
Object Oriented JavascriptObject Oriented Javascript
Object Oriented Javascript
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
 
React native
React nativeReact native
React native
 
Nestjs MasterClass Slides
Nestjs MasterClass SlidesNestjs MasterClass Slides
Nestjs MasterClass Slides
 
생산성을 높여주는 iOS 개발 방법들.pdf
생산성을 높여주는 iOS 개발 방법들.pdf생산성을 높여주는 iOS 개발 방법들.pdf
생산성을 높여주는 iOS 개발 방법들.pdf
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJS
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 
[Flutter] 來體驗 bloc 小方塊的神奇魔法 @Devfest 2022
[Flutter] 來體驗 bloc 小方塊的神奇魔法 @Devfest 2022[Flutter] 來體驗 bloc 小方塊的神奇魔法 @Devfest 2022
[Flutter] 來體驗 bloc 小方塊的神奇魔法 @Devfest 2022
 
Clean backends with NestJs
Clean backends with NestJsClean backends with NestJs
Clean backends with NestJs
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규
 
Kotlinアンチパターン
KotlinアンチパターンKotlinアンチパターン
Kotlinアンチパターン
 
Flutter & Firebase BootCamp.pdf
Flutter & Firebase BootCamp.pdfFlutter & Firebase BootCamp.pdf
Flutter & Firebase BootCamp.pdf
 
Declarative UIs with Jetpack Compose
Declarative UIs with Jetpack ComposeDeclarative UIs with Jetpack Compose
Declarative UIs with Jetpack Compose
 
20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native
 
Android jetpack compose | Declarative UI
Android jetpack compose | Declarative UI Android jetpack compose | Declarative UI
Android jetpack compose | Declarative UI
 

Similar to 與 Sign in with Apple 的愛恨情仇 @ iPlayground2020

Jason 專案經驗 (20170725)
Jason 專案經驗 (20170725)Jason 專案經驗 (20170725)
Jason 專案經驗 (20170725)
悅慶
 
zend framework in web services
zend framework in web serviceszend framework in web services
zend framework in web services王 承石
 
Google cloud message by sean
Google cloud message by seanGoogle cloud message by sean
Google cloud message by seanSean Lee
 
HTML+COIMOTION 開發跨平台 app
HTML+COIMOTION 開發跨平台 appHTML+COIMOTION 開發跨平台 app
HTML+COIMOTION 開發跨平台 app
Ben Lue
 
Anroid development part.1
Anroid development part.1Anroid development part.1
Anroid development part.1
RANK LIU
 
以HTML5和COIMOTION打造跨平台App
以HTML5和COIMOTION打造跨平台App以HTML5和COIMOTION打造跨平台App
以HTML5和COIMOTION打造跨平台App
Ben Lue
 
鼎鈞數位行銷App營運實務全攻略
鼎鈞數位行銷App營運實務全攻略鼎鈞數位行銷App營運實務全攻略
鼎鈞數位行銷App營運實務全攻略
淳甫 鄭
 
Cas Sso Intro
Cas Sso IntroCas Sso Intro
Cas Sso Intro
Shiny Zhu
 
mobiusDesign 梅比斯數位行銷工作室 作品集
mobiusDesign  梅比斯數位行銷工作室  作品集mobiusDesign  梅比斯數位行銷工作室  作品集
mobiusDesign 梅比斯數位行銷工作室 作品集
Leader Chen
 
Using google appengine_1027
Using google appengine_1027Using google appengine_1027
Using google appengine_1027Wei Sun
 
好的Windows Phone App 主要特色 (注意事項)
好的Windows Phone App 主要特色 (注意事項)好的Windows Phone App 主要特色 (注意事項)
好的Windows Phone App 主要特色 (注意事項)Herman Wu
 
S(P)Aas081008
S(P)Aas081008S(P)Aas081008
S(P)Aas081008yiming he
 
单点登录解决方案的架构与实现
单点登录解决方案的架构与实现单点登录解决方案的架构与实现
单点登录解决方案的架构与实现jeffz
 
行動商務實務 - PhoneGap Advance
行動商務實務 - PhoneGap Advance行動商務實務 - PhoneGap Advance
行動商務實務 - PhoneGap AdvanceMy own sweet home!
 
《氪周刊:互联网创业必读》(第58期).pdf
《氪周刊:互联网创业必读》(第58期).pdf《氪周刊:互联网创业必读》(第58期).pdf
《氪周刊:互联网创业必读》(第58期).pdfChada Chiu
 
About web app development. Intro to basic web app development .pdf
About web app development. Intro to basic web app development .pdfAbout web app development. Intro to basic web app development .pdf
About web app development. Intro to basic web app development .pdf
eddy0919
 
Using google appengine (2)
Using google appengine (2)Using google appengine (2)
Using google appengine (2)Wei Sun
 
Developer也可以做出漂亮網站 - Twitter Bootstrap/JQuery Mobile簡介
Developer也可以做出漂亮網站 - Twitter Bootstrap/JQuery Mobile簡介Developer也可以做出漂亮網站 - Twitter Bootstrap/JQuery Mobile簡介
Developer也可以做出漂亮網站 - Twitter Bootstrap/JQuery Mobile簡介Fred Lin
 
在雲端上啜飲爪哇
在雲端上啜飲爪哇在雲端上啜飲爪哇
在雲端上啜飲爪哇
建興 王
 

Similar to 與 Sign in with Apple 的愛恨情仇 @ iPlayground2020 (20)

Jason 專案經驗 (20170725)
Jason 專案經驗 (20170725)Jason 專案經驗 (20170725)
Jason 專案經驗 (20170725)
 
zend framework in web services
zend framework in web serviceszend framework in web services
zend framework in web services
 
Google cloud message by sean
Google cloud message by seanGoogle cloud message by sean
Google cloud message by sean
 
HTML+COIMOTION 開發跨平台 app
HTML+COIMOTION 開發跨平台 appHTML+COIMOTION 開發跨平台 app
HTML+COIMOTION 開發跨平台 app
 
Anroid development part.1
Anroid development part.1Anroid development part.1
Anroid development part.1
 
以HTML5和COIMOTION打造跨平台App
以HTML5和COIMOTION打造跨平台App以HTML5和COIMOTION打造跨平台App
以HTML5和COIMOTION打造跨平台App
 
鼎鈞數位行銷App營運實務全攻略
鼎鈞數位行銷App營運實務全攻略鼎鈞數位行銷App營運實務全攻略
鼎鈞數位行銷App營運實務全攻略
 
Cas Sso Intro
Cas Sso IntroCas Sso Intro
Cas Sso Intro
 
mobiusDesign 梅比斯數位行銷工作室 作品集
mobiusDesign  梅比斯數位行銷工作室  作品集mobiusDesign  梅比斯數位行銷工作室  作品集
mobiusDesign 梅比斯數位行銷工作室 作品集
 
Using google appengine_1027
Using google appengine_1027Using google appengine_1027
Using google appengine_1027
 
好的Windows Phone App 主要特色 (注意事項)
好的Windows Phone App 主要特色 (注意事項)好的Windows Phone App 主要特色 (注意事項)
好的Windows Phone App 主要特色 (注意事項)
 
S(P)Aas081008
S(P)Aas081008S(P)Aas081008
S(P)Aas081008
 
单点登录解决方案的架构与实现
单点登录解决方案的架构与实现单点登录解决方案的架构与实现
单点登录解决方案的架构与实现
 
行動商務實務 - PhoneGap Advance
行動商務實務 - PhoneGap Advance行動商務實務 - PhoneGap Advance
行動商務實務 - PhoneGap Advance
 
《氪周刊:互联网创业必读》(第58期).pdf
《氪周刊:互联网创业必读》(第58期).pdf《氪周刊:互联网创业必读》(第58期).pdf
《氪周刊:互联网创业必读》(第58期).pdf
 
About web app development. Intro to basic web app development .pdf
About web app development. Intro to basic web app development .pdfAbout web app development. Intro to basic web app development .pdf
About web app development. Intro to basic web app development .pdf
 
Using google appengine (2)
Using google appengine (2)Using google appengine (2)
Using google appengine (2)
 
所有Windows store 市集相關faq
所有Windows store 市集相關faq所有Windows store 市集相關faq
所有Windows store 市集相關faq
 
Developer也可以做出漂亮網站 - Twitter Bootstrap/JQuery Mobile簡介
Developer也可以做出漂亮網站 - Twitter Bootstrap/JQuery Mobile簡介Developer也可以做出漂亮網站 - Twitter Bootstrap/JQuery Mobile簡介
Developer也可以做出漂亮網站 - Twitter Bootstrap/JQuery Mobile簡介
 
在雲端上啜飲爪哇
在雲端上啜飲爪哇在雲端上啜飲爪哇
在雲端上啜飲爪哇
 

More from Johnny Sung

[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @Devfest Taipei 2023
[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @Devfest Taipei 2023[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @Devfest Taipei 2023
[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @Devfest Taipei 2023
Johnny Sung
 
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具 @ Devfest Kaohsiung 2023
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具 @ Devfest Kaohsiung 2023[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具 @ Devfest Kaohsiung 2023
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具 @ Devfest Kaohsiung 2023
Johnny Sung
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang) [Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
Johnny Sung
 
談談 Android constraint layout
談談 Android constraint layout談談 Android constraint layout
談談 Android constraint layout
Johnny Sung
 
炎炎夏日學 Android 課程 - Part3: Android app 實作
炎炎夏日學 Android 課程 - Part3: Android app 實作炎炎夏日學 Android 課程 - Part3: Android app 實作
炎炎夏日學 Android 課程 - Part3: Android app 實作
Johnny Sung
 
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
Johnny Sung
 
炎炎夏日學 Android 課程 - Part2: Android 元件介紹
炎炎夏日學 Android 課程 - Part2: Android 元件介紹炎炎夏日學 Android 課程 - Part2: Android 元件介紹
炎炎夏日學 Android 課程 - Part2: Android 元件介紹
Johnny Sung
 
炎炎夏日學 Android 課程 - Part 0: 環境搭建
炎炎夏日學 Android 課程 - Part 0: 環境搭建炎炎夏日學 Android 課程 - Part 0: 環境搭建
炎炎夏日學 Android 課程 - Part 0: 環境搭建
Johnny Sung
 
About Mobile Accessibility
About Mobile AccessibilityAbout Mobile Accessibility
About Mobile Accessibility
Johnny Sung
 
Introductions of Messaging bot 做聊天機器人
Introductions of Messaging bot 做聊天機器人Introductions of Messaging bot 做聊天機器人
Introductions of Messaging bot 做聊天機器人
Johnny Sung
 
First meet with Android Auto
First meet with Android AutoFirst meet with Android Auto
First meet with Android Auto
Johnny Sung
 
Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇
Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇
Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇
Johnny Sung
 
[MOPCON 2015] 談談行動裝置的 Accessibility
[MOPCON 2015] 談談行動裝置的 Accessibility[MOPCON 2015] 談談行動裝置的 Accessibility
[MOPCON 2015] 談談行動裝置的 Accessibility
Johnny Sung
 
Everything About Bluetooth (淺談藍牙 4.0) - Central 篇
Everything About Bluetooth (淺談藍牙 4.0) - Central 篇Everything About Bluetooth (淺談藍牙 4.0) - Central 篇
Everything About Bluetooth (淺談藍牙 4.0) - Central 篇
Johnny Sung
 
A Quick look at ANCS (Apple Notification Center Service)
A Quick look at ANCS (Apple Notification Center Service)A Quick look at ANCS (Apple Notification Center Service)
A Quick look at ANCS (Apple Notification Center Service)
Johnny Sung
 
uPresenter, the story.
uPresenter, the story.uPresenter, the story.
uPresenter, the story.
Johnny Sung
 
Android Wear Development
Android Wear DevelopmentAndroid Wear Development
Android Wear DevelopmentJohnny Sung
 
Android workshop - 02. Glass development 101
Android workshop - 02. Glass development 101Android workshop - 02. Glass development 101
Android workshop - 02. Glass development 101
Johnny Sung
 
Android workshop - 01. Getting started on android phone
Android workshop - 01. Getting started on android phoneAndroid workshop - 01. Getting started on android phone
Android workshop - 01. Getting started on android phone
Johnny Sung
 
Good!愛點兒 - 雲端電子點餐系統
Good!愛點兒 - 雲端電子點餐系統Good!愛點兒 - 雲端電子點餐系統
Good!愛點兒 - 雲端電子點餐系統
Johnny Sung
 

More from Johnny Sung (20)

[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @Devfest Taipei 2023
[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @Devfest Taipei 2023[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @Devfest Taipei 2023
[AI / ML] 用 LLM (Large language model) 來整理您的知識庫 @Devfest Taipei 2023
 
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具 @ Devfest Kaohsiung 2023
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具 @ Devfest Kaohsiung 2023[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具 @ Devfest Kaohsiung 2023
[Flutter] Flutter Provider 看似簡單卻又不簡單的狀態管理工具 @ Devfest Kaohsiung 2023
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang) [Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
 
談談 Android constraint layout
談談 Android constraint layout談談 Android constraint layout
談談 Android constraint layout
 
炎炎夏日學 Android 課程 - Part3: Android app 實作
炎炎夏日學 Android 課程 - Part3: Android app 實作炎炎夏日學 Android 課程 - Part3: Android app 實作
炎炎夏日學 Android 課程 - Part3: Android app 實作
 
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹炎炎夏日學 Android 課程 -  Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
 
炎炎夏日學 Android 課程 - Part2: Android 元件介紹
炎炎夏日學 Android 課程 - Part2: Android 元件介紹炎炎夏日學 Android 課程 - Part2: Android 元件介紹
炎炎夏日學 Android 課程 - Part2: Android 元件介紹
 
炎炎夏日學 Android 課程 - Part 0: 環境搭建
炎炎夏日學 Android 課程 - Part 0: 環境搭建炎炎夏日學 Android 課程 - Part 0: 環境搭建
炎炎夏日學 Android 課程 - Part 0: 環境搭建
 
About Mobile Accessibility
About Mobile AccessibilityAbout Mobile Accessibility
About Mobile Accessibility
 
Introductions of Messaging bot 做聊天機器人
Introductions of Messaging bot 做聊天機器人Introductions of Messaging bot 做聊天機器人
Introductions of Messaging bot 做聊天機器人
 
First meet with Android Auto
First meet with Android AutoFirst meet with Android Auto
First meet with Android Auto
 
Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇
Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇
Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇
 
[MOPCON 2015] 談談行動裝置的 Accessibility
[MOPCON 2015] 談談行動裝置的 Accessibility[MOPCON 2015] 談談行動裝置的 Accessibility
[MOPCON 2015] 談談行動裝置的 Accessibility
 
Everything About Bluetooth (淺談藍牙 4.0) - Central 篇
Everything About Bluetooth (淺談藍牙 4.0) - Central 篇Everything About Bluetooth (淺談藍牙 4.0) - Central 篇
Everything About Bluetooth (淺談藍牙 4.0) - Central 篇
 
A Quick look at ANCS (Apple Notification Center Service)
A Quick look at ANCS (Apple Notification Center Service)A Quick look at ANCS (Apple Notification Center Service)
A Quick look at ANCS (Apple Notification Center Service)
 
uPresenter, the story.
uPresenter, the story.uPresenter, the story.
uPresenter, the story.
 
Android Wear Development
Android Wear DevelopmentAndroid Wear Development
Android Wear Development
 
Android workshop - 02. Glass development 101
Android workshop - 02. Glass development 101Android workshop - 02. Glass development 101
Android workshop - 02. Glass development 101
 
Android workshop - 01. Getting started on android phone
Android workshop - 01. Getting started on android phoneAndroid workshop - 01. Getting started on android phone
Android workshop - 01. Getting started on android phone
 
Good!愛點兒 - 雲端電子點餐系統
Good!愛點兒 - 雲端電子點餐系統Good!愛點兒 - 雲端電子點餐系統
Good!愛點兒 - 雲端電子點餐系統
 

與 Sign in with Apple 的愛恨情仇 @ iPlayground2020

  • 1. 與 Sign in with Apple 的愛恨情仇 Johnny Sung #iplayground2020
  • 3. ⼤綱 • Sign in with Apple 的介紹 • iOS App 端流程 • 網站端流程 • 關於虛擬 E-mail • 蘋果開發者網站設定 • iOS、網站、後端 實作概念
  • 5. 官⽅消息指出, 從 2019 年 9 ⽉ 12 ⽇開始,新上架的 APP 需設置 Sign in with Apple
  • 7.
  • 8. 就「⼀定要」⽀援 Sign in with Apple http://www.johnnytimes.com/wp-content/uploads/2016/06/copycat.jpg
  • 13.
  • 14. Sign in with Apple • 使⽤ Apple ID 登入,強化保護您的隱私權 • 當⽤⼾不願給出⾃⼰的 E-mail 時,蘋果可以⽣成⼀組「虛擬 E-mail」給⽤⼾使⽤。 • 「虛擬 E-mail」收到的資訊,蘋果會代轉給⽤⼾的「真實 E-mail」
  • 15. Apple Sign In 的原理
  • 17. App 登入 1. 使⽤者按下 Sign in with Apple 按鈕, 呼叫相關 AuthenticationServices framework 的相關函式 2. iOS 系統跳出 AppleId 登入確認,利⽤ TouchId 指紋辨識 或 FaceId 臉部辨識 (可選擇是否隱藏其 E-mail) 3. 當登入授權成功時,系統呼叫 didCompleteWithAuthorization 處理該 Callback 相關參數 4. ⽤ API 傳回⾃⼰伺服器做驗證 https://support.apple.com/library/content/dam/edam/applecare/images/zh_TW/appleid/ios14-iphone-11-pro-sign-in-with-apple.jpg
  • 18.
  • 19.
  • 20. 網站登入 1. 使⽤者按下 Sign in with Apple 按鈕, 呼叫蘋果提供的 JavaScript 帶⼊ Redirect URI(轉址位址) 2. 使⽤者在 Apple 網站進⾏登⼊,輸⼊ AppleId 的帳號密碼, 並授權開發商授權允許(可選擇是否隱藏其 E-mail ) 3. 當登⼊授權成功時,轉址回設定之 Redirect URI 並附上參數 4. ⽤ API 傳回⾃⼰伺服器做驗證
  • 21.
  • 22.
  • 25. 蘋果開發者網站設定 1. App ID (iOS app 使⽤) 2. Service ID (網站使⽤) 3. Sign Key (後端驗證使⽤) 4. Email 寄件⼈ & 網域 (Email relay service 使⽤)
  • 26. 所需材料 (1/2) • Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs • App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs 範例值: - Name: SignAppleDemo - AppID: com.johnny.signapple 範例值: - Name: SignAppleDemo - AppID: com.johnny.websignapple
  • 27. 所需材料 (2/2) • Sign Key Certificates, Identifiers & Profiles -> Keys 範例值: - Name: SignAppleKey - KeyID: D2XXXXX7KY - p8 file: -----BEGIN PRIVATE KEY----- EGCCqGSM49AwEHBHkwdwIBA -----END PRIVATE KEY-----
  • 28. 設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs
  • 29. 設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs
  • 30. 設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs
  • 31. 設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs
  • 32. 設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs
  • 33. 設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
  • 34. 設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
  • 35. 設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
  • 36. 設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
  • 37. 設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs
  • 38. 設定 Sign Key Certificates, Identifiers & Profiles -> Keys
  • 39. 設定 Sign Key Certificates, Identifiers & Profiles -> Keys
  • 40. 設定 Sign Key Certificates, Identifiers & Profiles -> Keys
  • 41. 材料整理 • Client ID • iOS App - App ID (Bundle ID) • 網站 - Service ID • Redirect URI • iOS ⽤的 API endpoint • 網站 API endpoint • Team ID • Sign Key & Key ID
  • 43. • 蘋果⽣成⼀組,虛擬 E-mail 給⽤⼾使⽤ • 蘋果會驗證寄件⼈與寄件來源 (需設定寄件⼈&寄件網域) • 寄件⼈可以設定 Gmail • ⾃訂網域需設定 SPF (DNS Sender Policy Freamwork) Email Relay Service
  • 44. 設定寄件⼈、寄件網域 Certificates, Identifiers & Profiles -> More -> Sign in with Apple for Email Communication
  • 45. 設定寄件⼈、寄件網域 Certificates, Identifiers & Profiles -> More -> Sign in with Apple for Email Communication
  • 47. 設定 SPF (DNS Sender Policy Freamwork)
  • 48. 設定 SPF (DNS Sender Policy Freamwork) "v=spf1 include:_spf.google.com include:sendgrid.net include:amazonses.com ~all" 新增 DNS TXT Record 郵件服務 Email Service Provider (ESP) • Google Gmail • SendGrid • Amazon SES
  • 49.
  • 51. • 樣式:⿊⾊ vs. ⽩⾊有邊框 vs. ⽩⾊無邊框 • 字樣:Sign in with Apple vs. Continue with Apple vs. 無 • 圓⾓:有圓⾓ vs. 無圓⾓ 登入按鈕樣式 https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/
  • 52. iOS App 部分 1. 使⽤者按下 Sign in with Apple 按鈕, 呼叫相關 AuthenticationServices framework 的相關函式 2. iOS 系統跳出 AppleId 登入確認,利⽤ TouchId 指紋辨識 或 FaceId 臉部辨識 (可選擇是否隱藏其 E-mail) 3. 當登入授權成功時,系統呼叫 didCompleteWithAuthorization 處理該 Callback 將相關參數,⽤ API 傳回⾃⼰的網站
  • 53. import Foundation import AuthenticationServices class AppleSignInManager: NSObject { var currentView: UIView? func signIn(currentView: UIView) { guard #available(iOS 13.0, *) else { return } self.currentView = currentView let provider = ASAuthorizationAppleIDProvider() let request = provider.createRequest() request.requestedScopes = [.email, .fullName] request.nonce = "[NONCE]" request.state = "[STATE]" let controller = ASAuthorizationController(authorizationRequests: [request]) controller.delegate = self controller.presentationContextProvider = self controller.performRequests() } } iOS 實作片段 (1/3) 辨識⽤的值,避免 CSRF 攻擊
  • 54. extension AppleSignInManager: ASAuthorizationControllerDelegate { @available(iOS 13.0, *) func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { // Handle error print(error) } @available(iOS 13.0, *) func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return } // Post identityToken & authorizationCode to your server print(String(decoding: credential.identityToken ?? Data.init(), as: UTF8.self)) print(String(decoding: credential.authorizationCode ?? Data.init(), as: UTF8.self)) } } iOS 實作片段 (2/3) 要處理請求失敗 請求成功,⽤ API 回傳 id_token 與 auth_code 回您的 Server
  • 55. extension AppleSignInManager: ASAuthorizationControllerPresentationContextProviding { @available(iOS 13.0, *) func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { return self.currentView?.window ?? UIApplication.shared.keyWindow! } } iOS 實作片段 (3/3) 要放入⽬前所在 ViewController 的 window
  • 57. • 樣式:⿊⾊ vs. ⽩⾊有邊框 vs. ⽩⾊無邊框 • 字樣:Sign in with Apple vs. Continue with Apple vs. 無 • 圓⾓:有圓⾓ vs. 無圓⾓ 登入按鈕樣式 https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/
  • 58. <html> <head> </head> <body> <script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script> <div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div> <script type="text/javascript"> AppleID.auth.init({ clientId: '[CLIENT_ID]', scope: 'name email', redirectURI: '[REDIRECT_URI]', state: '[STATE]', nonce: '[NONCE]', usePopup: false }); </script> </body> </html> 網站實作片段 (1/2) 辨識⽤的值,避免 CSRF 攻擊 設定轉跳的網址 使⽤彈窗模式? 填入 Service ID
  • 59. async function doAppleSignIn() { try { const data = await AppleID.auth.signIn(); console.log(data); } catch (error) { //handle error. } } 網站實作片段 (2/2)
  • 64. • RFC 7519 - JSON Web Token(JWT) 定義了 header 內容與 claim 內容,以及 token 的相關規範 • RFC 7515 - JSON Web Signature(JWS) 定義如何做帶有簽章的 token • RFC 7516 - JSON Web Encryption(JWE) 定義內容加密的 token • RFC 7517 - JSON Web Key(JWK) 定義⾦鑰的格式 • RFC 7518 - JSON Web Algorithms(JWA) 定義加解密的演算法 https://ithelp.ithome.com.tw/articles/10224787 JWT? JWS? JWK? JWA? - JWS 與 JWE 都是屬於 JWT 的⼀種。 - 如果沒特別說明,則 JWT 皆是指 JWS。 https://hlqft4a0qsn1cy1gi1bevyhj-wpengine.netdna-ssl.com/wp-content/uploads/2019/05/key-types-600x453.jpg 🖖
  • 65. https://twitter.com/irina_papuc/status/900085165568937984/photo/1 base64UrlEncode({ "alg": "RS256",
 "typ": "JWT" }) base64UrlEncode{{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }) HMACSHA256(
 base64UrlEncode(header) + "." +
 base64UrlEncode(payload)
 , secretKey) . . Header Algorithm & token type Payload Data Signature Verification Json Web Token https://19yw4b240vb03ws8qm25h366-wpengine.netdna-ssl.com/wp-content/uploads/Why-Cant-I-Just-Send-JWTs-Without-OAuth-JWT.png
  • 67. { "iss": "https://appleid.apple.com", "aud": "com.johnny.signapple", "exp": 1596621649, "iat": 1596621049, "sub": "001451.3dc43615849bcf03b2cce4e48048a59f.0447", "c_hash": "iUqI9RgFbplkcW9Org-CyoA", "email": "8n4prkdcmew@privaterelay.appleid.com", "email_verified": "true", "is_private_email": "true", "auth_time": 1596621049, "nonce_supported": true } { "kid": "86D88Kf", "alg": "RS256" } eyJraWQiOiI4NkQ4OEtmIiwiYWxnIjoiUlMyNTYifQ Header Algorithm & token type eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkI joiY29tLjkxcHUhQ5LCJpYXQiOjE1OTY2MjEwNDksInN1YiI6IjAw MTQ1MS4zZGM0MzYxNTVmYjA0NjAzYjJjY2U0ZTQ4MDQ4YTU5Zi4wN Q3lvQSIsImVtYWlsIjoiOkuYXBwbGVpZC5jb20iLCJlbWFpbF92ZX JpZmllZCI6InRydWUiLCJpc19wcml2YXRlX2VtYWlsIjoidHJ1ZSI sImF1dGhfdGltZSI6MTU5NjYyMTA0OSwibm9uY2Vfc3VwcG9ydGVk Ijp0cnVlfQ Payload Data Signature Verification KccMlP7OoIctkaEzy09pJK0t-uzwkT-u3UT7BNWJ1mS2mU_FXH- pKTjnyO7Whd9vh-pBQdVU5vZ7kKeD3rMqGi- kKkLmNO1yjBse2cnfs7WLthtrhrthnbi1iDxHvedFjBOUhOzfcFfwn4- CLSUZcb7aukHd0hj0NYzigBWzFAbxDmYtM7hlqQmJaYBh6RzYfwMOxK58 HRcVnx9wy3vzTFfj25x6nqMGxosVXkD0N0PP1b30uem8tyS4wSu3w5zoE 2Bpaos_fhattM_p28WdcrA4Ne89ET8D5GYSe448VlIyXSonfHBveE5- hSVQAzIjP4B_JOCcRBpM3Q
  • 68. JWT • Header • alg - 加解密演算法 JWA (JSON Web Algorithms) • "HS256" (HMAC-SHA256) • "RS256" (RSA-SHA256) • "ES256" (ECDSA-SHA256) • typ - JWT 本⾝的媒體類型 ⽤預設值 "JWT" • kid - Sign Key ID { "kid": "86D88Kf", "typ": "JWT" "alg": "RS256" } Header Algorithm & token type
  • 69. JWT • Payload • iss - 發⾏者 ( Issuer ) • aud - 接收者 ( Audience ) • iat - 發⾏時間 ( Issued at (time) ) ⽤ Unix timestamp 表⽰ • exp - 過期時間 ( Expiration (time) ) ⽤ Unix timestamp 表⽰ • sub - 主題 ( Subject ) ⽤ URI 表⽰唯⼀識別訊息 • Signature • 非對稱演算法加密(Header + "." + Payload) { "iss": "https://appleid.apple.com", "aud": "com.johnny.signapple", "iat": 1596621049, "exp": 1596621649, "sub": "001451.3dc436158........9f.0447", "c_hash": "iUqI9RgFbplkcW9Org-CyoA", "email": "8nmew@privaterelay.appleid.com", "email_verified": "true", "is_private_email": "true", "auth_time": 1596621049, "nonce_supported": true } Payload Data
  • 70. 驗證⽅式 1: 驗證 IdentityToken
  • 71. 步驟 1. 接收從 client 傳來的 IdentityToken (JWT) ( 蘋果 會⽤它的私鑰加密 IdentityToken 的簽章部分 ) 2. 呼叫 /auth/keys 取得 蘋果 公鑰 (JWK) 3. 整理 JWK 成 pem 格式 4. ⽤ 蘋果 公鑰 來驗證 client 傳來的 IdentityToken 5. 從 IdentityToken 的 payload 取得資料
  • 72. { "keys": [ { "kid": "86D88Kf", "kty": "RSA", "use": "sig", "alg": "RS256", "n": "iGaLqP6y-SJCCBq5H.....Yw-zHLwQ", "e": "AQAB" }, { "kty": "RSA", "kid": "eXaunmL", "use": "sig", "alg": "RS256", "n": "4dGQ7bQK8LgI...........JNdUhxw", "e": "AQAB" } ] } 取得蘋果公鑰 • API Endpoint GET https://appleid.apple.com/auth/keys • 內容為標準 JWK (JSON Web Key) 格式 • kid - ⾦鑰 ID • kty - Key Type ⾦鑰類型 • alg - 演算法 值 "RS256" 為 RSA-SHA256 演算法 • use - ⽤途描述 值 "sig" 意思是 數位簽章 • n - RSA 模數 (Modulus) 為公鑰內容的⼀部分,內容為 base64urlUInt 編碼後的結果 • e - RSA 指數 (Exponent) 為公鑰內容的⼀部分,內容為 base64urlUInt 編碼後的結果 回傳結果
  • 73. 蘋果  API ⽂件: https://developer.apple.com/documentation/sign_in_with_apple/fetch_apple_s_public_key_for_verifying_token_signature
  • 74. require_once '../vendor/autoload.php'; function getUserDataFromIdentityToken($idToken) { $token = (new LcobucciJWTParser())->parse((string)$idToken); $applePublicKeysRaw = curlGetAppleAuthKeys(); $applePublicKeys = JWKParseKeySet($applePublicKeysRaw); $applePublicKey = $applePublicKeys[$token->getHeader('kid')]; $signer = new LcobucciJWTSignerRsaSha256(); $keychain = new LcobucciJWTSignerKeychain(); if (!$token->verify($signer, $keychain->getPublicKey($applePublicKey))) { throw new RuntimeException("Key validation failed."); } if ('https://appleid.apple.com' !== $token->getClaim('iss')) { throw new RuntimeException("Source incorrect."); } $userData = array(); $userData['email'] = $token->getClaim('email'); $userData['id'] = $token->getClaim('sub'); return $userData; } 驗證 JWT 的 Signature 找到指定的公鑰 擷取 JWT 的 Payload 內容 抓取蘋果的公鑰
  • 75. function curlGetAppleAuthKeys() { $ch = curl_init('https://appleid.apple.com/auth/keys'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($ch); curl_close($ch); return json_decode($result, true); } function JWKParseKeySet($keySets) { $parsed = FirebaseJWTJWK::parseKeySet($keySets); $pemKeySets = array(); foreach ($parsed as $keyId => $sslKey) { $pemKeySets[$keyId] = openssl_pkey_get_details($sslKey)['key']; } return $pemKeySets; } function JWKVerify($idToken, $publicKeyPem) { $signer = new LcobucciJWTSignerRsaSha256(); $keychain = new LcobucciJWTSignerKeychain(); $token = (new LcobucciJWTParser())->parse((string)$idToken); return $token->verify($signer, $keychain->getPublicKey($publicKeyPem)); } composer.json { "require": { "firebase/php-jwt": "5.2.0", "lcobucci/jwt": "3.3.2" } }
  • 76. -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiGaLqP6y+ SJCCBq5Hv6p GDbG/ SQ11MNjH7rWHcCFYz4hGwHC4lcSurTlV8u3avoVNM8jXevG1Iu1SY 11qInq UvjJur+ +hghr1b56OPJu6H1iKulSxGjEIyDP6c5BdE1uwprYyr4IO9th8fOw CPyg jLFrh44XEGbDIFeImwvBAGOhmMB2AD1n1KviyNsH0bEB7phQtiLk+ ILjv1bORSRl 8AK677+1T8isGfHKXGZ/ ZGtStDe7Lu0Ihp8zoUt59kx2o9uWpROkzF56ypresiIl 4WprClRCjz8x6cPZXU2qNWhu71TQvUFwvIvbkE1oYaJMb0jcOTmBR ZA2QuYw+zHL wQIDAQAB -----END PUBLIC KEY----- { "kty": "RSA", "kid": "86D88Kf", "use": "sig", "alg": "RS256", "n": "iGaLqP6y- SJCCBq5Hv6pGDbG_SQ11MNjH7rWHcCFYz4hGwHC4lcSurTlV8u3av oVNM8jXevG1Iu1SY11qInqUvjJur-- hghr1b56OPJu6H1iKulSxGjEIyDP6c5BdE1uwprYyr4IO9th8fOwC PygjLFrh44XEGbDIFeImwvBAGOhmMB2AD1n1KviyNsH0bEB7phQti Lk- ILjv1bORSRl8AK677-1T8isGfHKXGZ_ZGtStDe7Lu0Ihp8zoUt59k x2o9uWpROkzF56ypresiIl4WprClRCjz8x6cPZXU2qNWhu71TQvUF wvIvbkE1oYaJMb0jcOTmBRZA2QuYw-zHLwQ", "e": "AQAB" } JWKParseKey
  • 77. 驗證⽅式 2: 使⽤ AuthorizationCode
  • 78. 步驟 1. 接收從 client 傳來的 AuthorizationCode 2. ⽤ 您的私鑰 製作 client_secret 也是⼀個 JWT Token 3. 呼叫 /auth/token 的 API,得到 IdentityToken ( 蘋果 會⽤ 您的公鑰 解密驗證 client_secret 的簽章部分 ) ( 蘋果 會⽤它的私鑰加密 IdentityToken 的簽章部分 ) 4. ⽤ 蘋果 公鑰 來驗證 client 傳來的 IdentityToken(步驟同上述做法) 5. 解開 IdentityToken 的 JWT 取得資料
  • 79. 蘋果  API ⽂件: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
  • 80. • API Endpoint POST https://appleid.apple.com/auth/token • 傳送參數 • client_id - 填入 Service ID (網站) 或 App ID (iOS App) • client_secret - ⼀個 JWT 格式的要求⽂件(詳) • code - Authorization code • grant_type - 授權⽅式 填 `authorization_code` 來交換 AccessToken 交換 AuthorizationCode
  • 81. { "access_token": "a6cab...........Y1A", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "r9d77fa9..........gfYA", "id_token": "eyJraW.................jMA" } • API Endpoint POST https://appleid.apple.com/auth/token • 回傳結果 • access_token - token,⽬前沒作⽤ 😂 • expires_in - 過期時間 • id_token - IdentityToken • refresh_token - 更新 access_token 時使⽤ 交換 AuthorizationCode 回傳結果
  • 82. 蘋果  API ⽂件: https://developer.apple.com/documentation/sign_in_with_apple/tokenresponse 🤔
  • 83. • invalid_request • 通常是連參數都弄錯 • invalid_client • 可能是 client_id 弄錯 • 可能是 client_secret (JWT 格式) 裡的 sub 參數跟 client_id 參數不吻合 Troubleshooting
  • 84. • invalid_grant • 可能是 client_secret (JWT 格式) 加解密算錯 ⚠ • 可能是 Authorization Code 過期 ⚠ (Authorization Code 效期超短,通常只有 1-2 分鐘,不超過 5 分鐘) • 可能是 Authorization Code 已被使⽤,變成無效的 code ⚠ (API 帶相同參數重複打就會出現) • 其他錯誤訊息,請參考蘋果  API ⽂件: https://developer.apple.com/documentation/sign_in_with_apple/errorresponse Troubleshooting
  • 85. Server to Server Notification
  • 86. 設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs
  • 87. { "payload": "eyJraWQxxxxxxxxxxxxxxiUlMyNTYifQ.eyJpcxxxxxxxxx xxxxc0fSJ9.IUFWxPxxxxxxxxxxxxxxxxxbL3olA" } Server notification 我也是⼀個 JWT 哦 ❤ 範例值: - API Endpoint: https://your.awesome.domain/handle_signin_notification.php 接收範例值 註:截稿至現在, Apple 還沒有⽂件,只有在 WWDC 2020 影⽚上提到
  • 88.
  • 89.
  • 90.
  • 91.
  • 92. - Introducing Sign In with Apple - WWDC2019 https://developer.apple.com/videos/play/wwdc2019/706/ - Get the most out of Sign in with Apple - WWDC2020 https://developer.apple.com/videos/play/wwdc2020/10173 - JWT 簽名算法 HS256、RS256 及 ES256 及密鑰⽣成 https://www.cnblogs.com/kirito-c/p/12402066.html - 驗證 JSON Web Token https://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html - Sign in with Apple http://uirate.net/?p=10363 - Ensure mail delivery & prevent spoofing (SPF) https://support.google.com/a/answer/33786 - DNS 設定 spf 記錄 - Sender Policy Framework https://blog.xuite.net/tolarku/blog/233356505 - Generate and Validate Tokens https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens - 簡介 JWK 與 JWA https://ithelp.ithome.com.tw/articles/10225590 - Sign in with Apple Tutorial, Part 4: Web and Other Platforms https://sarunw.com/posts/sign-in-with-apple-4/ - JWT 概觀 https://ithelp.ithome.com.tw/articles/10224787 - [Note] OAuth2.0 學習筆記 | PJCHENder 未整理筆記 https://pjchender.github.io/2017/11/16/note-oauth2-0-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98/ 參考資料 (1/3)
  • 93. - 簡單易懂的 OAuth 2.0 https://speakerdeck.com/chitsaou/jian-dan-yi-dong-de-oauth-2-dot-0 - 關於OAuth 2.0-以Facebook為例 https://medium.com/@justinlee_78563/%E9%97%9C%E6%96%BCoauth-2-0-%E4%BB%A5facebook%E7%82%BA%E4%BE%8B-6f78a4a55f52 - [PHP] OAuth / Sign in with Apple JS - 使⽤ Apple JS SDK 讓網站⽀援 Apple ID 登入 http://blog.changyy.org/2019/11/php-jwt-oauth-sign-in-with-apple-js.html - What the Heck is Sign In with Apple? https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple - 如何整合 Sign in with Apple 到⾃⼰的 iOS App 上 (iOS & Backend) https://medium.com/@tuzaiz/%E5%A6%82%E4%BD%95%E6%95%B4%E5%90%88-sign-in-with-apple- %E5%88%B0%E8%87%AA%E5%B7%B1%E7%9A%84-ios-app-%E4%B8%8A-ios-backend-e64d9de15410 - Sign in with Apple(蘋果授權登陸) https://blog.csdn.net/wpf199402076118/article/details/99677412 - Sign in with Apple 登錄詳解 https://ihtcboy.com/2019/09/16/2019-09-16_Sign-in-with-Apple/ - iOS13 Sign In With Apple 適配 http://jerryliu.org/ios%20programming/iOS13-Sign-With-Apple%E6%96%B0%E7%89%B9%E6%80%A7%E9%80%82%E9%85%8D - 蘋果Sign In with Apple爆可被劫持帳號的漏洞 https://www.ithome.com.tw/news/137972 - 蘋果重磅推出「Sign in with Apple」登入,背後忽略的隱私盲點 https://www.bnext.com.tw/article/53765/what-is-the-meaning-of-sign-in-with-apple 參考資料 (2/3)
  • 94. - [筆記] 透過 JWT 實作驗證機制 https://medium.com/ %E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98- %E9%80%8F%E9%81%8E-jwt-%E5%AF%A6%E4%BD%9C%E9%A9%97%E8%AD%89%E6%A9%9F%E5%88%B6-2e64d72594f8 - 是誰在敲打我窗?什麼是 JWT ? https://5xruby.tw/posts/what-is-jwt/ - 基礎密碼學-對稱式與非對稱式加密技術 https://medium.com/@RiverChan/%E5%9F%BA%E7%A4%8E%E5%AF%86%E7%A2%BC%E5%AD%B8- %E5%B0%8D%E7%A8%B1%E5%BC%8F%E8%88%87%E9%9D%9E%E5%B0%8D%E7%A8%B1%E5%BC%8F%E5%8A%A0%E5%AF%86%E6%8A%80%E8%A1 %93-de25fd5fa537 參考資料 (3/3)