According to the documentation at https://developers.google.com/accounts/docs/OAuth2ServiceAccount%|%Using OAuth 2.0 for Server to Server Applications%|% === The signing algorithm in the JWT header must be used when computing the signature. The only signing algorithm supported by the Google OAuth 2.0 Authorization Server is RSA using SHA-256 hashing algorithm. This is expressed as ‘RS256’ in the ‘alg’ field in the JWT header. Sign the UTF-8 representation of the input using SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) with the private key obtained from the Google Cloud Console. The output will be a byte array. === What is there in the tcl space that is equivalent to `SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function)`? I was thinking that the `sha256` package would do the trick, but now I'm not so sure. Reason is that I took the signature block given on the developers.google.com page and did a `::base64::decode`. This gave me a string of assorted low and high ascii, which is not what I'm getting with a `::sha2::hmac` The goal is to be able to set up an OAuth2 connection to Google Analytics. I've already been to the https://cloud.google.com/console%|%Google Cloud Console%|% to set up the account, and get the various keys. The code I'm using is below. I'm still at the point where you generate the header. I haven't got to the HTTP stuff yet. ====== package require json package require sha256 package require base64 set h [open "client_secret.json" r] set d [read $h] close $h set mydd [dict create {*}[lindex [::json::json2dict $d] 1]] set header [string map {\n "" "=" ""} [::base64::encode "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"]] set claims [string map {\n "" "=" ""} [::base64::encode "{\ \"iss\":\"[dict get $mydd client_email]\",\ \"scope\":\"https://www.googleapis.com/auth/analytics.readonly\",\ \"aud\":\"https://accounts.google.com/o/oauth2/token\",\ \"exp\":[expr [clock seconds] + 3600],\ \"iat\":[clock seconds]\ }"]] set signature "$header.$claims" set h [open "privatekey.p12" r] fconfigure $h -translation binary set d [read $h] close $h set sig [string map {\n "" "=" ""} [::base64::encode [::sha2::hmac $d $signature]]] set final "$signature.$sig" puts $final ====== [APN] See if http://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/pki/pki.html#3%|%pki::sign%|% from the pki package in [tcllib] does what you want. [Bovine] We got this working, and the pki module was indeed the key: ====== package require yajltcl package require sha256 package require base64 package require http package require tls package require pki proc base64_url_encode {input} { return [string map {\n "" "=" "" + - / _} [::base64::encode $input]] } set header {{"alg":"RS256","typ":"JWT"}} set header [base64_url_encode $header] set x [yajl create #auto] $x map_open \ string iss string "this_is_my_identifier_here@developer.gserviceaccount.com" \ string scope string "https://www.googleapis.com/auth/prediction" \ string aud string "https://accounts.google.com/o/oauth2/token" \ string exp number [expr {[clock seconds] + 3600}] \ string iat number [clock seconds] \ map_close set claims [base64_url_encode [$x get]] $x delete set signature "$header.$claims" set fd [open "privatekey.pem" "r"] set keydata [read $fd] close $fd set key [::pki::pkcs::parse_key $keydata "this_is_my_pem_password"] set sig [base64_url_encode [::pki::sign $signature $key sha256]] set final "$signature.$sig" set postdata [::http::formatQuery grant_type "urn:ietf:params:oauth:grant-type:jwt-bearer" assertion $final] ::http::register https 443 ::tls::socket set fp [::http::geturl "https://accounts.google.com/o/oauth2/token" -query $postdata] set status [::http::status $fp] set ncode [::http::ncode $fp] set html [::http::data $fp] ::http::cleanup $fp array set token [::yajl::json2dict $html] parray token ====== [wiwo] The latest Google JSON credentials provide the key in PEM format. ::pki::parse_key expects the key in RSA format. Openssl to the rescue: ====== openssl rsa -in pk.key -out pk-rsa.key ====== <> Security