如果你的app只能通過微信、google、facebook等三方賬號登錄,則你的app也需要集成AppId登錄,也就是Sign in with Apple。
1. 什么是 Sign in with Apple
Sign in with Apple是蘋果在WWDC2019推出的,作用同微信登錄一樣,用戶可以通過手機(jī)上的AppId賬號登錄別的應(yīng)用。
Sign in with Apple支持iOS13以上的iOS手機(jī),同時也支持網(wǎng)頁端使用appId登錄。
官方文檔推薦:
WWDC2019 Sign In With Apple 視頻
Sign in with Apple快速開始
Apple登錄更新指南
2. 在蘋果后臺配置Sigin in with Apple相關(guān)證書

image.png
-
登錄Apple開發(fā)者賬號,點(diǎn)擊
Certificates,Identifiers & Profiles
image.png - 【添加appId】
- 選中左邊的Identifiers之后,再點(diǎn)擊右邊Identifiers旁邊的
+號按鈕 - 之后選中App IDs,再點(diǎn)擊右上角的Continue
- 在下一頁選擇App,再點(diǎn)擊右上角的Continue
- 來到Register an App ID頁面,這里的Description隨便輸入,例如:mobile, BundleID這里就輸入應(yīng)用的包名,例如:com.wing.mobile。在Capabilities* 這里向下滑動頁面到Sign In with Apple,然后將其勾選。再點(diǎn)擊右上角的Continue
- 來到Confirm your App ID頁面之后,直接點(diǎn)擊右上角的Register
- 【添加Keys】
- 選中左邊的Keys之后,再點(diǎn)擊右邊Keys旁邊的
+號按鈕 - 來到Register a New Key頁面,在key Name輸入框輸入:mobile sign in,勾選中Sign in with Apple并點(diǎn)擊旁邊的
Configure - 來到Configure Key頁面,點(diǎn)擊下拉框選中com.wing.mobile,再點(diǎn)擊右上角的Save
- 回到Register a New Key頁面后直接點(diǎn)擊右上角的Continue,之后再點(diǎn)擊Register完成Keys的添加
- 點(diǎn)擊Download下載你的key【注意:下載之后一定要備份,因?yàn)橄螺d之后蘋果后臺就會把這個key刪除掉】
- 記錄下自己的Key ID,大概是V2ZJ2K4SMC這個樣子
3. iOS客戶端集成Sign in with Apple
前置條件
- iOS 13以上真機(jī)
- Xcode 11以上
- 電腦macos 10.15以上
工程配置

