Как я могу вычислить подпись OAuth для учетной записи службы? - PullRequest
0 голосов
/ 04 апреля 2019

Я хочу получить токен доступа к учетной записи службы для API Google с помощью метода HTTP / REST, но OAuth отправляет мне ошибку в подписи.Я использую Java.

Я получил следующую строку JSON:

{
    "error": "invalid_grant",
    "error_description": "Invalid JWT Signature."
}

Как я понимаю, в документации мне нужно составить JWT (JSON Web Token) с заголовком,набор претензий и подпись.Мне удалось получить правильный заголовок и набор утверждений, но, очевидно, мои подписные вычисления неверны.

Мой импорт:

import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.Security;
import java.security.PrivateKey;

Вот заголовок вычисления:

String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
byte[] bytes = header.getBytes();
header = Base64.getEncoder().encodeToString(bytes);

Моя заявка установлена ​​:

long time_milis = System.currentTimeMillis()/1000L;
String claim_set = "{\n"
     + "  \"iss\":\"something@something.iam.gserviceaccount.com\",\n"
     + "  \"scope\":\"https://www.googleapis.com/auth/devstorage.read_write\",\n"
     + "  \"aud\":\"https://www.googleapis.com/oauth2/v4/token\",\n"
     + "  \"exp\":" + (time_milis + 300) + ",\n"
     + "  \"iat\":" + time_milis + "\n"
     + "}";
bytes = claim_set.getBytes();
claim_set = Base64.getEncoder().encodeToString(bytes);

Будьте готовы к моей подписи попытки!(по понятным причинам безопасности я замаскировал закрытый ключ):

String signature = header + "." + claim_set;
String privateKeyString = "-----BEGIN PRIVATE KEY-----\nturlututu123\n-----END PRIVATE KEY-----\n";
privateKeyString = private_key.replaceAll("-----END PRIVATE KEY-----", "").replaceAll("-----BEGIN PRIVATE KEY-----", "").replaceAll("\n", "");

Signature privateSignature = Signature.getInstance("SHA256withRSA");

KeyFactory keyFactory=KeyFactory.getInstance("RSA");

PrivateKey privateKey = keyFactory.generatePrivate(
    new PKCS8EncodedKeySpec(
        Base64.getDecoder().decode(privateKeyString)
    )
);

privateSignature.initSign(privateKey);

privateSignature.update(signature.getBytes("UTF-8"));
bytes = privateSignature.sign();
signature = Base64.getEncoder().encodeToString(bytes);

Я отправляю свой запрос в https://www.googleapis.com/oauth2/v4/token в режиме POST со следующим заголовком:

"Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded"

и в теле:

"grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=" + header + "." + claim_set + "." + signature

Я действительно застрял и не знаю, как двигаться дальше.

1 Ответ

1 голос
/ 05 апреля 2019

Наконец-то я нашел ответ!Это была проблема кодирования.Фактически, когда я кодирую свои строки, я вызываю кодировщик Base64.getEncoder() вместо кодировщика Base64.getUrlEncoder().Теперь мы можем изменить все сценарии.

Вот заголовок :

String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
byte[] bytes = header.getBytes();
header = Base64.getUrlEncoder().encodeToString(bytes);

Мой набор заявок :

long time_milis = System.currentTimeMillis()/1000L;
String claim_set = "{\n"
     + "  \"iss\":\"something@something.iam.gserviceaccount.com\",\n"
     + "  \"scope\":\"https://www.googleapis.com/auth/devstorage.read_write\",\n"
     + "  \"aud\":\"https://www.googleapis.com/oauth2/v4/token\",\n"
     + "  \"exp\":" + (time_milis + 300) + ",\n"
     + "  \"iat\":" + time_milis + "\n"
     + "}";
bytes = claim_set.getBytes();
claim_set = Base64.getUrlEncoder().encodeToString(bytes);

И подпись (по понятным причинам безопасности я замаскировал закрытый ключ):

String signature = header + "." + claim_set;
String privateKeyString = "-----BEGIN PRIVATE KEY-----\nturlututu123\n-----END PRIVATE KEY-----\n";
privateKeyString = private_key.replaceAll("-----END PRIVATE KEY-----", "").replaceAll("-----BEGIN PRIVATE KEY-----", "").replaceAll("\n", "");

Signature privateSignature = Signature.getInstance("SHA256withRSA");

KeyFactory keyFactory=KeyFactory.getInstance("RSA");

PrivateKey privateKey = keyFactory.generatePrivate(
    new PKCS8EncodedKeySpec(
        Base64.getDecoder().decode(privateKeyString)
    )
);

privateSignature.initSign(privateKey);

privateSignature.update(signature.getBytes("UTF-8"));
bytes = privateSignature.sign();
signature = Base64.getUrlEncoder().encodeToString(bytes);

Спасибо этой записи , которая помогает мне во время отладки.

...