我试图实现的目标:
- iOS客户端将JWT令牌发送到后端.
- 后端(Java)调用 appleid.apple/auth/token验证令牌.
- iOS client sends a JWT token to the backend.
- Backend (Java) calls appleid.apple/auth/token to verify the token.
我到目前为止有什么:
拨打Apple验证电话:
to make Apple verification call:
restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); map.add("client_id", clientId); // app_id like com.app.id String token = generateJWT(); // generated jwt map.add("client_secret", token); map.add("grant_type", "authorization_code"); map.add("code", authorizationCode); // JWT code we got from iOS HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers); final String appleAuthURL = "appleid.apple/auth/token"; String response = restTemplate.postForObject(appleAuthURL, request, String.class);代币生成:
final PrivateKey privateKey = getPrivateKey(); final int expiration = 1000 * 60 * 5; String token = Jwts.builder() .setHeaderParam(JwsHeader.KEY_ID, keyId) // key id I got from Apple .setIssuer(teamId) .setAudience("appleid.apple") .setSubject(clientId) // app id com.app.id .setExpiration(new Date(System.currentTimeMillis() + expiration)) .setIssuedAt(new Date(System.currentTimeMillis())) .signWith(SignatureAlgorithm.ES256, privateKey) // ECDSA using P-256 and SHA-256 pact(); return token;从文件中获取我的私钥:
to get my private key from the file:
final Reader pemReader = new StringReader(getKeyData()); final PEMParser pemParser = new PEMParser(pemReader); final JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); final PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject(); final PrivateKey pKey = converter.getPrivateKey(object);我确认我的JWT具有所有必填字段:
I confirmed my JWT has all required fields:
{ "kid": "SAME KEY AS MY KEY ID", "alg": "ES256" } { "iss": "Blahblah", "aud": "appleid.apple", "sub": "com.app.id", "exp": 1578513833, "iat": 1578513533 }推荐答案
此行引起了我的注意:
map.add("code", authorizationCode); // JWT code we got from iOSauthorizationCode不是jwt
JSON Web令牌由3个部分组成,这些部分由点分隔
JSON Web Tokens consist of 3 parts separated by dots
,但是authorizationCode具有以下4个部分:
but the authorizationCode has 4 parts like this:
text1.text2.0.text3您可能正在使用iOS应用中的identityToken而不是authorizationCode
You are probably using the identityToken from the iOS app instead of the authorizationCode
这是您检索它的方式:
let authorizationCode = String(data: appleIDCredential.authorizationCode!, encoding: .utf8)! print("authorizationCode: \(authorizationCode)")对于那些在遇到相同的invalid_client错误后可能会来到这里的人,也要谨记以下几点:
Also good to have the following in mind for those who might come here after getting the same invalid_client error:
孩子是来自developer.apple/account/resources/authkeys/list
kid is the id for the private key from developer.apple/account/resources/authkeys/list
keyFile是保存从developer.apple
keyFile is the file holding the private key downloaded from developer.apple
teamID,可以在右上角看到teamID
teamID can be found by logging in to developer.apple and clicking on account, the teamID can be seen in the upper right corner
以aud为单位的值应为 appleid.apple
the value in aud should be appleid.apple
app_id是应用程序的捆绑包标识符
app_id is the bundle identifier for the app
以防万一,在python中,这是一个可行的解决方案,用于创建client_secret:
In case it might help, here is a working solution in python to create a client_secret:
# $ pip install pyjwt import jwt import time kid = "myKeyId" keyFile = "/pathToFile/AuthKey.p8" key = "" with open(keyFile, 'r') as myFile: key = myFile.read() print(key) timeNow = int(round(time.time())) time3Months = timeNow + 86400*90 claims = { 'iss': teamID, 'iat': timeNow, 'exp': time3Months, 'aud': 'appleid.apple', 'sub': app_id, } secret = jwt.encode(claims, key, algorithm='ES256', headers={'kid': kid}) print("secret:") print(secret) client_secret = secret.decode("utf-8") print(client_secret)更多推荐
使用Apple登录的invalid
发布评论