Slide 1

Slide 1 text

與 Sign in with Apple 的愛恨情仇 Johnny Sung #iplayground2020

Slide 2

Slide 2 text

Mobile devices Developer https://fb.com/j796160836 https://blog.jks.coffee/ https://www.slideshare.net/j796160836 https://github.com/j796160836 Johnny Sung

Slide 3

Slide 3 text

⼤綱 • Sign in with Apple 的介紹 • iOS App 端流程 • 網站端流程 • 關於虛擬 E-mail • 蘋果開發者網站設定 • iOS、網站、後端 實作概念

Slide 4

Slide 4 text

https://support.apple.com/zh-tw/HT210318

Slide 5

Slide 5 text

官⽅消息指出, 從 2019 年 9 ⽉ 12 ⽇開始,新上架的 APP 需設置 Sign in with Apple

Slide 6

Slide 6 text

只要您的 app 有⽀援第三⽅登入 在 2020 年 4 ⽉之後,

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

就「⼀定要」⽀援 Sign in with Apple http://www.johnnytimes.com/wp-content/uploads/2016/06/copycat.jpg

Slide 9

Slide 9 text

否則,

Slide 10

Slide 10 text

否則?

Slide 11

Slide 11 text

https://image.cnbcfm.com/api/v1/image/105608434-1543945658496rts28qzc.jpg

Slide 12

Slide 12 text

https://www.appmachine.com/wp-content/uploads/2015/01/7-Reasons-Why-Apple-Could-Reject-Your-App-b-1.jpg

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

Sign in with Apple • 使⽤ Apple ID 登入,強化保護您的隱私權 • 當⽤⼾不願給出⾃⼰的 E-mail 時,蘋果可以⽣成⼀組「虛擬 E-mail」給⽤⼾使⽤。 • 「虛擬 E-mail」收到的資訊,蘋果會代轉給⽤⼾的「真實 E-mail」

Slide 15

Slide 15 text

Apple Sign In 的原理

Slide 16

Slide 16 text

App 登入

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

網站登入 1. 使⽤者按下 Sign in with Apple 按鈕, 呼叫蘋果提供的 JavaScript 帶⼊ Redirect URI(轉址位址) 2. 使⽤者在 Apple 網站進⾏登⼊,輸⼊ AppleId 的帳號密碼, 並授權開發商授權允許(可選擇是否隱藏其 E-mail ) 3. 當登⼊授權成功時,轉址回設定之 Redirect URI 並附上參數 4. ⽤ API 傳回⾃⼰伺服器做驗證

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

網站登入

Slide 24

Slide 24 text

蘋果開發者網站設定

Slide 25

Slide 25 text

蘋果開發者網站設定 1. App ID (iOS app 使⽤) 2. Service ID (網站使⽤) 3. Sign Key (後端驗證使⽤) 4. Email 寄件⼈ & 網域 (Email relay service 使⽤)

Slide 26

Slide 26 text

