Создание JWT в Coldfusion для учетной записи Сервиса Google - PullRequest
0 голосов
/ 05 декабря 2018

Я запутался в аспекте подписи для JWT.Я полагаю, что у меня есть правильный заголовок и утверждение, так как я получил все ошибки, которые я видел, когда писал эту статью.Мой вопрос в основном о подписи.Правильно ли работает HMac с HMACSHA256?Я думаю, что я не могу понять, где взять закрытый ключ для шифрования.Если у кого-то есть рекомендации, которые были бы хорошими.

<cfset JWT_header = structNew()>
<cfset JWT_header['alg'] = 'RS256'>
<cfset JWT_header['typ'] = 'JWT'>
<cfset JWT_header = serializeJSON(JWT_header)>

<cfset JWT_claim_set = structNew()>
<cfset JWT_claim_set['iss'] = 'secret_iss'>
<cfset JWT_claim_set['scope'] = 'my_scope'>
<cfset JWT_claim_set['aud'] = 'https://www.googleapis.com/oauth2/v4/token'>
<cfset JWT_claim_set['exp'] = 'Time_Stamp')>
<cfset JWT_claim_set['iat'] = 'Time_Stamp')>
<cfset JWT_claim_set = serializeJSON(JWT_claim_set)>

<cfset data = ToBase64(JWT_header) & '.' & ToBase64(JWT_claim_set)>

<cfset hashedData = HMac(data, 'my_secret_private_key','HMACSHA256')>

<cfset signature = toBase64(hashedData)>

<cfset JWT = data & '.' & signature>

<cfhttp url="https://www.googleapis.com/oauth2/v4/token" method="post" result="result">
    <cfhttpparam name="grant_type"          type="formField" value="urn:ietf:params:oauth:grant-type:jwt-bearer" />
    <cfhttpparam name="assertion"       type="formField" value="#JWT#" />
</cfhttp>

<cfoutput>#result.filecontent#</cfoutput>

Возвращает:

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

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Для тех, кому нужен код в будущем, чтобы он шел по правильному пути.Этот код используется для API-интерфейса обмена сообщениями Firebase для push-уведомлений, но может быть адаптирован для других служб Google.

<cfscript>
variables.service_json = deserializeJSON(fileRead(expandPath('./serviceaccountprivatekey.json')));


variables.timestamp = dateDiff("s", CreateDate(1970,1,1), now());
variables.timestampUTC = timestamp + 21600; //add 6 hour to convert to utc 

//generate jwt 
variables.jwt_header = {
    'alg': 'RS256',
    'typ': 'JWT'
};
variables.jwt_header = serializeJSON(variables.jwt_header);
variables.jwt_header = toBase64(variables.jwt_header);

variables.jwt_claim = {
    'iss': service_json.client_email,
    'scope': 'https://www.googleapis.com/auth/firebase.messaging',
    'aud': 'https://www.googleapis.com/oauth2/v4/token',
    'iat': timestampUTC,
    'exp': (timestampUTC + 3600)    
};
variables.jwt_claim = serializeJSON(variables.jwt_claim);
variables.jwt_claim = toBase64(variables.jwt_claim);

variables.jwt = variables.jwt_header & '.' & variables.jwt_claim;


//sign jwt

variables.keyText = reReplace( service_json.private_key, "-----(BEGIN|END)[^\r\n]+", "", "all" );
variables.keyText = trim( keyText );

variables.privateKeySpec = createObject( "java", "java.security.spec.PKCS8EncodedKeySpec" )
    .init(binaryDecode( variables.keyText, "base64" ));

variables.privateKey = createObject( "java", "java.security.KeyFactory" )
    .getInstance( javaCast( "string", "RSA" ) )
    .generatePrivate( privateKeySpec );

variables.signer = createObject( "java", "java.security.Signature" )
    .getInstance( javaCast( "string", 'SHA256withRSA' ));

variables.signer.initSign( variables.privateKey );
variables.signer.update( charsetDecode( variables.jwt, "utf-8" ) );
variables.signedBytes = signer.sign();
variables.signedBase64 = toBase64(signedBytes);


variables.jwt_signed = variables.jwt & '.' & variables.signedBase64;

</cfscript>

<cfhttp 
    url="https://www.googleapis.com/oauth2/v4/token"
    method="POST"
    result="res"
>
    <cfhttpparam name="grant_type" type="formField" value="urn:ietf:params:oauth:grant-type:jwt-bearer" />
    <cfhttpparam name="assertion" type="formField" value="#variables.jwt_signed#" />
</cfhttp>

<cfset variables.res = deserializeJSON(res.filecontent) />

<cfscript>
    variables.body = {
        "message": {
            "notification": {
                "title": "test",
                "body": "test test test"
            },
            "token": "e7blahblahSQ:thisisanexamplefirebasemessengingtokenpleaseputyourownonehere"
        }
    };
</cfscript>

<cfhttp url="https://fcm.googleapis.com/v1/projects/{project_id}/messages:send" method="post" result="res">
    <cfhttpparam type="header" name="Content-type" value="application/json" />
    <cfhttpparam type="header" name="Authorization" value="Bearer #variables.res.access_token#" />
    <cfhttpparam type="body" value="#serializeJSON(body)#" />
</cfhttp>

<cfdump var="#res.fileContent#">
0 голосов
/ 27 декабря 2018

Я получил это для работы с кодом Бена Наделя (https://www.bennadel.com/blog/2941-experimenting-with-rsa-encrypted-signature-generation-and-verification-in-coldfusion.htm),, но мне пришлось изменить его для работы. Я закомментировал все, что связано с открытым ключом, так как я не использовал его для взаимодействия с Google. ЕслиЯ должен был улучшить его, я мог бы создать логику для поиска использования открытого или закрытого ключа. Затем я пропустил что-либо с форматированием файла Pem, так как Google не использует это. Теперь это работает.

...