苹果授权登陆方式

  1. PC/M端授权登陆,采用协议类似于oauth2协议
  2. App端授权登陆,提供两种后端验证方式

开发者后台配置

详细配置参考该文档,手把手教学
https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple

1、 PC/M接入方式

  • https://appleid.apple.com/auth/authorize?response_type=code&client_id=&redirect_uri=&state=1234
  • 参考上面的后台配置,其中client_id对应的是Services ID,redirect_uri就是后台配置的接收code码的地址

2、APP端客户端授权登陆功能开发,可以参考如下文档

  • https://www.jianshu.com/p/23b46dea2076

重点讲解苹果授权登陆后端如何验证

针对后端验证苹果提供了两种验证方式,一种是基于JWT的算法验证,另外一种是基于授权码的验证

1、基于JWT的算法验证

  • 使用到的Apple公钥接口:https://appleid.apple.com/auth/keys
  • 详细接口文档说明参见:https://developer.apple.com/documentation/signinwithapplerestapi/fetch_apple_s_public_key_for_verifying_token_signature
  • 接口返回值:
{
"keys": [{"kty": "RSA", "kid": "AIDOPK1","use": "sig","alg": "RS256","n": "lxrwmuYSAsTfn-lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu_auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY-RNwCWdjNfEaY_esUPY3OVMrNDI15Ns13xspWS3q-13kdGv9jHI28P87RvMpjz_JCpQ5IM44oSyRnYtVJO-320SB8E2Bw92pmrenbp67KRUzTEVfGU4-obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd_JhmqX5CAaT9Pgi0J8lU_pcl215oANqjy7Ob-VMhug9eGyxAWVfu_1u6QJKePlE-w","e": "AQAB"}
]
}

kid,为密钥id标识,签名算法采用的是RS256(RSA 256 + SHA 256),kty常量标识使用RSA签名算法,其公钥参数为n和e,其值采用了BASE64编码,使用时需要先解码

  • 使用方式:APP内苹果授权登陆会提供如下几个参数:userID、email、fullName、authorizationCode、 identityToken

    • userID:授权的用户唯一标识
    • email、fullName:授权的用户资料
    • authorizationCode:授权code
    • identityToken:授权用户的JWT凭证

下面针对identityToken后端验证做简要说明:

  • identityToken参考样例:
// jwt 格式
eyJraWQiOiJBSURPUEsxIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLnNreW1pbmcuZGV2aWNlbW9uaXRvciIsImV4cCI6MTU2NTY2ODA4NiwiaWF0IjoxNTY1NjY3NDg2LCJzdWIiOiIwMDEyNDcuOTNiM2E3OTlhN2M4NGMwY2I0NmNkMDhmMTAwNzk3ZjIuMDcwNCIsImNfaGFzaCI6Ik9oMmFtOWVNTldWWTNkcTVKbUNsYmciLCJhdXRoX3RpbWUiOjE1NjU2Njc0ODZ9.e-pdwK4iKWErr_Gcpkzo8JNi_MWh7OMnA15FvyOXQxTx0GsXzFT3qE3DmXqAar96nx3EqsHI1Qgquqt2ogyj-lLijK_46ifckdqPjncTEGzVWkNTX8uhY7M867B6aUnmR7u-cf2HsmhXrvgsJLGp2TzCI3oTp-kskBOeCPMyTxzNURuYe8zabBlUy6FDNIPeZwZXZqU0Fr3riv2k1NkGx5MqFdUq3z5mNfmWbIAuU64Z3yKhaqwGd2tey1Xxs4hHa786OeYFF3n7G5h-4kQ4lf163G6I5BU0etCRSYVKqjq-OL-8z8dHNqvTJtAYanB3OHNWCHevJFHJ2nWOTT3sbw// header 解码
{"kid":"AIDOPK1","alg":"RS256"} 其中kid对应上文说的密钥id// claims 解码
{"iss":"https://appleid.apple.com","aud":"com.skyming.devicemonitor","exp":1565668086,"iat":1565667486,"sub":"001247.93b3a799a7c84c0cb46cd08f100797f2.0704","c_hash":"Oh2am9eMNWVY3dq5JmClbg","auth_time":1565667486
}其中 iss标识是苹果签发的,aud是接收者的APP ID,该token的有效期是10分钟,sub就是用户的唯一标识

如何验证?

