<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic JSON Web Signature (JWS) - JSON Web Token (JWT) to call Google API (Server-Server) - proc groovy? in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/JSON-Web-Signature-JWS-JSON-Web-Token-JWT-to-call-Google-API/m-p/227322#M40953</link>
    <description>&lt;P&gt;I am using SAS 9.4. I want to write a JSON Web Signature ("JWS") to complete my JSON Web Token ("JWT") - (I already have the header and claims encoded and tested). I would like to make API calls to Google (Server to Server API). My problem is that I am not certain how to create the JWS. Per all the docs and tutorial web sites I have researched the syntax to create the signature is (pseudo-code):&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;encodedContent = base64UrlEncode(header) + "." + base64UrlEncode(payload);signature = hashHmacSHA256($encodedContent);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;and/or&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);HMACSHA256(encodedString,&lt;STRONG&gt; 'secret'&lt;/STRONG&gt;);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;etc.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have been attempting to create the JWS using SAS PROC GROOVY code found here:&amp;nbsp;&lt;A href="https://gist.github.com/FriedEgg/79ad315afa1b315e8ac3" target="_blank"&gt;https://gist.github.com/FriedEgg/79ad315afa1b315e8ac3&lt;/A&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;...and other places.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Google's doc (&lt;A href="https://developers.google.com/identity/protocols/OAuth2ServiceAccount" target="_blank"&gt;https://developers.google.com/identity/protocols/OAuth2ServiceAccount&lt;/A&gt;) states: "Sign the UTF-8 representation of the input ('{Base64url encoded header}.{Base64url encoded claim set}') using SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) &lt;STRONG&gt;with the private key&lt;/STRONG&gt; obtained from the Google Developers Console. The output will be a byte array."&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;However, I am confused about what &lt;STRONG&gt;"key"&lt;/STRONG&gt;&amp;nbsp;to use (or whether I should be using a key) as some sites (example above) just suggest hashing the encoded header+claims while others suggest hashing using a &lt;STRONG&gt;"secret key"&lt;/STRONG&gt; while others say &lt;STRONG&gt;"private key"&lt;/STRONG&gt; - and the github page (URL above) just states&amp;nbsp;&lt;STRONG&gt;"key"&lt;/STRONG&gt;.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="line-height: 20px;"&gt;I am also confused about sha1 vs. sha256. The Google docs state sha256 but some have suggested sha1 in this Stack Overflow thread: &lt;A href="http://stackoverflow.com/questions/18362327/creating-digital-signature-usining-sas-for-google-api-geocode" target="_blank"&gt;http://stackoverflow.com/questions/18362327/creating-digital-signature-usining-sas-for-google-api-geocode&lt;/A&gt; . I do note a related question where FriedEgg suggested writing a perl module to use sha256 (&amp;nbsp;&lt;A href="https://communities.sas.com/t5/Base-SAS-Programming/Connecting-to-amazon-web-service/m-p/35555/highlight/true#M7036" target="_blank"&gt;https://communities.sas.com/t5/Base-SAS-Programming/Connecting-to-amazon-web-service/m-p/35555/highlight/true#M7036&lt;/A&gt; ) but we do not currently have perl installed on our SAS server and our admins have the x/execute commands in SAS disabled for security purposes.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Again, I have verified my header and claims (encoded in SAS) are&amp;nbsp;working using:&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;jwt.io&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;kjur.github.io/jsjws/tool_jwt.html.&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Since SAS supports Groovy (PROC GROOVY) I assume that I can write my JWS successfully using java code but I have not yet been able to replicate any &lt;SPAN&gt;JW&lt;/SPAN&gt;&lt;SPAN&gt;S&lt;/SPAN&gt; in my SAS code using examples found on the sites I have mentioned above and others.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Has anyone ever done this before (using SAS to connect to Google APIs using JWT)?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any help is appreciated!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Fri, 25 Sep 2015 18:22:24 GMT</pubDate>
    <dc:creator>blueblueskies</dc:creator>
    <dc:date>2015-09-25T18:22:24Z</dc:date>
    <item>
      <title>JSON Web Signature (JWS) - JSON Web Token (JWT) to call Google API (Server-Server) - proc groovy?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/JSON-Web-Signature-JWS-JSON-Web-Token-JWT-to-call-Google-API/m-p/227322#M40953</link>
      <description>&lt;P&gt;I am using SAS 9.4. I want to write a JSON Web Signature ("JWS") to complete my JSON Web Token ("JWT") - (I already have the header and claims encoded and tested). I would like to make API calls to Google (Server to Server API). My problem is that I am not certain how to create the JWS. Per all the docs and tutorial web sites I have researched the syntax to create the signature is (pseudo-code):&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;encodedContent = base64UrlEncode(header) + "." + base64UrlEncode(payload);signature = hashHmacSHA256($encodedContent);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;and/or&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);HMACSHA256(encodedString,&lt;STRONG&gt; 'secret'&lt;/STRONG&gt;);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;etc.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have been attempting to create the JWS using SAS PROC GROOVY code found here:&amp;nbsp;&lt;A href="https://gist.github.com/FriedEgg/79ad315afa1b315e8ac3" target="_blank"&gt;https://gist.github.com/FriedEgg/79ad315afa1b315e8ac3&lt;/A&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;...and other places.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Google's doc (&lt;A href="https://developers.google.com/identity/protocols/OAuth2ServiceAccount" target="_blank"&gt;https://developers.google.com/identity/protocols/OAuth2ServiceAccount&lt;/A&gt;) states: "Sign the UTF-8 representation of the input ('{Base64url encoded header}.{Base64url encoded claim set}') using SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) &lt;STRONG&gt;with the private key&lt;/STRONG&gt; obtained from the Google Developers Console. The output will be a byte array."&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;However, I am confused about what &lt;STRONG&gt;"key"&lt;/STRONG&gt;&amp;nbsp;to use (or whether I should be using a key) as some sites (example above) just suggest hashing the encoded header+claims while others suggest hashing using a &lt;STRONG&gt;"secret key"&lt;/STRONG&gt; while others say &lt;STRONG&gt;"private key"&lt;/STRONG&gt; - and the github page (URL above) just states&amp;nbsp;&lt;STRONG&gt;"key"&lt;/STRONG&gt;.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="line-height: 20px;"&gt;I am also confused about sha1 vs. sha256. The Google docs state sha256 but some have suggested sha1 in this Stack Overflow thread: &lt;A href="http://stackoverflow.com/questions/18362327/creating-digital-signature-usining-sas-for-google-api-geocode" target="_blank"&gt;http://stackoverflow.com/questions/18362327/creating-digital-signature-usining-sas-for-google-api-geocode&lt;/A&gt; . I do note a related question where FriedEgg suggested writing a perl module to use sha256 (&amp;nbsp;&lt;A href="https://communities.sas.com/t5/Base-SAS-Programming/Connecting-to-amazon-web-service/m-p/35555/highlight/true#M7036" target="_blank"&gt;https://communities.sas.com/t5/Base-SAS-Programming/Connecting-to-amazon-web-service/m-p/35555/highlight/true#M7036&lt;/A&gt; ) but we do not currently have perl installed on our SAS server and our admins have the x/execute commands in SAS disabled for security purposes.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Again, I have verified my header and claims (encoded in SAS) are&amp;nbsp;working using:&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;jwt.io&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;kjur.github.io/jsjws/tool_jwt.html.&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Since SAS supports Groovy (PROC GROOVY) I assume that I can write my JWS successfully using java code but I have not yet been able to replicate any &lt;SPAN&gt;JW&lt;/SPAN&gt;&lt;SPAN&gt;S&lt;/SPAN&gt; in my SAS code using examples found on the sites I have mentioned above and others.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Has anyone ever done this before (using SAS to connect to Google APIs using JWT)?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any help is appreciated!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 25 Sep 2015 18:22:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/JSON-Web-Signature-JWS-JSON-Web-Token-JWT-to-call-Google-API/m-p/227322#M40953</guid>
      <dc:creator>blueblueskies</dc:creator>
      <dc:date>2015-09-25T18:22:24Z</dc:date>
    </item>
    <item>
      <title>Re: JSON Web Signature (JWS) - JSON Web Token (JWT) to call Google API (Server-Server) - proc groovy</title>
      <link>https://communities.sas.com/t5/SAS-Programming/JSON-Web-Signature-JWS-JSON-Web-Token-JWT-to-call-Google-API/m-p/227708#M41048</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/56136"&gt;@blueblueskies﻿&lt;/a&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I updated the gist you mentioned to add support for JWT. &amp;nbsp;I made use of the JAVA library&amp;nbsp;&lt;A href="https://github.com/auth0/java-jwt" target="_blank"&gt;java-jwt&lt;/A&gt;&amp;nbsp;and added support for SHA256withRSA.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Example for PROC GROOVY:&lt;/P&gt;&lt;P&gt;&lt;A href="https://gist.github.com/FriedEgg/79ad315afa1b315e8ac3#file-sha256withrsa-jwt4sas-sas" target="_blank"&gt;https://gist.github.com/FriedEgg/79ad315afa1b315e8ac3#file-sha256withrsa-jwt4sas-sas&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Github Repository for my fork of JAVA-JWT:&lt;/P&gt;&lt;P&gt;&lt;A href="https://github.com/FriedEgg/java-jwt" target="_blank"&gt;https://github.com/FriedEgg/java-jwt&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;and the JAR:&lt;/P&gt;&lt;P&gt;&lt;A href="https://github.com/FriedEgg/java-jwt/releases/download/java-jwt-2.1.2/java-jwt-2.1.1-SNAPSHOT.jar" target="_blank"&gt;https://github.com/FriedEgg/java-jwt/releases/download/java-jwt-2.1.2/java-jwt-2.1.1-SNAPSHOT.jar&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;filename jwt '/path/to/java-jwt-2.1.2-SNAPSHOT.jar';

