#ios #scala #jwt #app-store-connect
Вопрос:
я хочу создать JWT в приложении scala для общения с API Apple AppStore Connect. я следую руководству здесь
я получаю неверную подпись на jwt.io при создании JWT с приведенным ниже кодом. запрос на подключение к appstore приводит к 401
я могу убедиться, что JWT правильно кодирует заголовок и полезную нагрузку на http://jwt.io
глядя на эту библиотеку, я думаю, что выбираю правильный алгоритм кривой:
После создания токена необходимо подписать его закрытым ключом, предоставленным Apple, с использованием алгоритма цифровой подписи с эллиптической кривой (ECDSA) с кривой P-256 и алгоритмом хэширования SHA-256, или ES256.
я не уверен, что не так — может быть, я неправильно генерирую S
значение?
def generateJWT(): String = {
val privateKeyBytes: Array[Byte] =
Base64.getDecoder.decode("base64 representation of private key")
val S = BigInt(privateKeyBytes)
val curveParams = ECNamedCurveTable.getParameterSpec("P-256")
val curveSpec: ECParameterSpec =
new ECNamedCurveSpec("P-256", curveParams.getCurve(), curveParams.getG(), curveParams.getN(), curveParams.getH());
val privateSpec = new ECPrivateKeySpec(S.underlying, curveSpec)
val privateKey =
KeyFactory.getInstance("EC").generatePrivate(privateSpec)
val unixTimestamp: Long = Instant.now.getEpochSecond
val fiveMins = unixTimestamp.toInt 300
val header = Map[String, Object](
"kid" -> "appstore connect Key Identifier",
"typ" -> "JWT",
"alg" -> "ES256"
)
val payload = Map[String, Object](
"iss" -> "issuer ID from the API Keys page in App Store Connect",
"aud" -> "appstoreconnect-v1",
"exp" -> new Integer(fiveMins)
)
Jwts
.builder()
.setHeaderParams(header.asJava)
.setClaims(payload.asJava)
.signWith(SignatureAlgorithm.ES256, privateKey)
.compact()
}
Комментарии:
1. где вы получили ошибку «недопустимая подпись»? Когда вы на самом деле использовали токен или просто когда вы его проверили jwt.io?
2. да, когда я проверял jwt.io. запрос на подключение к appstore дает 401. обновит мой вопрос
3. Когда вы проверяли jwt.io, вы предоставили открытый ключ? Или токен содержит достаточно информации (URL-адрес эмитента, идентификатор ключа), чтобы jwt.io можно ли получить открытый ключ из конечной точки? Pwoplw часто думают, что подпись недействительна, но, не зная открытого ключа, jwt.io не могу проверить.
4. я вижу, что заголовок и полезная нагрузка верны без предоставления открытого ключа. похоже, я не могу ввести открытый ключ, не введя также закрытый ключ на jwt.io и я не хотел этого делать
5. выберите алгоритм в раскрывающемся списке, затем вставьте открытый ключ в поле открытый ключ в правых столбцах и, наконец, вставьте маркер, созданный с помощью кода, в поле слева. Для этого вам действительно не нужен закрытый ключ.
Ответ №1:
Я могу предложить две вещи, чтобы попробовать:
JwtBuilder signWith(SignatureAlgorithm var1, Key var2)
является устаревшим. Можете ли вы попробовать использоватьJwtBuilder signWith(Key var1, SignatureAlgorithm var2)
и посмотреть , получится ли это?- Если нет, вы можете попробовать использовать bountycastle , который действительно работает для меня. Ниже приведен фрагмент кода для получения закрытого ключа.
def getPrivateKey(): PrivateKey = {
val pemParser = new PEMParser(new FileReader(<Your Apple-AuthKey file with extension .p8>))
val converter = new JcaPEMKeyConverter
val privateKeyInfo = pemParser.readObject.asInstanceOf[PrivateKeyInfo]
val pKey = converter.getPrivateKey(privateKeyInfo)
pemParser.close()
pKey
}
Комментарии:
1. как выглядит ваш build.sbt, чтобы получить эту зависимость?
2. я добавил
"org.bouncycastle" % "bcprov-jdk15on" % "1.68"
, но он не может найтиPEMParser
, например3. Это тот, с которым я связался. Я использую их напрямую через библиотеку Intellij и артефакты. «org.bouncycastle» % «bcpkix-jdk15on» % «1.68» Я вижу, что это единственная зависимость, связанная с bountycastle в моем проекте
4. Это «bcpkix», а не «bcprov» .
5. ты мой спаситель, спасибо тебе! для записи решение 2 сработало для меня!