1、配置app套餐的Identifiers支持Sign In With Apple
如下圖

2、項目配置

3、集成代碼
主要步驟:
-
使用ASAuthorizationAppleIDButton創(chuàng)建button,布局,添加點擊事件;
-
實現(xiàn)點擊事件:授權(quán)請求
-
授權(quán)代理實現(xiàn)(授權(quán)成功,授權(quán)失敗)ASAuthorizationControllerDelegate
-
驗證
-
已經(jīng)Sign In with Apple登陸過app的用戶,處理
-
監(jiān)聽授權(quán)狀態(tài)改變
4、實現(xiàn)
使用ASAuthorizationAppleIDButton創(chuàng)建button,布局,添加點擊事件;
- (void)createView {
if (@available(iOS 13.0, *)) {
ASAuthorizationAppleIDButton *appleIDButton = [[ASAuthorizationAppleIDButton alloc] init];
appleIDButton.frame = CGRectMake(50, 100+CGRectGetHeight(self.view.frame) * 0.4, CGRectGetWidth(self.view.frame)-100, 50);
[appleIDButton addTarget:self action:@selector(appleIDButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:appleIDButton];
}
}

實現(xiàn)點擊事件:授權(quán)請求
- (void)appleIDButtonClicked API_AVAILABLE(ios(13.0)) {
//基于用戶的Apple ID授權(quán)用戶,生成用戶授權(quán)請求的一種機制
ASAuthorizationAppleIDProvider *provide = [[ASAuthorizationAppleIDProvider alloc] init];
//創(chuàng)建新的AppleID 授權(quán)請求
ASAuthorizationAppleIDRequest *request = provide.createRequest;
//在用戶授權(quán)期間請求的聯(lián)系信息
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
//由ASAuthorizationAppleIDProvider創(chuàng)建的授權(quán)請求 管理授權(quán)請求的控制器
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
//設(shè)置授權(quán)控制器通知授權(quán)請求的成功與失敗的代理
controller.delegate = self;
//設(shè)置提供 展示上下文的代理,在這個上下文中 系統(tǒng)可以展示授權(quán)界面給用戶
controller.presentationContextProvider = self;
//在控制器初始化期間啟動授權(quán)流
[controller performRequests];
}


授權(quán)代理實現(xiàn)(授權(quán)成功,授權(quán)失?。〢SAuthorizationControllerDelegate
驗證
#pragma mark - ASAuthorizationControllerDelegate
//授權(quán)成功的回調(diào)
/**
當(dāng)授權(quán)成功后,我們可以通過這個拿到用戶的 userID、email、fullName、authorizationCode、identityToken 以及 realUserStatus 等信息。
*/
-(void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
// 用戶登錄使用ASAuthorizationAppleIDCredential
ASAuthorizationAppleIDCredential *credential = authorization.credential;
//蘋果用戶唯一標(biāo)識符,該值在同一個開發(fā)者賬號下的所有 App 下是一樣的,開發(fā)者可以用該唯一標(biāo)識符與自己后臺系統(tǒng)的賬號體系綁定起來。
NSString *userId = credential.user;
NSString *state = credential.state;
NSPersonNameComponents *fullName = credential.fullName;
//蘋果用戶信息,郵箱
NSString *email = credential.email;
NSString *authorizationCode = [[NSString alloc] initWithData:credential.authorizationCode encoding:NSUTF8StringEncoding]; // refresh token
/**
驗證數(shù)據(jù),用于傳給開發(fā)者后臺服務(wù)器,然后開發(fā)者服務(wù)器再向蘋果的身份驗證服務(wù)端驗證本次授權(quán)登錄請求數(shù)據(jù)的有效性和真實性,詳見 Sign In with Apple REST API。如果驗證成功,可以根據(jù) userIdentifier 判斷賬號是否已存在,若存在,則返回自己賬號系統(tǒng)的登錄態(tài),若不存在,則創(chuàng)建一個新的賬號,并返回對應(yīng)的登錄態(tài)給 App。
*/
NSString *identityToken = [[NSString alloc] initWithData:credential.identityToken encoding:NSUTF8StringEncoding];
/**
用于判斷當(dāng)前登錄的蘋果賬號是否是一個真實用戶
取值有:unsupported、unknown、likelyReal。
*/
ASUserDetectionStatus realUserStatus = credential.realUserStatus;
// 存儲userId到keychain中,代碼省略
······
} else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
// 用戶登錄使用現(xiàn)有的密碼憑證
ASPasswordCredential *passwordCredential = authorization.credential;
// 密碼憑證對象的用戶標(biāo)識 用戶的唯一標(biāo)識
NSString *user = passwordCredential.user;
// 密碼憑證對象的密碼
NSString *password = passwordCredential.password;
_appleIDInfoTextView.text = [NSString stringWithFormat:@"%@",passwordCredential];
} else {
}
}
//失敗的回調(diào)
-(void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) {
}
#pragma mark - ASAuthorizationControllerPresentationContextProviding
//告訴代理應(yīng)該在哪個window 展示授權(quán)界面給用戶
-(ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)) {
return self.view.window;
}
已經(jīng)Sign In with Apple登陸過app的用戶
1、如果設(shè)備中存在iCloud Keychain憑證或者AppleID憑證,提示用戶直接使用TouchID或FaceID登錄即可。
2、新增ASAuthorizationPasswordRequest,如果 KeyChain 里面有登錄信息的話,可以直接使用里面保存的用戶名和密碼進行登錄。
- (void)perfomExistingAccountSetupFlows {
if (@available(iOS 13.0, *)) {
// 授權(quán)請求依賴于用于的AppleID
ASAuthorizationAppleIDRequest *authAppleIDRequest = [[ASAuthorizationAppleIDProvider new] createRequest];
// 為了執(zhí)行鑰匙串憑證分享生成請求的一種機制
ASAuthorizationPasswordRequest *passwordRequest = [[ASAuthorizationPasswordProvider new] createRequest];
NSMutableArray <ASAuthorizationRequest *> *mArr = [NSMutableArray arrayWithCapacity:2];
if (authAppleIDRequest) {
[mArr addObject:authAppleIDRequest];
}
if (passwordRequest) {
[mArr addObject:passwordRequest];
}
// ASAuthorizationRequest:對于不同種類授權(quán)請求的基類
NSArray <ASAuthorizationRequest *> *requests = [mArr copy];
// 由ASAuthorizationAppleIDProvider創(chuàng)建的授權(quán)請求 管理授權(quán)請求的控制器
ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:requests];
// 設(shè)置授權(quán)控制器通知授權(quán)請求的成功與失敗的代理
authorizationController.delegate = self;
// 設(shè)置提供 展示上下文的代理,在這個上下文中 系統(tǒng)可以展示授權(quán)界面給用戶
authorizationController.presentationContextProvider = self;
// 在控制器初始化期間啟動授權(quán)流
[authorizationController performRequests];
}
}
在 App 使用過程中,通過通知方法來監(jiān)聽 revoked 狀態(tài)
- (void)observeAppleSignInState {
if (@available(iOS 13.0, *)) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(handleSignInWithAppleStateChanged:) name:ASAuthorizationAppleIDProviderCredentialRevokedNotification object:nil];
}
}
// 觀察SignInWithApple狀態(tài)改變
- (void)handleSignInWithAppleStateChanged:(id)noti {
}
程序啟動時,監(jiān)聽授權(quán)狀態(tài)
用戶終止 App 中使用 Sign in with Apple 功能;
用戶在設(shè)置里注銷了 AppleId時
App 需要獲取到這些狀態(tài),然后做退出登錄操作,或者重新登錄。
我們需要在 App 啟動的時候,通過 getCredentialState:completion: 來獲取當(dāng)前用戶的授權(quán)狀態(tài)。
- (void)observeAuthticationState {
// 基于用戶的Apple ID 生成授權(quán)用戶請求的機制
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
// 注意 存儲用戶標(biāo)識信息需要使用鑰匙串來存儲 這里使用NSUserDefaults 做的簡單示例
NSString *userIdentifier = [[NSUserDefaults standardUserDefaults] valueForKey:@"ShareCurrentIdentifier"];
if (userIdentifier) {
// 在回調(diào)中返回用戶的授權(quán)狀態(tài)
[appleIDProvider getCredentialStateForUserID:userIdentifier completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
// 蘋果證書的授權(quán)狀態(tài)
switch (credentialState) {
case ASAuthorizationAppleIDProviderCredentialRevoked:
// 蘋果授權(quán)憑證失效
dispatch_async(dispatch_get_main_queue(), ^{
//做對應(yīng)處理
});
break;
case ASAuthorizationAppleIDProviderCredentialAuthorized:
// 蘋果授權(quán)憑證狀態(tài)良好
dispatch_async(dispatch_get_main_queue(), ^{
//做對應(yīng)處理
});
break;
case ASAuthorizationAppleIDProviderCredentialNotFound:
// 未發(fā)現(xiàn)蘋果授權(quán)憑證
// 可以引導(dǎo)用戶重新登錄
dispatch_async(dispatch_get_main_queue(), ^{
//做對應(yīng)處理
});
break;
default:
break;
}
}];
}
}
參考文章:
Sign In With Apple(一)
Sign In with Apple - 使用蘋果賬號登錄你的應(yīng)用
iOS 13 適配
Sign in with Apple
iOS 13-Sign In with Apple