iOS 實現(xiàn)蘋果第三方登錄

Sign in with Apple

Provide users the ability to sign in to your apps and websites using their Apple ID.

Overview

Sign in with Apple gives your users a fast and safe way to sign in to your apps and websites using their Apple ID. Incorporating Sign in with Apple eliminates the need for additional sign-up steps, allowing users to engage and focus on your app or website.

To support Sign in with Apple for websites, you must integrate Sign in with Apple JS. Use the Sign in with Apple REST API to communicate with Apple servers. For native iOS, macOS, tvOS, and watchOS apps, use the AuthenticationServices framework.

簡介

Sign In with Apple登錄支持的最低iOS系統(tǒng)要求是iOS13娩梨,凡是包含第三方登錄功能的App奥务,必須帶有蘋果登錄功能傲霸,且樣式需要滿足蘋果要求,并需要把蘋果登錄放在所有第三方登錄的前面企巢,也就是說要放在第一個位置上斩启,上架應用被要求添加蘋果登錄功能的最終截止時間不詳综慎。不過可以肯定的是窗宦,在7月30日我提交了審核,8月1日被拒了咏闪,原因就是沒有添加蘋果登錄功能程剥。

image.png
image.png

蘋果提供文檔之Implementing User Authentication with Sign in with Apple
蘋果提供文檔之Sign in with Apple
蘋果提供文檔之Human Interface Guidelines

實現(xiàn)

  • 1、登錄蘋果開發(fā)者后臺汤踏,把需要添加蘋果登錄Identifiers的項目打開登錄開關
image.png

保存后织鲸,下載.p8文件,文件下載完要保存好溪胶,因為只提供一次下載機會搂擦。

  • 2、添加key
image.png

添加完可以直接在下面的頁面看到keyID和teamID哗脖,都復制一下瀑踢,后面需要用到

image.png
  • 3、打開項目才避,按照下圖中1橱夭、2步添加Sign In with Apple
image.png
  • 4、到登錄頁面添加代碼
    導入系統(tǒng)頭文件#import <AuthenticationServices/AuthenticationServices.h>
    實現(xiàn)兩個代理方法ASAuthorizationControllerDelegateASAuthorizationControllerPresentationContextProviding
    添加蘋果登錄按鈕桑逝,按鈕ASAuthorizationAppleIDButton是系統(tǒng)提供的棘劣,只要實現(xiàn)了兩個代理就能輕松獲取登錄用戶的信息,代碼如下:

按鈕布局

if (@available(iOS 13.0, *)) {
                    
    ASAuthorizationAppleIDButton *appleButon = [[ASAuthorizationAppleIDButton alloc]initWithAuthorizationButtonType:ASAuthorizationAppleIDButtonTypeSignIn authorizationButtonStyle:ASAuthorizationAppleIDButtonStyleBlack];
    appleButon.cornerRadius = 30.f;
    [appleButon addTarget:self action:@selector(appleSignAction) forControlEvents:UIControlEventTouchUpInside];
    [view addSubview:appleButon];
    [appleButon mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.right.mas_equalTo(0);
        make.height.mas_equalTo(view.mas_width);
    }];
                    
}