首先通过identityToken中的header中的kid,然后结合苹果获取公钥的接口,拿到相应的n和e的值,然后通过下面这个方法构建RSA公钥public RSAPublicKeySpec build(String n, String e) {  BigInteger modulus = new BigInteger(1, Base64.decodeBase64(n));BigInteger publicExponent = new BigInteger(1, Base64.decodeBase64(e));return new RSAPublicKeySpec(modulus, publicExponent);
}通过下面这个方法验证JWT的有效性
public int verify(PublicKey key, String jwt, String audience, String subject) {                      JwtParser jwtParser = Jwts.parser().setSigningKey(key);              jwtParser.requireIssuer("https://appleid.apple.com");        jwtParser.requireAudience(audience);jwtParser.requireSubject(subject); try {Jws<Claims> claim = jwtParser.parseClaimsJws(jwt);if (claim != null && claim.getBody().containsKey("auth_time")) {  return GlobalCode.SUCCESS;            }           return GlobalCode.THIRD_AUTH_CODE_INVALID;} catch (ExpiredJwtException e) { log.error("apple identityToken expired", e);return GlobalCode.THIRD_AUTH_CODE_INVALID;} catch (Exception e) {log.error("apple identityToken illegal", e);return GlobalCode.FAIL_ILLEGAL_REQ;}
}使用的JWT工具库为:
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>

2、基于授权码的后端验证

  • 首先需要了解如何构建client_secret,详细文档可以参考如下两个:
  • https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple
  • https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens

首先说下client_secret的构建方法:

先在后台生成授权应用APP ID的密钥KEY文件,然后下载密钥文件格式样例:-----BEGIN PRIVATE KEY-----BASE64编码后的密钥
-----END PRIVATE KEY-----public  byte[] readKey() throws Exception {String temp = "密钥文件中间的编码字符串";return Base64.decodeBase64(temp);
}构建client_secret关键代码:String client_id = "..."; // 被授权的APP ID
Map<String, Object> header = new HashMap<String, Object>();
header.put("kid", "密钥id"); // 参考后台配置
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("iss", "team id"); // 参考后台配置 team id
long now = System.currentTimeMillis() / 1000;
claims.put("iat", now);
claims.put("exp", now + 86400 * 30); // 最长半年,单位秒
claims.put("aud", "https://appleid.apple.com"); // 默认值
claims.put("sub", client_id);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(readKey());
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
String client_secret = Jwts.builder().setHeader(header).setClaims(claims).signWith(SignatureAlgorithm.ES256, privateKey).compact();

如何验证?

String url = "https://appleid.apple.com/auth/token";
// POST 请求
HttpSynClient client = new HttpSynClient(5000, 5000, 5000, 20);
Map<String, String> form = new HashMap<String, String>();
form.put("client_id", client_id);
form.put("client_secret", client_secret);
form.put("code", code);form.put("grant_type","authorization_code");
form.put("redirect_uri", redirectUrl);
HttpResponse result = client.excutePost(url, form);
System.out.println(result);

返回值样例:

{"access_token":"a0996b16cfb674c0eb0d29194c880455b.0.nsww.5fi5MVC-i3AVNhddrNg7Qw",
"token_type":"Bearer",
"expires_in":3600,
"refresh_token":"r9ee922f1c8b048208037f78cd7dfc91a.0.nsww.KlV2TeFlTr7YDdZ0KtvEQQ",
"id_token":"eyJraWQiOiJBSURPUEsxIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLnNreW1pbmcuYXBwbGVsb2dpbmRlbW8iLCJleHAiOjE1NjU2NjU1OTQsImlhdCI6MTU2NTY2NDk5NCwic3ViIjoiMDAwMjY2LmRiZTg2NWIwYWE3MjRlMWM4ODM5MDIwOWI5YzdkNjk1LjAyNTYiLCJhdF9oYXNoIjoiR0ZmODhlX1ptc0pqQ2VkZzJXem85ZyIsImF1dGhfdGltZSI6MTU2NTY2NDk2M30.J6XFWmbr0a1hkJszAKM2wevJF57yZt-MoyZNI9QF76dHfJvAmFO9_RP9-tz4pN4ua3BuSJpUbwzT2xFD_rBjsNWkU-ZhuSAONdAnCtK2Vbc2AYEH9n7lB2PnOE1mX5HwY-dI9dqS9AdU4S_CjzTGnvFqC9H5pt6LVoCF4N9dFfQnh2w7jQrjTic_JvbgJT5m7vLzRx-eRnlxQIifEsHDbudzi3yg7XC9OL9QBiTyHdCQvRdsyRLrewJT6QZmi6kEWrV9E21WPC6qJMsaIfGik44UgPOnNnjdxKPzxUAa-Lo1HAzvHcAX5i047T01ltqvHbtsJEZxAB6okmwco78JQA"
}

其中id_token是一个JWT,其中claims中的sub就是授权的用户唯一标识,该token也可以使用上述的验证方法进行有效性验证,另外授权code是有时效性的,且使用一次即失效

