@blueblueskies I updated the gist you mentioned to add support for JWT. I made use of the JAVA library java-jwt and added support for SHA256withRSA. Example for PROC GROOVY: https://gist.github.com/FriedEgg/79ad315afa1b315e8ac3#file-sha256withrsa-jwt4sas-sas Github Repository for my fork of JAVA-JWT: https://github.com/FriedEgg/java-jwt and the JAR: https://github.com/FriedEgg/java-jwt/releases/download/java-jwt-2.1.2/java-jwt-2.1.1-SNAPSHOT.jar 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<String, Object> claims = new HashMap<String, Object>();
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<String, Object> claims = new HashMap<String, Object>();
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*/ Instructions to generate a RSA key using OpenSSL and get the modulus and privateExponent *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
... View more