代理方法

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization NS_SWIFT_NAME(authorizationController(controller:didCompleteWithAuthorization:)) API_AVAILABLE(ios(13.0)){
    
    if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]])       {
        ASAuthorizationAppleIDCredential *credential = authorization.credential;
        
        NSLog(@"credential = %@",credential);
        
        NSString *state = credential.state;
        NSString *userID = credential.user;
        NSPersonNameComponents *fullName = credential.fullName;
        NSString *email = credential.email;
        NSString *authorizationCode = [[NSString alloc] initWithData:credential.authorizationCode encoding:NSUTF8StringEncoding]; // 驗證 token
        NSString *identityToken = [[NSString alloc] initWithData:credential.identityToken encoding:NSUTF8StringEncoding]; // 用戶 token
        ASUserDetectionStatus realUserStatus = credential.realUserStatus;
        NSArray *authorizedScopes = credential.authorizedScopes;
        
        NSLog(@"state: %@\nuserID: %@\nfullName: %@\nemail: %@\nauthorizationCode: %@\nidentityToken: %@\nrealUserStatus: %@\nauthorizedScopes: %@",
              state,
              userID,
              fullName,
              email,
              authorizationCode,
              identityToken,
              @(realUserStatus),
              authorizedScopes);
    
}

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error  NS_SWIFT_NAME(authorizationController(controller:didCompleteWithError:)) API_AVAILABLE(ios(13.0)){
    
    NSString *errorMsg = nil;
    switch (error.code) {
        case ASAuthorizationErrorCanceled:
            errorMsg = @"用戶取消了授權請求";
            break;
        case ASAuthorizationErrorFailed:
            errorMsg = @"授權請求失敗";
            break;
        case ASAuthorizationErrorInvalidResponse:
            errorMsg = @"授權請求響應無效";
            break;
        case ASAuthorizationErrorNotHandled:
            errorMsg = @"未能處理授權請求";
            break;
        case ASAuthorizationErrorUnknown:
            errorMsg = @"授權請求失敗未知原因";
            break;
    }
    
}

- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){
    return self.window;
}

-(void)appleSignAction{
    
    if (@available(iOS 13.0, *)) {
        
        ASAuthorizationAppleIDProvider *provider = [[ASAuthorizationAppleIDProvider alloc] init];
        ASAuthorizationAppleIDRequest *request = [provider createRequest];
        request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
        
        ASAuthorizationController *vc = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
        vc.delegate = self;
        vc.presentationContextProvider = self;
        [vc performRequests];
        
    }
    
}

后端驗證

  • 1楞遏、前端獲取到Apple ID的用戶信息后茬暇,需要把code傳給后端,后端再調用蘋果的驗證接口進行驗證寡喝,通過驗證接口返回的數(shù)據(jù)進行校驗(此處省略一萬字)...code是什么呢糙俗?code就是前端獲取到的authorizationCode

  • 2、蘋果驗證接口:https://appleid.apple.com/auth/token

必傳參數(shù)

client_id:app的 bundle identifier
code:手機端獲取到的 authorizationCode
grant_type:傳入固定字符串 authorization_code
client_secret:秘鑰

  • 3预鬓、秘鑰client_secret的生成

使用ruby代碼生成client_secret巧骚,對于ruby應該不會陌生,就算ruby代碼不會寫(我也不會寫格二,代碼是copy的)劈彪,至少也知道這個東西,畢竟使用pod管理代碼的前提是必須安裝ruby環(huán)境??

ruby代碼如下:

require "jwt"

key_file = "Path to the private key"
team_id = "Your Team ID"
client_id = "Your App Bundle ID"
key_id = "The Key ID of the private key"
validity_period = 180 # In days. Max 180 (6 months) according to Apple docs.

private_key = OpenSSL::PKey::EC.new IO.read key_file

token = JWT.encode(
  {
    iss: team_id,
    iat: Time.now.to_i,
    exp: Time.now.to_i + 86400 * validity_period,
    aud: "https://appleid.apple.com",
    sub: client_id
  },
  private_key,
  "ES256",
  header_fields=
  {
    kid: key_id 
  }
)
puts token

參數(shù)說明

key_file:蘋果開發(fā)者中心下載的.p8文件(實現(xiàn)-1步驟中提到的)保存的路徑
team_id:開發(fā)者賬號的teamID(實現(xiàn)-2步驟中提到的)
client_id:項目的bundleID
key_id:蘋果開發(fā)者中心創(chuàng)建的keyID(實現(xiàn)-2步驟中提到的)

