三方登陆-apple
1.apple web登陆配置
2.配置
3.官方文档
https://help.apple.com/developer-account/?lang=zh-cn#/devde676e696 (登陆配置)
https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple
https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens (apple的jwt验证参数生成)
一、 apple web登陆配置
配置回调url
二、AppleId登录 后台服务器验证
流程描述
实际的可以参考苹果官网的示意图:
简单描述下。首先,客户使用SDK访问苹果服务,获取到用户信息。主要会得到一个identityToken
(jwt)和code
,其中code
5分钟有效。然后访问服务端,服务端第一步验证客户端传入的identityToken
是否有效。如果失败,则返回客户端;如果有效,再构造请求,带着code
访问苹果服务,验证请求的合法性。下面详细描述下具体的实现。
获取苹果公钥
首先根据苹果开放的公钥构造PublicKey
,这个key基本上是不变的,可以保存到本地,或者加到缓存里。具体作用是验证客户端传入的identityToken
。这里我加了个缓存,仍然请求苹果公钥地址来生成。
- 公钥地址
https://appleid.apple.com/auth/keys
- 公钥内容示例
实际内容在公钥地址可以取到,包括kid,算法名称,模数,指数等。
{
"keys": [
{
"kty": "RSA",
"kid": "86D88Kf",
"use": "sig",
"alg": "RS256",
"n": "iGaLq...",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "eXaunmL",
"use": "sig",
"alg": "RS256",
"n": "4dGQ7bQK..."
"e": "AQAB"
}
]
}
### ymal 配置
``
#三方登陆验证
auth:
apple:
teamId: xxx
kid: xxx
clientId: com.studyxapp.www
privateKey: xxx
redirectUri: xxx
## apple安卓要注意
andriodRedirectUri: https://xxxx
```
三、 authorizationCode验证,生成和验证token
官方文档: Generate and validate tokens
1. 生成client_secret
client_secret
是一个JSON对象,它包含一个header和playload。头包含以下参数
参数 | 类型 | 是否必填 | 描述 | 实例值 |
---|---|---|---|---|
alg | String | 是 | 算法类型 | ES256 |
kid | String | 是 | 开发者标识符密钥 | AXXXX |
iss | String | 是 | 开发者team ID | BXXXXX |
iat | String | 是 | 生成claim时间戳 | 1437179938 |
exp | String | 是 | claim过期时间(最长生命周期180天) | 1493298904 |
aud | String | 是 | claim key | https://appleid.apple.com |
sub | String | 是 | 开发者的APP ID | com.xxx.xxx |
四、验证授权授予代码
当您向验证服务器发送授权请求时,请包含以下表单数据参数:
-
client_id 标识符id
-
client_secret jwt生成的
-
code 前端授权返回
-
grant_type
-
redirect_uri
笔记
使用您的应用授权用户时,仅当应用在初始授权请求中提供 a 时才包含该参数。redirect_uri
redirect_uri
以下是通过以下方式的示例授权验证请求 URL :cURL
curl -v POST "https://appleid.apple.com/auth/token" \-H 'content-type: application/x-www-form-urlencoded' \-d 'client_id=CLIENT_ID' \-d 'client_secret=CLIENT_SECRET' \-d 'code=CODE' \-d 'grant_type=authorization_code' \-d 'redirect_uri=REDIRECT_URI'
服务器验证授权码后,端点返回身份令牌、访问令牌和刷新令牌。以下是授权验证响应示例:
{ "access_token": "adg61...67Or9", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "rca7...lABoQ" "id_token": "eyJra...96sZg"}
使用刷新令牌从服务器验证用户会话并获取访问令牌。
jwt代码
public static String buildJwt(String iss, String clientId , String kid) { Map<String, Object> header = new HashMap<>(); header.put("alg", SignatureAlgorithm.ES256.getValue()); //SHA256withECDSA header.put("kid", kid); long iat = System.currentTimeMillis() / 1000; //以秒为单位 Map<String, Object> claims = new HashMap<>(); claims.put("iss", iss); claims.put("iat", iat); claims.put("exp", iat + Days.SEVEN.toStandardSeconds().getSeconds()); //设置为7天过期 claims.put("aud","https://appleid.apple.com"); //固定值
claims.put("sub", clientId); return new DefaultJwtBuilder().setHeader(header).setClaims(claims).signWith(getPrivateKey(), SignatureAlgorithm.ES256).compact();
}
/**
* 验证客户端identityToken参数
*
* @param jwt
* @return
*/
public static Pair<Boolean, String> verify(String jwt) {
AppleIdentityToken identityToken = null;
try {
identityToken = getAppleIdentityToken(jwt);
PublicKey publicKey = cache.getUnchecked(identityToken.getHeader().getKid());
if (null == publicKey) {
return Pair.of(false, "系统异常");
}
JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(publicKey)
.requireAudience("com.xxx.www") //一般是项目包名称
.requireIssuer("https://appleid.apple.com") //固定值
.require("auth_time", identityToken.getIat()) //这里做了个简单的验证,如果auth_time == iat则是有效的。
.build();
Jws<Claims> claimsJws = jwtParser.parseClaimsJws(jwt);
Claims claims = claimsJws.getBody();
//验证是否过期,
if (!claims.getExpiration().before(new Date()) && StringUtils.isNotBlank(identityToken.getSub())) {
log.error("ios verify fail. exp:{}", claims.getExpiration());
return Pair.of(true, identityToken.getSub());
}
} catch (Exception e) {
log.error("verify jwt error token:{}.", identityToken, e);
}
return Pair.of(false, "验证失败");
}
参考资料
- jwt.io在线解析验证jwt
- Sign in with Apple REST API
- jwt信息校验介绍
- Sign in with Apple-苹果登录(客户端和服务端)
- Sign in with Apple(苹果授权登陆)服务端验证
- 苹果第三方登录Sign in with Apple服务端验证-非常详细
- https://blog.csdn.net/wpf199402076118/article/details/99677412?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EESLANDING%7Edefault-3-99677412-blog-118340500.pc_relevant_multi_platform_whitelistv4eslandingrelevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EESLANDING%7Edefault-3-99677412-blog-118340500.pc_relevant_multi_platform_whitelistv4eslandingrelevant&utm_relevant_index=4
- https://www.jianshu.com/p/6dea3d12e3e8/
kid