Web透過Apple ID登入
Apple Console設定
首先前往Apple Console App的總覽頁
並前往Certificates, Indentifiers & Profiles頁
接著新增一個新的Identifiers選擇Services IDs類型
接著依序做基本設定
最後設定Web的網域、RedirectURI設定
接著前往Keys頁面建立全新的Key並保留好
後續會接著使用
比較麻煩的地方
有處理過Apple的App或是API的人
應該都知道Apple很多有的沒的限制
以下這幾點是Apple ID登入跟其他常見的第三方登入(Google/Facebook)差異比較大的部份
不能用localhost只能用https
Apple表示為了安全只能用https
所以local開發只能靠ngrok
url不能有hash
本來想說用github page發佈比較快
結果因為我用vuejs寫放到github page只能用hash mode
然後apple又擋掉說不行有hash ( ???
Email可以隱藏
這點最麻煩
因為Apple ID登入可以讓使用者選擇是否要隱藏email
隱藏的話Apple會產一個隨機的email
如果對這個隨機email發信
Apple會轉寄給使用者原始的email
如果系統的會員一定要透過email註冊、登入
就需要考慮當使用者隱藏的時候
要怎麼處理
沒有一定答案就看專案的商業邏輯
return uri(或是redirect uri)是用form post模式
Google跟Facebook登入完成之後導回redirect uri都是用get模式
但apple就一定要用form post
如果是的前後端分離前端用SPA的話
變成要用後端去當return uri的進入點另外去接參數然後導回前端
流程
以下為Vue + Laravel架構
1. 觸發Apple登入
使用Apple sign in library或自行組url導向Apple登入頁面
2. 導向Apple登入頁面
使用用者輸入Apple ID帳號密碼登入
登入成功
Apple畫面開始跳轉到redirect uri
3. Apple導向redirect uri(後端)並夾帶code
code是一個有"時效性"、"一次性"的暫時驗證碼
4. 後端用這個code發api跟Apple Server做驗證
驗證的API:https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
驗證API參數需要帶以下幾個東西
- client_id: Apple Sign In Console會有
- client_secret: 透過一些很麻煩的機制產生的JWT token, 下一段會講
- code: 前面登入成功後取得的code
- grant_type: authorization_code
- redirect_uri: 這個一定要符合前面的redirect uri, 不然Apple會擋掉
驗證成功後取得TokenResponse
5. 產生client secret
可查看此連結的Creating the Client Secret段落
主要是透過設定JWT的一些參數
- header的kid: Key ID, 就是secret key的Authkey_後的檔名
- payload的iss: 設定為team id
- payload的sub: client id
- payload的aud: https://appleid.apple.com
並使用ES256演算法產生
即可取得client secret發驗證code的API
6. 解開TokenResponse取得user的email
但是解開後有可能是隱藏的email
7. 自行依照專案的商業邏輯處理
取得email(或是隱藏的email)後
就可以自行依照專案的需求做處理
前端
載入apple sign in library
<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
觸發Apple ID登入
window.AppleID.auth.init({
clientId: 'client-id',
scope: 'name email',
redirectURI: 'https://foobar.com/your-return-url',
state: JSON.stringify({ foo: 'bar' }),
response_type: 'code',
})
window.AppleID.auth.signIn()
後端產生client secret
以laravel使用lcobucci/jwt這個jwt套件來說
大概是這樣產生client secret
<?php
public function createAppleClientSecretToken()
{
$signer = new \Lcobucci\JWT\Signer\Hmac\Sha256\Sha256();
$secret = file_get_contents(env('APPLE_ID_SECRET_PATH'));
$privateKey = new \Lcobucci\JWT\Signer\Key($secret);
$time = time();
$teamId = env('APPLE_ID_TEAM_ID');
$audId = 'https://appleid.apple.com';
$keyId = env('APPLE_ID_KEY_ID'); // (AuthKey後十碼)
$clientId = env('APPLE_ID_CLIENT');
$clientSecretToken = (new Builder())->issuedBy($teamId)
->permittedFor($audId)
->withClaim('sub', $clientId)
->issuedAt($time)
->expiresAt($time + 86400)
->withHeader('kid', $keyId)
->withHeader('alg', 'ES256')
->getToken($signer, $privateKey);
return $clientSecretToken->__toString();
}
撤銷Apple存取權
開發過程中可能需要不斷測試有無隱藏Email的狀況
因此需要從iphone撤銷App存取權
開啟iphone設定頁 > 點選最上方自己的姓名 > 密碼與帳號安全
選擇使用Apple ID的App
接著點選"停止使用Apple ID"
即可撤銷App存取權
推薦使用套件
https://github.com/patrickbussmann/oauth2-apple
用這個套件比較省事
不用自己在那邊組client secret發api驗證
推薦參考資料
- https://medium.com/@tuzaiz/如何整合-sign-in-with-apple-到自己的-ios-app-上-ios-backend-e64d9de15410
- https://medium.com/@yl.vic.liu/how-to-sign-in-with-apple-using-a-web-page-1a86f339ca94
- https://ms0680146.medium.com/laravel-apple-login-61772e52083b
- https://www.tech-prastish.com/blog/apple-sign-in-in-a-php-website/
- 官方client端設定文件
- 官方server驗證code文件