所需材料 (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

Slide 27

Slide 27 text

所需材料 (2/2) • Sign Key Certificates, Identifiers & Profiles -> Keys 範例值: - Name: SignAppleKey - KeyID: D2XXXXX7KY - p8 file: -----BEGIN PRIVATE KEY----- EGCCqGSM49AwEHBHkwdwIBA -----END PRIVATE KEY-----

Slide 28

Slide 28 text

設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs

Slide 29

Slide 29 text

設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs

Slide 30

Slide 30 text

設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs

Slide 31

Slide 31 text

設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs

Slide 32

Slide 32 text

設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs

Slide 33

Slide 33 text

設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs

Slide 34

Slide 34 text

設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs

Slide 35

Slide 35 text

設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs

Slide 36

Slide 36 text

設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs

Slide 37

Slide 37 text

設定 Service ID Certificates, Identifiers & Profiles -> Identifiers -> Service IDs

Slide 38

Slide 38 text

設定 Sign Key Certificates, Identifiers & Profiles -> Keys

Slide 39

Slide 39 text

設定 Sign Key Certificates, Identifiers & Profiles -> Keys

Slide 40

Slide 40 text

設定 Sign Key Certificates, Identifiers & Profiles -> Keys

Slide 41

Slide 41 text

材料整理 • Client ID • iOS App - App ID (Bundle ID) • 網站 - Service ID • Redirect URI • iOS ⽤的 API endpoint • 網站 API endpoint • Team ID • Sign Key & Key ID

Slide 42

Slide 42 text

Email Relay Service

Slide 43

Slide 43 text

• 蘋果⽣成⼀組,虛擬 E-mail 給⽤⼾使⽤ • 蘋果會驗證寄件⼈與寄件來源 (需設定寄件⼈&寄件網域) • 寄件⼈可以設定 Gmail • ⾃訂網域需設定 SPF (DNS Sender Policy Freamwork) Email Relay Service

Slide 44

Slide 44 text

設定寄件⼈、寄件網域 Certificates, Identifiers & Profiles -> More -> Sign in with Apple for Email Communication

Slide 45

Slide 45 text

設定寄件⼈、寄件網域 Certificates, Identifiers & Profiles -> More -> Sign in with Apple for Email Communication

Slide 46

Slide 46 text

設定寄件⼈、寄件網域

Slide 47

Slide 47 text

設定 SPF (DNS Sender Policy Freamwork)

Slide 48

Slide 48 text

設定 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

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

iOS App 端實作

Slide 51

Slide 51 text

• 樣式:⿊⾊ 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/

Slide 52

Slide 52 text

iOS App 部分 1. 使⽤者按下 Sign in with Apple 按鈕, 呼叫相關 AuthenticationServices framework 的相關函式 2. iOS 系統跳出 AppleId 登入確認,利⽤ TouchId 指紋辨識 或 FaceId 臉部辨識 (可選擇是否隱藏其 E-mail) 3. 當登入授權成功時,系統呼叫 didCompleteWithAuthorization 處理該 Callback 將相關參數,⽤ API 傳回⾃⼰的網站

Slide 53

Slide 53 text

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 攻擊

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

網站實作

Slide 57

Slide 57 text

• 樣式:⿊⾊ 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/

Slide 58

Slide 58 text

AppleID.auth.init({ clientId: '[CLIENT_ID]', scope: 'name email', redirectURI: '[REDIRECT_URI]', state: '[STATE]', nonce: '[NONCE]', usePopup: false }); 網站實作片段 (1/2) 辨識⽤的值,避免 CSRF 攻擊 設定轉跳的網址 使⽤彈窗模式? 填入 Service ID

Slide 59

Slide 59 text

async function doAppleSignIn() { try { const data = await AppleID.auth.signIn(); console.log(data); } catch (error) { //handle error. } } 網站實作片段 (2/2)

Slide 60

Slide 60 text

對稱式加密 & 非對稱式加密 基礎密碼學

Slide 61

Slide 61 text

對稱式加密 (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

Slide 62

Slide 62 text

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)

Slide 63

Slide 63 text

Json Web Token

Slide 64

Slide 64 text

• 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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

https://jwt.io/

Slide 67

Slide 67 text

{ "iss": "https://appleid.apple.com", "aud": "com.johnny.signapple", "exp": 1596621649, "iat": 1596621049, "sub": "001451.3dc43615849bcf03b2cce4e48048a59f.0447", "c_hash": "iUqI9RgFbplkcW9Org-CyoA", "email": "[email protected]", "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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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": "[email protected]", "email_verified": "true", "is_private_email": "true", "auth_time": 1596621049, "nonce_supported": true } Payload Data

Slide 70

Slide 70 text

驗證⽅式 1: 驗證 IdentityToken

Slide 71

Slide 71 text

步驟 1. 接收從 client 傳來的 IdentityToken (JWT) ( 蘋果 會⽤它的私鑰加密 IdentityToken 的簽章部分 ) 2. 呼叫 /auth/keys 取得 蘋果 公鑰 (JWK) 3. 整理 JWK 成 pem 格式 4. ⽤ 蘋果 公鑰 來驗證 client 傳來的 IdentityToken 5. 從 IdentityToken 的 payload 取得資料

Slide 72

Slide 72 text

{ "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 編碼後的結果 回傳結果

Slide 73

Slide 73 text

蘋果  API ⽂件: https://developer.apple.com/documentation/sign_in_with_apple/fetch_apple_s_public_key_for_verifying_token_signature

Slide 74

Slide 74 text

require_once '../vendor/autoload.php'; function getUserDataFromIdentityToken($idToken) { $token = (new Lcobucci\JWT\Parser())->parse((string)$idToken); $applePublicKeysRaw = curlGetAppleAuthKeys(); $applePublicKeys = JWKParseKeySet($applePublicKeysRaw); $applePublicKey = $applePublicKeys[$token->getHeader('kid')]; $signer = new Lcobucci\JWT\Signer\Rsa\Sha256(); $keychain = new Lcobucci\JWT\Signer\Keychain(); 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 內容 抓取蘋果的公鑰

Slide 75

Slide 75 text

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 = \Firebase\JWT\JWK::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 Lcobucci\JWT\Signer\Rsa\Sha256(); $keychain = new Lcobucci\JWT\Signer\Keychain(); $token = (new Lcobucci\JWT\Parser())->parse((string)$idToken); return $token->verify($signer, $keychain->getPublicKey($publicKeyPem)); } composer.json { "require": { "firebase/php-jwt": "5.2.0", "lcobucci/jwt": "3.3.2" } }

Slide 76

Slide 76 text

-----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

Slide 77

Slide 77 text

驗證⽅式 2: 使⽤ AuthorizationCode

Slide 78

Slide 78 text

步驟 1. 接收從 client 傳來的 AuthorizationCode 2. ⽤ 您的私鑰 製作 client_secret 也是⼀個 JWT Token 3. 呼叫 /auth/token 的 API,得到 IdentityToken ( 蘋果 會⽤ 您的公鑰 解密驗證 client_secret 的簽章部分 ) ( 蘋果 會⽤它的私鑰加密 IdentityToken 的簽章部分 ) 4. ⽤ 蘋果 公鑰 來驗證 client 傳來的 IdentityToken(步驟同上述做法) 5. 解開 IdentityToken 的 JWT 取得資料

Slide 79

Slide 79 text

蘋果  API ⽂件: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens

Slide 80

Slide 80 text

• 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

Slide 81

Slide 81 text

{ "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 回傳結果

Slide 82

Slide 82 text

蘋果  API ⽂件: https://developer.apple.com/documentation/sign_in_with_apple/tokenresponse

Slide 83

Slide 83 text

• invalid_request • 通常是連參數都弄錯 • invalid_client • 可能是 client_id 弄錯 • 可能是 client_secret (JWT 格式) 裡的 sub 參數跟 client_id 參數不吻合 Troubleshooting

Slide 84

Slide 84 text

• 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

Slide 85

Slide 85 text

Server to Server Notification

Slide 86

Slide 86 text

設定 App ID (Bundle ID) Certificates, Identifiers & Profiles -> Identifiers -> App IDs

Slide 87

Slide 87 text

{ "payload": "eyJraWQxxxxxxxxxxxxxxiUlMyNTYifQ.eyJpcxxxxxxxxx xxxxc0fSJ9.IUFWxPxxxxxxxxxxxxxxxxxbL3olA" } Server notification 我也是⼀個 JWT 哦 ❤ 範例值: - API Endpoint: https://your.awesome.domain/handle_signin_notification.php 接收範例值 註:截稿至現在, Apple 還沒有⽂件,只有在 WWDC 2020 影⽚上提到

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

No content

Slide 90

Slide 90 text

No content

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

- 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)

Slide 93

Slide 93 text

- 簡單易懂的 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)

Slide 94

Slide 94 text

- [筆記] 透過 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)

Slide 95

Slide 95 text

https://www.newaydirections.com/wp-content/uploads/2019/08/Blog-picture.jpg