苹果AppId登录注册相关推荐

  1. Axure经典实例高保真交互下载(微信元件高保真交互库+微信原型交互+安卓设备模板含登录注册引导欢迎流程+ios苹果设备模板)

    作品介绍:原型内容包括:微信小程序原件库.视觉规范.基础组件.操作反馈.导航搜索.ios机型设备模板.常用元素.安卓手机设备模板包含注册登录.欢迎引导页等 Axure兼容版本:8.0 和9.0 Axu ...

  2. Apple Sign in with Apple(苹果授权登录PHP)

    Apple Sign in with Apple(苹果授权登录PHP) 文章目录 Apple Sign in with Apple(苹果授权登录PHP) 一.登录Apple Developer 二.创 ...

  3. 苹果授权登录 jwt node 解码

    苹果授权登录 jwt node 解码 const jwt_decode = require('jwt-decode') const NodeRSA = require('node-rsa'); con ...

  4. php微信网页开发实现自动登录注册功能实例

    功能:自动登录注册功能 描述:php实现微信网页自动登录注册功能 范围:适用于所有php版本 功能实例 $token = $_COOKIE['wechat_token']; if($token){// ...

  5. 苹果手机怎么创建php,怎么在苹果官网注册Apple ID?在网页上创建Apple ID教程

    如何在网页上创建Apple ID呢?Apple ID账号是苹果手机上面常常使用的一个账号,很多人可能注册时都是在苹果手机上面注册Apple ID账号的,其实除了苹果手机注册以外,我们还可以直接通过网页 ...

  6. 苹果开发者账号注册申请流程

    苹果开发者账号的注册过程比较复杂,和大家分享一下过程和细节,以免大家走了弯路. 1.登陆苹果开发者官网页面 https://developer.apple.com/programs/ios/ 2.点击 ...

  7. Sign In with Apple - 使用苹果账号登录你的应用

    编辑:老峰,作者:KANGZUBIN 来源:小专栏<WWDC19 内参> 苹果在 9 月 12 号更新了审核指南,加入 4.8 Sign in with Apple 一条,要求所有使用 第 ...

  8. 2017最新苹果 APPLE ID注册流程

    不管你是苹果开发者还是苹果爱好者,只要你手中有苹果的终端(IPHONE .IPAD .ITouch,MAC电脑) 你想用苹果的一些服务,你就必须要申请苹果APPLE ID,才能享受到苹果提供高品质的服 ...

  9. 2015年最新苹果开发者账号注册流程详解

    苹果开发者账号的注册过程比较复杂,和大家分享一下过程和细节,以免大家走了弯路. 1.登陆苹果开发者官网页面 https://developer.apple.com/programs/ios/ 2.点击 ...

  10. 2016年最新苹果开发者账号注册流程详解(公司账号篇)

    随着苹果规定金融/理财类应用需要使用公司开发者账号上传,并进一步加大对此类问题的审核力度,公司开发者账号开始呈现出炙手可热之势! 不过,公司开发者账号的注册流程着实复杂--不仅要填写公司的D-U-N- ...

最新文章

  1. 最全整理 | 万字长文综述目标检测领域,您要的,都在这里!
  2. 毕业设计:Springboot实现疫情宿舍学生管理系统
  3. spoon kettle连接数据库失败解决方法
  4. WinAPI: Pie - 绘制饼图
  5. mysql死锁释放时间参数_由FTWRL导致的MySQL从库死锁分析及参数深究
  6. 微软MCITP系列课程(八)文件服务器及磁盘配额
  7. oracle 取第三大的值,Oracle 常见的几种访问提取数据的方式!
  8. 如何卸载bytefence anti-malware
  9. php+中午截取,php中截取中文字符串的代码小结
  10. tkinter 实现简单登录窗
  11. Android SQLite封装sql语句、查看数据库
  12. 如何将MID音乐转换成MP3
  13. Jenkinsfile脚本实现master、slave节点(agent)共享内容
  14. Python教学视频(五)顺序结构练习
  15. java中nextToken,Java StringTokenizer nextToken()用法及代碼示例
  16. 《实用软件工程答案》张海涛人民邮电出版社
  17. openmp多线程简单编程
  18. matlab输出的特征向量,关于matlab中的eig函数(求特征值和特征向量)(最新整理)
  19. 《数据结构》实验三:栈和队列实验 (实验报告)
  20. Inspection info: Reports octal integer literals. Some coding standards prohibit the use of octal...

热门文章

  1. opencv面试知识点
  2. 南华大学计算机科学学院,南华大学计算机科学与技术学院介绍
  3. css中aspect,CSS属性之aspect-ratio
  4. BW数据加载后不能实时刷新到水晶易表解决方法
  5. 电脑桌面简约时钟工具OneClock
  6. python实现——40W告警日志分析(上)
  7. 如何“延迟加载”嵌入式YouTube视频
  8. 排序系列(代码c++版)
  9. 从python入门机器学习系列--2、Z 检验与 T 检验
  10. 带通滤波器作用和用途_什么是带通滤波器?工作原理及原理图详解