如果你的app只能通过微信、google、facebook等三方账号登录,则你的app也需要集成AppId登录,也就是Sign in with Apple。
1. 什么是 Sign in with Apple
Sign in with Apple是苹果在WWDC2019推出的,作用同微信登录一样,用户可以通过手机上的AppId账号登录别的应用。
Sign in with Apple支持iOS13以上的iOS手机,同时也支持网页端使用appId登录。
官方文档推荐:
WWDC2019 Sign In With Apple 视频
Sign in with Apple快速开始
Apple登录更新指南
2. 在苹果后台配置Sigin in with Apple相关证书
- 登录Apple开发者账号,点击
Certificates,Identifiers & Profiles
- 【添加appId】
- 选中左边的Identifiers之后,再点击右边Identifiers旁边的
+
号按钮 - 之后选中App IDs,再点击右上角的Continue
- 在下一页选择App,再点击右上角的Continue
- 来到Register an App ID页面,这里的Description随便输入,例如:mobile, BundleID这里就输入应用的包名,例如:com.wing.mobile。在Capabilities* 这里向下滑动页面到Sign In with Apple,然后将其勾选。再点击右上角的Continue
- 来到Confirm your App ID页面之后,直接点击右上角的Register
- 【添加Keys】
- 选中左边的Keys之后,再点击右边Keys旁边的
+
号按钮 - 来到Register a New Key页面,在key Name输入框输入:mobile sign in,勾选中Sign in with Apple并点击旁边的
Configure
- 来到Configure Key页面,点击下拉框选中com.wing.mobile,再点击右上角的Save
- 回到Register a New Key页面后直接点击右上角的Continue,之后再点击Register完成Keys的添加
- 点击Download下载你的key【注意:下载之后一定要备份,因为下载之后苹果后台就会把这个key删除掉】
- 记录下自己的Key ID,大概是V2ZJ2K4SMC这个样子
3. iOS客户端集成Sign in with Apple
前置条件
- iOS 13以上真机
- Xcode 11以上
- 电脑macos 10.15以上
工程配置
AppId登录代码
导入头文件:#import
- 添加登录按钮
- (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登录回调代理
#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(@"授权信息不符");
}
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error {
NSLog(@"[Wing] error = %@", error);
}
完整的ViewController.m代码如下,可直接拷贝到Demo项目中使用
#import "ViewController.h"
#import
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
}
/// 添加点击按钮
- (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登录回调
#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(@"授权信息不符");
}
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error {
NSLog(@"[Wing] error = %@", error);
}
4. Sign in with Apple服务端验证
服务端验证一共需要3个参数:
- client_id:也就是客户端的包名,本例中是:com.wing.mobile【
注意:
Web端的client_id和客户端是不一样的】 - client_secret:需要通过加密算法生成,最长有效期180天
- code:每次appId登录成功后客户端获取到的authorizationCode的data转成的字符串
client_secret生成
- 终端执行
sudo gem install jwt
安装jwt
- 添加下面需要的信息并将内容保存为
secret_gen.rb
require "jwt"
key_file = "Path to the private key" # 一个.p8文件,在添加Key时最后一步那个只能下载一次的文件
team_id = "Your Team ID" # 10个字节的字符串,可以在苹果账户后台中看到,位于右上角
client_id = "Bundle ID" # 客户端是bundleId,网页端是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
- 终端执行命令ruby secret_gen.rb运行secret_gen.rb,之后终端会输入
client_secret
curl 验证
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'
参考文章
- iOS开发:Sign In With Apple(使用Apple登录)
- 快速配置 Sign In with Apple