Web透過Apple ID登入

2021/03/26

Apple Console設定

 

首先前往Apple Console App的總覽頁

並前往Certificates, Indentifiers & Profiles頁

4.png

 

接著新增一個新的Identifiers選擇Services IDs類型

1.png

 

接著依序做基本設定

最後設定Web的網域、RedirectURI設定

3.png

 

接著前往Keys頁面建立全新的Key並保留好

後續會接著使用

5.png

 

2.png

 

比較麻煩的地方

有處理過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可以隱藏

hide-email.png

這點最麻煩

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

security.JPG

 

接著點選"停止使用Apple ID"

即可撤銷App存取權

manager-sign-in.JPG

 

推薦使用套件

https://github.com/patrickbussmann/oauth2-apple

用這個套件比較省事

不用自己在那邊組client secret發api驗證

 

推薦參考資料