filename cp temp;

proc groovy classpath=cp;

add classpath=jwt;
/* test *//*
submit;
import java.security.KeyFactory
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.RSAPrivateKeySpec;
import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.Algorithm;
modulus = new BigInteger("AB34D0D48B16438BBBDFF6DA0CC7D3936DC2CE71E89DEF5B4AA9EA2539EAC17B5765FAAF2C533D176AF95CF16F157FECB977F51DE6E5473808E95A487321A3AB", 16);
privateExponent = new BigInteger("0FEA1CEF64EE70E0F059E54C679BBBA31CB4DB13E397AAC445B07DBF701ECE554DE0266E99B96CE8F3148291551E70357E5AF29FB192FB9E5C2F4AA5C45A0141", 16);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus,privateExponent);
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyFactory.generatePrivate(rsaPrivateKeySpec);
signer = new JWTSigner(rsaPrivateKey);
HashMap&amp;lt;String, Object&amp;gt; claims = new HashMap&amp;lt;String, Object&amp;gt;();
String token = signer.sign(claims, new JWTSigner.Options().setAlgorithm(Algorithm.RS256));
println token
endsubmit;
*/

submit load;
import java.security.KeyFactory
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.RSAPrivateKeySpec;
import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.Algorithm;

public class Jwt4SAS {
   private JWTSigner signer;
   private HashMap&amp;lt;String, Object&amp;gt; claims = new HashMap&amp;lt;String, Object&amp;gt;();