在上面的ruby中蟋定,有看到引入jwt粉臊,那么還需要你的Mac安裝jwt環(huán)境草添。
打開終端驶兜,輸入命令:sudo gem install jwt安裝jwt環(huán)境,安裝完成后,桌面創(chuàng)建一個文件夾抄淑,并在終端cd到該文件目錄下屠凶,然后輸入命令:touch secret_gen.rb創(chuàng)建.rb文件,創(chuàng)建完成雙擊打開該文件肆资,把上面的ruby代碼復制黏貼進去矗愧,并修改key_fileteam_id郑原、client_id唉韭、key_id這四個keyvalue,保存文件犯犁,秘鑰client_secret就生成了属愤。

其實client_secret大可不必由前端來生成,完全可以由后端同事自己去搞酸役,奈何實在是太想裝逼的我想要嘚瑟一把(此處省略一萬字)...

好了住诸,到此為止,后端完成了蘋果的驗證之后涣澡,后續(xù)業(yè)務該怎么玩怎么玩了贱呐,其實關于Sign In with Apple登錄的文章一搜一大把,說來說去主要重點就是這么點東西入桂,可能部分細節(jié)我這里沒有實現(xiàn)奄薇,但是重點就是這些。

全劇終

2020-8-26 補充 Apple登錄成功案例之一

(深沉厚重的背景獨白抗愁,自己配音)事情發(fā)生在2020年7月30號的早上7點09分惕艳,還記得那是第一次因為Apple登錄的問題被蘋果拒絕審核通過……剎那間,仿佛過了許多個日日夜夜……咳咳驹愚,不扯淡了远搪,哈哈哈哈

  • 時間是7月30號第一次被拒,原因是未添加Apple第三方登錄逢捺,由于是初次實現(xiàn)該功能谁鳍,所以用的時間比較長吧,到了8月4號劫瞳,已經完全實現(xiàn)了Apple登錄功能倘潜,只不過需要和后臺對接的相關處理還沒搞定,也是因為后臺的功能還沒有實現(xiàn)志于,呵涮因!垃圾……
時間.png

不小心暴露了上班時間,好吧伺绽,我們公司是6.30下班的

  • 頁面顯示
登錄頁面.png

看到了吧养泡,登錄頁面就是上面這個樣子的了

補充信息頁面.png

登錄成功后需要用戶補充郵箱和手機號碼

image.png

最后的提審時間是8月25號上午11點46分

image.png

8月25號晚上23點45分通過審核

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末嗜湃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子澜掩,更是在濱河造成了極大的恐慌购披,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肩榕,死亡現(xiàn)場離奇詭異刚陡,居然都是意外死亡,警方通過查閱死者的電腦和手機株汉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門筐乳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乔妈,你說我怎么就攤上這事哥童。” “怎么了褒翰?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵贮懈,是天一觀的道長。 經常有香客問我优训,道長朵你,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任揣非,我火速辦了婚禮抡医,結果婚禮上,老公的妹妹穿的比我還像新娘早敬。我一直安慰自己忌傻,他們只是感情好,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布搞监。 她就那樣靜靜地躺著水孩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琐驴。 梳的紋絲不亂的頭發(fā)上俘种,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音绝淡,去河邊找鬼宙刘。 笑死,一個胖子當著我的面吹牛牢酵,可吹牛的內容都是我干的悬包。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼馍乙,長吁一口氣:“原來是場噩夢啊……” “哼布近!你這毒婦竟也來了垫释?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吊输,失蹤者是張志新(化名)和其女友劉穎饶号,沒想到半個月后铁追,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體季蚂,經...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年琅束,在試婚紗的時候發(fā)現(xiàn)自己被綠了扭屁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡涩禀,死狀恐怖料滥,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情艾船,我是刑警寧澤葵腹,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站屿岂,受9級特大地震影響践宴,放射性物質發(fā)生泄漏。R本人自食惡果不足惜爷怀,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一阻肩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧运授,春花似錦烤惊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至逗宜,卻和暖如春伦泥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锦溪。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工不脯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刻诊。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓防楷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親则涯。 傳聞我的和親對象是個殘疾皇子复局,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354