三方登陆-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,其中code5分钟有效。然后访问服务端,服务端第一步验证客户端传入的identityToken是否有效。如果失败,则返回客户端;如果有效,再构造请求,带着code访问苹果服务,验证请求的合法性。下面详细描述下具体的实现。

获取苹果公钥

首先根据苹果开放的公钥构造PublicKey,这个key基本上是不变的,可以保存到本地,或者加到缓存里。具体作用是验证客户端传入的identityToken。这里我加了个缓存,仍然请求苹果公钥地址来生成。

  1. 公钥地址

https://appleid.apple.com/auth/keys

  1. 公钥内容示例
    实际内容在公钥地址可以取到,包括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_uriredirect_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, "验证失败");
}
 

参考资料

  1. jwt.io在线解析验证jwt
  2. Sign in with Apple REST API
  3. jwt信息校验介绍
  4. Sign in with Apple-苹果登录(客户端和服务端)
  5. Sign in with Apple(苹果授权登陆)服务端验证
  6. 苹果第三方登录Sign in with Apple服务端验证-非常详细
  7. 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
  8. https://www.jianshu.com/p/6dea3d12e3e8/

 



 
 
kid
posted @ 2022-11-04 16:30  逐星i  阅读(498)  评论(0编辑  收藏  举报