I a generating jwt token using below payload.
{
"sub":"adddd-97df-42de-be9f-ea49c8b24712",
"iat":"1655457036",
"iss":"gdddd-5a32-49b4-a185-2b4a8f721073",
"aud":"account-d.docusign.com",
"scope":"signature impersonation",
"exp":"1755457036"
}
along with it I am sending public and private kye genrated by docusign portal.
it is working successfully. now I need to generate the same using java because I have to call multiple APIs back to back. I am writing below code.
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/jwt")
public class JwtController {
@GetMapping("/token")
public static String createJwtSignedHMAC() throws InvalidKeySpecException, NoSuchAlgorithmException {
PrivateKey privateKey = getPrivateKey();
Instant now = Instant.now();
String jwtToken = Jwts.builder()
.claim("aud", "account-d.docusign.com")
.claim("scope", "signature impersonation")
.setSubject("e48dbc73-97df-42de-be9f-ea49c8b24712")
.setId("e89f1c24-5a32-49b4-a185-2b4a8f721073")
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(now.plus(600, ChronoUnit.MINUTES)))
.signWith(privateKey)
.compact();
return jwtToken;
}
private static PrivateKey getPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
String rsaPrivateKey =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEowIBAAKCAQEAqGHe8Aj7cGiwxR7Mz/h9dBDXKonV5Q YnYebQgz sr2/3PsO\r\n"
"eP3gAC52UbGKOAcmkEXJdiJLxEOhnuNsnwi26oN9S9jKWtnWbsoeYCqJfDwxHHRX\r\n"
"X 5P2FK F4D8eqX9QKzeO11Ztdq8chNvAYa/NsBfFLvFX/VaWrZmlTW1OQafkml6\r\n"
"Pnx9hVi8EH3 3K68X49vyzSRIiuJ09B37hRKW3vYd5203YXlrxM5LZo4JO3QKz3g\r\n"
"uzAdiMJ2Ca wQrpjB/GDMaFycXcB3oQUaqvTIavqGpx5XgNdyFyVGS55BHVfX0Da\r\n"
"9sOdiNNjrAQ VE1SJ1rqxvHk9K91cWpSngZKhQIDAQABAoIBAC6uW3kedF7Yl1E \r\n"
"1bc g8E vfgsGGGVrlDV/IQWSDJTirJ/46ZFc l4 BJz7wbTbKyIvG6E2Y6C1XbQ\r\n"
"RBfe Z8Qbxcs9gSz6c/zNvKgOFd59H X/XU6A2bMoaiweM6j4A8jHcVFfw58osvZ\r\n"
"eWfp7G8IbBO6buDIi5EkilIJfsFdEYRWOkBY8Sf5oFt/lOzcbbEmXNiVe4iHnLlS\r\n"
"uuN NXygpS9f6I0BpP6kT427b7uh2lIuofJyk0ZCprqXIa0mGneOPs4BhC0dFsUf\r\n"
"ycM7bdBo xUlMRRHAzPL0zZpO74E7Nk/gnBBUvE5zDPT/WtNSrsVMUE5d4tdxNbj\r\n"
"Y5EVD 0CgYEA7f/BJjdNwf9KvAVqeRv1 k6nrrZsqaE02DofX5 f9CC4uMBtOsX3\r\n"
"nYZEnNp3KQDStKE0cTuD7E6dqCwHzCWx0cBQTdpNqyG2RwFDnZJvJh2YMf6bjuPH\r\n"
"9FbypmMs3oG0VHK lgPjTn6HKeXmQIMjXfRnGYShDCWGhwQLxBUuPSsCgYEAtR4q\r\n"
"YlXYC01RTZeuOVY9NbGoFPWUxTHRhVvfcqXhj/G31yqOcZjUA0/cLS7I cQBGSS3\r\n"
"gDG0pnGPfkhRjuv2Gdu7qgfI d8WBJgIwRWRWw6a57et7E1z9k2DI6S9ZFwNwAiO\r\n"
"j2c79gMky8dwW5TZVLIZ3pxFFcdZgrNO/r15nw8CgYAHhzR72fn6rfGWOvGgPRMt\r\n"
"xLknHJwZTYEXadc NhVgKnzNU0DhQAvSDsIy1/I2 NCxZ/v5rPFCU0ZHYIUqnvKd\r\n"
" OBRZhtY02spmc it1QOt5bt1ejjvy6 tUYEEEGFMI4fZyrsBnLjNMHrz72QW n\r\n"
"9CgitYBGmxVDRgx9OlJJGwKBgQCc5GOsyVYb/D8YqvNGQdlGIP5MIaxc4dnw3vQC\r\n"
"OYXajnZFUl0QNGY79DrzfNql2c9lu3Ol/ejSYf7 UqEr4GVQYxL qD3FjiVhl13F\r\n"
"/OvsaAtx/KAR2cpBK0YVY0iYnlFe70qnGLNNWc3PJJXFD3zwLFPSjaYexpBYcwFU\r\n"
"FEg9qwKBgCSZCXBOEsVp1sAWEK4xw7Pi2VOccAwr1MsW3SFh5GFVHd9ZtP94 s5h\r\n"
"GylNCY9zmULLTG7F2wwD43/3dHsFcEIntaxQPVcGJcV9Il6t2UfK7LbunKU8FIJJ\r\n"
"DUVLp3i91kanSFDwSHHVsrsOTvnuHJ3jmF1umntKGQWqgdL4i07E\r\n"
"-----END RSA PRIVATE KEY-----";
rsaPrivateKey = rsaPrivateKey.replace("-----BEGIN PRIVATE KEY-----", "");
rsaPrivateKey = rsaPrivateKey.replace("-----END PRIVATE KEY-----", "");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(rsaPrivateKey));
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(keySpec);
return privKey;
}
}
but it is throwing exception. what wrong I am doing?
java.lang.IllegalArgumentException: Illegal base64 character 2d at java.base/java.util.Base64$Decoder.decode0(Base64.java:847) ~[na:na] at java.base/java.util.Base64$Decoder.decode(Base64.java:566) ~[na:na] at java.base/java.util.Base64$Decoder.decode(Base64.java:589) ~[na:na] at com.marsh.docusign.controller.JwtController.getPrivateKey(JwtController.java:78) ~[classes/:na] at com.marsh.docusign.controller.JwtController.createJwtSignedHMAC(JwtController.java:30) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.20.jar:5.3.20] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.20.jar:5.3.20] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.20.jar:5.3.20] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.20.jar:5.3.20] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.20.jar:5.3.20] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.20.jar:5.3.20] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.20.jar:5.3.20] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.20.jar:5.3.20] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.20.jar:5.3.20] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.20.jar:5.3.20] at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.63.jar:4.0.FR] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.20.jar:5.3.20] at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.63.jar:4.0.FR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.63.jar:9.0.63] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.20.jar:5.3.20] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.20.jar:5.3.20] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.20.jar:5.3.20] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.20.jar:5.3.20] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.20.jar:5.3.20] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.20.jar:5.3.20] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.63.jar:9.0.63] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
could you pls help me on the same?
CodePudding user response:
Although the complete code snippet you have posted might have other errors as well, the specific error that you get and mention in the question has to do with the following
Base64.getDecoder().decode("\r\n".getBytes()); //Exception
Because \r\n
is not valid base 64 encoded text.
CodePudding user response:
Problem is in this line of code:
rsaPrivateKey = rsaPrivateKey.replace("-----BEGIN PRIVATE KEY-----", "");
rsaPrivateKey = rsaPrivateKey.replace("-----END PRIVATE KEY-----", "");
Change it with this:
rsaPrivateKey = rsaPrivateKey.replace("-----BEGIN RSA PRIVATE KEY-----", "");
rsaPrivateKey = rsaPrivateKey.replace("-----END RSA PRIVATE KEY-----", "");
rsaPrivateKey = rsaPrivateKey.replaceAll("\\r\\n", "");
And it should work as expected.