iOS DeviceCheck API持续返回400:授权令牌缺失或格式错误
iOS DeviceCheck API 400错误:授权令牌缺失或格式错误
调用iOS DeviceCheck API时持续收到400错误,提示「Missing or badly formatted authorization token」(授权令牌缺失或格式错误),无论从本地服务器还是直接从App调用都存在该问题。
请求示例
curl --location 'https://api.development.devicecheck.apple.com/v1/query_two_bits' \ --header 'Authorization: Bearer <<JWT-token>>' \ --header 'Content-Type: application/json' \ --data '{ "device_token": Token_fetched_from_Device_Check, "transaction_id":"c6bdb659-0ee6-443d-88cb-a8f036dfc551", "timestamp": 1721300244267 }'
参数说明
device_token:通过DeviceCheck框架生成JWT-token:使用Apple开发者门户生成的.p8文件密钥、对应keyId及团队ID(个人开发者账号)生成
已尝试的排查步骤
- 创建.p8密钥时已启用Device Check选项
- 等待密钥激活超过7小时后再调用API
- 使用DeviceCheck框架生成的全新device_token进行测试
DeviceCheck令牌生成代码
if curDevice.isSupported{ DCDevice.current.generateToken { (data, error) in if let data = data { } } }
初始JWT令牌生成代码
func createJWTToken(privateKey: String, keyID: String, teamID: String) -> String? { // Set up the JWT header var jwtHeader = Header() jwtHeader.kid = keyID // Set up the JWT claims let jwtClaims = MyClaims(iss: teamID, iat: Date()) // Create the JWT var jwt = JWT(header: jwtHeader, claims: jwtClaims) // Convert the private key to Data guard let privateKeyData = Data(base64Encoded: privateKey) else { print("Invalid private key") return nil } // Sign the JWT let jwtSigner = JWTSigner.es256(privateKey: privateKeyData) do { let signedJWT = try jwt.sign(using: jwtSigner) return signedJWT } catch { print("Failed to sign JWT: \(error)") return nil } }
问题仍未解决,恳请提供技术建议。
更新:检查多语言JWT生成代码是否存在问题
Python方法
import jwt import time import uuid def generate_jwt(private_key, key_id, team_id): headers = { "alg": "ES256", "kid": key_id, } payload = { "iss": team_id, "iat": int(time.time()), "exp": int(time.time()) + 3600, # Token valid for 1 hour } token = jwt.encode(payload, private_key, algorithm="ES256", headers=headers) return token # Load your private key with open('AuthKey_abc.p8', 'r') as key_file: private_key = key_file.read() key_id = "########" # Replace with your Key ID team_id = "#########" # Replace with your Team ID jwt_token = generate_jwt(private_key, key_id, team_id).decode('utf-8') transaction_id = str(uuid.uuid4()) timestamp = int(time.time() * 1000) print("JWT Token:", jwt_token) print("Transaction ID:", transaction_id) print("Timestamp:", timestamp)
Swift代码
import SwiftJWT func createJWTToken(privateKey: String, keyID: String, teamID: String) -> String? { // Set up the JWT header var jwtHeader = Header() jwtHeader.kid = keyID // Set up the JWT claims let jwtClaims = MyClaims(iss: teamID, iat: Date()) // Create the JWT var jwt = JWT(header: jwtHeader, claims: jwtClaims) // Convert the private key to Data guard let privateKeyData = Data(base64Encoded: privateKey) else { print("Invalid private key") return nil } // Sign the JWT let jwtSigner = JWTSigner.es256(privateKey: privateKeyData) do { let signedJWT = try jwt.sign(using: jwtSigner) return signedJWT } catch { print("Failed to sign JWT: \(error)") return nil } } func readFileFromBundle(fileName: String, fileType: String) -> String? { if let fileURL = Bundle.main.url(forResource: fileName, withExtension: fileType) { do { // Read the file contents let privateKey = try String(contentsOf: fileURL, encoding: .utf8) // Clean the private key by removing header, footer, and whitespace/newlines let cleanedKey = privateKey .replacingOccurrences(of: "-----BEGIN PRIVATE KEY-----", with: "") .replacingOccurrences(of: "-----END PRIVATE KEY-----", with: "") .replacingOccurrences(of: "\n", with: "") .replacingOccurrences(of: "\r", with: "") .trimmingCharacters(in: .whitespacesAndNewlines) return cleanedKey } catch { print("Error reading private key: \(error)") return nil } } else { print("Private key file not found") return nil } }
Node.js代码
const privateKey = fs.readFileSync('AuthKey_abc.p8', 'utf8'); const payload = { iss: teamId, iat: curTime, exp: curTime + 3600 // 1 hour expiration }; // Prepare the JWT headers const headers = { kid: keyId, alg: 'ES256' }; // Create and sign the JWT var jwToken = jwt.sign(payload, privateKey, { header: headers }); console.log(jwToken)
内容的提问来源于stack exchange,提问作者Suryakant Sharma
相关产品推荐
相关产品推荐