   public Jwt4SAS(String modulus, String privateExponent) {
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
	  RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(
	     new BigInteger(modulus, 16),
		 new BigInteger(privateExponent, 16)
	  );
      RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyFactory.generatePrivate(rsaPrivateKeySpec);
	  signer = new JWTSigner(rsaPrivateKey);
   }

   public void addClaim(String key, String value) {
      this.claims.put(key, value);
   }

   public String sign() {
      return signer.sign(claims, new JWTSigner.Options().setAlgorithm(Algorithm.RS256));
   }
}
endsubmit;

quit;

options set=classpath "%sysfunc(pathname(cp,f))";

data x;
dcl javaObj jwt4sas('Jwt4SAS',
   'AB34D0D48B16438BBBDFF6DA0CC7D3936DC2CE71E89DEF5B4AA9EA2539EAC17B5765FAAF2C533D176AF95CF16F157FECB977F51DE6E5473808E95A487321A3AB',
   '0FEA1CEF64EE70E0F059E54C679BBBA31CB4DB13E397AAC445B07DBF701ECE554DE0266E99B96CE8F3148291551E70357E5AF29FB192FB9E5C2F4AA5C45A0141');

jwt4sas.callVoidMethod('addClaim','sub','123456789');
jwt4sas.callVoidMethod('addClaim','name','John Doe');