添加Sign in with Apple.png
AppId登錄代碼
導(dǎo)入頭文件:#import <AuthenticationServices/AuthenticationServices.h>
- 添加登錄按鈕
- (void)setupUI {
ASAuthorizationAppleIDButton *btn = [ASAuthorizationAppleIDButton buttonWithType:ASAuthorizationAppleIDButtonTypeSignIn style:ASAuthorizationAppleIDButtonStyleBlack];
btn.frame = CGRectMake(50, 150, 200, 50);
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- 當(dāng)點(diǎn)擊登錄按鈕時請求appId登錄
- (void)btnClick:(UIButton *)btn {
if (@available(iOS 13.0, *)) {
ASAuthorizationAppleIDProvider *provider = [ASAuthorizationAppleIDProvider new];
ASAuthorizationAppleIDRequest *request = provider.createRequest;
request.requestedScopes = @[ASAuthorizationScopeEmail, ASAuthorizationScopeFullName];
ASAuthorizationController *vc = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
vc.delegate = self;
vc.presentationContextProvider = self;
[vc performRequests];
}
}
- 實(shí)現(xiàn)AppId登錄回調(diào)代理
#pragma mark - ASAuthorizationControllerDelegate
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization {
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
ASAuthorizationAppleIDCredential *credential = authorization.credential;
NSString *user = credential.user;
NSData *identifyToken = credential.identityToken;
NSData *authCode = credential.authorizationCode;
NSString *codeStr = [[NSString alloc] initWithData:authCode encoding:NSUTF8StringEncoding];
NSLog(@"user = %@, authCode = %@", user, codeStr);
} else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
ASPasswordCredential *credential = authorization.credential;
NSLog(@"password = %@", credential.password);
} else {
NSLog(@"授權(quán)信息不符");
}
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error {
NSLog(@"[Wing] error = %@", error);
}
完整的ViewController.m代碼如下,可直接拷貝到Demo項(xiàng)目中使用
#import "ViewController.h"
#import <AuthenticationServices/AuthenticationServices.h>
@interface ViewController ()<ASAuthorizationControllerDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
}
/// 添加點(diǎn)擊按鈕
- (void)setupUI {
ASAuthorizationAppleIDButton *btn = [ASAuthorizationAppleIDButton buttonWithType:ASAuthorizationAppleIDButtonTypeSignIn style:ASAuthorizationAppleIDButtonStyleBlack];
btn.frame = CGRectMake(50, 150, 200, 50);
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
/// 請求appId登錄
- (void)btnClick:(UIButton *)btn {
if (@available(iOS 13.0, *)) {
ASAuthorizationAppleIDProvider *provider = [ASAuthorizationAppleIDProvider new];
ASAuthorizationAppleIDRequest *request = provider.createRequest;
request.requestedScopes = @[ASAuthorizationScopeEmail, ASAuthorizationScopeFullName];
ASAuthorizationController *vc = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
vc.delegate = self;
vc.presentationContextProvider = self;
[vc performRequests];
}
}
/// AppId登錄回調(diào)
#pragma mark - ASAuthorizationControllerDelegate
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization {
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
ASAuthorizationAppleIDCredential *credential = authorization.credential;
NSString *user = credential.user;
NSData *identifyToken = credential.identityToken;
NSData *authCode = credential.authorizationCode;
NSString *codeStr = [[NSString alloc] initWithData:authCode encoding:NSUTF8StringEncoding];
NSLog(@"user = %@, authCode = %@", user, codeStr);
} else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
ASPasswordCredential *credential = authorization.credential;
NSLog(@"password = %@", credential.password);
} else {
NSLog(@"授權(quán)信息不符");
}
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error {
NSLog(@"[Wing] error = %@", error);
}
4. Sign in with Apple服務(wù)端驗(yàn)證
服務(wù)端驗(yàn)證一共需要3個參數(shù):
- client_id:也就是客戶端的包名,本例中是:com.wing.mobile【
注意:Web端的client_id和客戶端是不一樣的】 - client_secret:需要通過加密算法生成,最長有效期180天
- code:每次appId登錄成功后客戶端獲取到的authorizationCode的data轉(zhuǎn)成的字符串
client_secret生成
- 終端執(zhí)行
sudo gem install jwt安裝jwt - 添加下面??需要的信息并將內(nèi)容保存為
secret_gen.rb
require "jwt"
key_file = "Path to the private key" # 一個.p8文件,在添加Key時最后一步那個只能下載一次的文件
team_id = "Your Team ID" # 10個字節(jié)的字符串,可以在蘋果賬戶后臺中看到,位于右上角
client_id = "Bundle ID" # 客戶端是bundleId,網(wǎng)頁端是servicesId
key_id = "The Key ID of the private key" # V2ZJ2K4SMC
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
- 終端執(zhí)行命令ruby secret_gen.rb運(yùn)行secret_gen.rb,之后終端會輸入
client_secret
curl 驗(yàn)證
curl -v POST "https://appleid.apple.com/auth/token" \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'client_id=com.match.woohoo' \
-d 'client_secret=eyJraWQiOiJNMzQ5RDZVNDY2IiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJGU0hYV1c2NjhTIiwiaWF0IjoxNjE2MTMyOTE5LCJleHAiOjE2MzE2ODQ5MTksImF1ZCI6Imh0dHBzOi8vYXBwbGVpZC5hcHBsZS5jb20iLCJzdWIiOiJjb20ubWF0Y2gud29vaG9vIn0.zFWtXv1CCZ3KTgSWoiARYlowZjbUon_cMuHZQZg36eAcsxgIxGBCWWZXqRVZxa2fil0ipguRIZF28AjXi3APGw' \
-d 'code=c9755915369ad47169813487f0e6c1ea2.0.rrwrv.ZWwChKXLiTlh1lsXHvlC3A' \
-d 'grant_type=authorization_code'