length jwt $ 2048;
Jwt4SAS.callStringMethod('sign',jwt);

jwt = strip(jwt);
put jwt=;

array enc[3] $ 1024 encodedHeader encodedPayload signedData;
do _n_=1 to dim(enc);
   enc[_n_]=scan(jwt,_n_,'.');
end;

length header payload $ 1024;
header = input(encodedHeader,$base64x1024.);
payload = input(encodedPayload,$base64x1024.);

put (encodedHeader  header ) (=/) //
    (encodedPayload payload) (=/) //
	signedData=;
run;

/*http://jwt.io*/&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Instructions to generate a RSA key using OpenSSL and get the modulus and privateExponent&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;*generate RSA private key
openssl genrsa -out foo.pem
* show the details of the key as text, help identify modulus and privateExponent
openssl rsa -in foo.pem –text
* makes the values easier to copy/paste
openssl asn1parse -in foo.pem
* create you public key
openssl rsa -in foo.pem -outform PEM -pubout -out foo_public.pem&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 29 Sep 2015 16:29:43 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/JSON-Web-Signature-JWS-JSON-Web-Token-JWT-to-call-Google-API/m-p/227708#M41048</guid>
      <dc:creator>FriedEgg</dc:creator>
      <dc:date>2015-09-29T16:29:43Z</dc:date>
    </item>
    <item>
      <title>Re: JSON Web Signature (JWS) - JSON Web Token (JWT) to call Google API (Server-Server) - proc groovy</title>
      <link>https://communities.sas.com/t5/SAS-Programming/JSON-Web-Signature-JWS-JSON-Web-Token-JWT-to-call-Google-API/m-p/363651#M86145</link>
      <description>&lt;P&gt;This is GREAT! Thanks! I was struggling with the same thing and will try this.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Quick question, though... Why not just use the Google API for Java in a proc Groovy?&lt;/P&gt;&lt;P&gt;&lt;A href="https://developers.google.com/identity/protocols/OAuth2ServiceAccount?hl=en_US#delegatingauthority" target="_blank"&gt;https://developers.google.com/identity/protocols/OAuth2ServiceAccount?hl=en_US#delegatingauthority&lt;/A&gt; (see the "Preparing to make an authorized API call" heading and Java example).&lt;/P&gt;&lt;P&gt;The Java API are at&amp;nbsp;&lt;A href="https://github.com/google/google-api-java-client#Service_Accounts" target="_blank"&gt;https://github.com/google/google-api-java-client#Service_Accounts&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;From the sounds of it, the&amp;nbsp;&lt;SPAN&gt;SHA256HMACHEX('key','message',3) function doesn't quite work like this groovy option, is that correct?&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 01 Jun 2017 23:57:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/JSON-Web-Signature-JWS-JSON-Web-Token-JWT-to-call-Google-API/m-p/363651#M86145</guid>
      <dc:creator>bartman</dc:creator>
      <dc:date>2017-06-01T23:57:38Z</dc:date>
    </item>
  </channel>
</rss>

