moved nonce from cookie to session, added state processing, cleaned up unused classes

pull/210/head
Justin Richer 2012-08-15 14:52:49 -04:00
parent 209fc2d249
commit c5244db1a2
4 changed files with 141 additions and 246 deletions

View File

@ -40,6 +40,7 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@ -77,68 +78,11 @@ import com.google.gson.JsonParser;
public class AbstractOIDCAuthenticationFilter extends public class AbstractOIDCAuthenticationFilter extends
AbstractAuthenticationProcessingFilter { AbstractAuthenticationProcessingFilter {
/** protected static final String REDIRECT_URI_SESION_VARIABLE = "redirect_uri";
* Used to remove parameters from a Request before passing it down the protected static final String STATE_SESSION_VARIABLE = "state";
* chain... protected final static String NONCE_SESSION_VARIABLE = "nonce";
*
* @author nemonik
*
*/
protected class SanatizedRequest extends HttpServletRequestWrapper {
private List<String> paramsToBeSanatized;
public SanatizedRequest(HttpServletRequest request,
String[] paramsToBeSanatized) {
super(request);
this.paramsToBeSanatized = Arrays.asList(paramsToBeSanatized);
}
public String getParameter(String name) {
if (paramsToBeSanatized.contains(name)) {
return null;
} else {
return super.getParameter(name);
}
}
public Map<String, String[]> getParameterMap() {
Map<String, String[]> params = super.getParameterMap();
for (String paramToBeSanatized : paramsToBeSanatized) {
params.remove(paramToBeSanatized);
}
return params;
}
public Enumeration<String> getParameterNames() {
ArrayList<String> paramNames = Collections.list(super.getParameterNames());
for (String paramToBeSanatized : paramsToBeSanatized) {
paramNames.remove(paramToBeSanatized);
}
return Collections.enumeration(paramNames);
}
public String[] getParameterValues(String name) {
if (paramsToBeSanatized.contains(name)) {
return null;
} else {
return super.getParameterValues(name);
}
}
}
protected final static int HTTP_SOCKET_TIMEOUT = 30000; protected final static int HTTP_SOCKET_TIMEOUT = 30000;
protected final static String SCOPE = "openid"; protected final static String DEFAULT_SCOPE = "openid";
protected final static int KEY_SIZE = 1024;
protected final static String SIGNING_ALGORITHM = "SHA256withRSA";
protected final static String NONCE_SIGNATURE_COOKIE_NAME = "nonce";
protected final static String FILTER_PROCESSES_URL = "/openid_connect_login"; protected final static String FILTER_PROCESSES_URL = "/openid_connect_login";
@ -156,18 +100,15 @@ public class AbstractOIDCAuthenticationFilter extends
* an array of field names to ignore. * an array of field names to ignore.
* @return a URL built from the messaged parameters. * @return a URL built from the messaged parameters.
*/ */
public static String buildRedirectURI(HttpServletRequest request, public static String buildRedirectURI(HttpServletRequest request, String[] ignoreFields) {
String[] ignoreFields) {
List<String> ignore = (ignoreFields != null) ? Arrays List<String> ignore = (ignoreFields != null) ? Arrays.asList(ignoreFields) : null;
.asList(ignoreFields) : null;
boolean isFirst = true; boolean isFirst = true;
StringBuffer sb = request.getRequestURL(); StringBuffer sb = request.getRequestURL();
for (Enumeration<?> e = request.getParameterNames(); e for (Enumeration<?> e = request.getParameterNames(); e.hasMoreElements();) {
.hasMoreElements();) {
String name = (String) e.nextElement(); String name = (String) e.nextElement();
@ -212,7 +153,7 @@ public class AbstractOIDCAuthenticationFilter extends
* parameters. * parameters.
*/ */
public static String buildURL(String baseURI, Map<String, String> queryStringFields) { public static String buildURL(String baseURI, Map<String, String> queryStringFields) {
// TODO: replace this with URIUtils call
StringBuilder URLBuilder = new StringBuilder(baseURI); StringBuilder URLBuilder = new StringBuilder(baseURI);
char appendChar = '?'; char appendChar = '?';
@ -238,87 +179,12 @@ public class AbstractOIDCAuthenticationFilter extends
return URLBuilder.toString(); return URLBuilder.toString();
} }
/**
* Returns the signature text for the byte array of data
*
* @param signer
* The algorithm to sign with
* @param privateKey
* The private key to sign with
* @param data
* The data to be signed
* @return The signature text
*/
public static String sign(Signature signer, PrivateKey privateKey, byte[] data) {
String signature;
try {
signer.initSign(privateKey);
signer.update(data);
byte[] sigBytes = signer.sign();
signature = (new String(Base64.encodeBase64URLSafe(sigBytes)))
.replace("=", "");
} catch (GeneralSecurityException generalSecurityException) {
// generalSecurityException.printStackTrace();
throw new IllegalStateException(generalSecurityException);
}
return signature;
}
/**
* Verifies the signature text against the data
*
* @param data
* The data
* @param sigText
* The signature text
* @return True if valid, false if not
*/
public static boolean verify(Signature signer, PublicKey publicKey,
String data, String sigText) {
try {
signer.initVerify(publicKey);
signer.update(data.getBytes("UTF-8"));
byte[] sigBytes = Base64.decodeBase64(sigText);
return signer.verify(sigBytes);
} catch (GeneralSecurityException generalSecurityException) {
// generalSecurityException.printStackTrace();
throw new IllegalStateException(generalSecurityException);
} catch (UnsupportedEncodingException unsupportedEncodingException) {
// unsupportedEncodingException.printStackTrace();
throw new IllegalStateException(unsupportedEncodingException);
}
}
protected String errorRedirectURI; protected String errorRedirectURI;
protected String scope; protected String scope;
protected int httpSocketTimeout = HTTP_SOCKET_TIMEOUT; protected int httpSocketTimeout = HTTP_SOCKET_TIMEOUT;
protected PublicKey publicKey;
protected PrivateKey privateKey;
protected Signature signer;
/** /**
* OpenIdConnectAuthenticationFilter constructor * OpenIdConnectAuthenticationFilter constructor
*/ */
@ -332,24 +198,8 @@ public class AbstractOIDCAuthenticationFilter extends
Assert.notNull(errorRedirectURI, "An Error Redirect URI must be supplied"); Assert.notNull(errorRedirectURI, "An Error Redirect URI must be supplied");
KeyPairGenerator keyPairGenerator; // prepend the spec necessary DEFAULT_SCOPE
setScope((scope != null && !scope.isEmpty()) ? DEFAULT_SCOPE + " " + scope : DEFAULT_SCOPE);
try {
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
publicKey = keyPair.getPublic();
privateKey = keyPair.getPrivate();
signer = Signature.getInstance(SIGNING_ALGORITHM);
} catch (GeneralSecurityException generalSecurityException) {
// generalSecurityException.printStackTrace();
throw new IllegalStateException(generalSecurityException);
}
// prepend the spec necessary SCOPE
setScope((scope != null && !scope.isEmpty()) ? SCOPE + " " + scope
: SCOPE);
} }
/* /*
@ -376,7 +226,7 @@ public class AbstractOIDCAuthenticationFilter extends
/** /**
* Handles the authorization grant response * Handles the authorization grant response
* *
* @param authorizationGrant * @param authorizationCode
* The Authorization grant code * The Authorization grant code
* @param request * @param request
* The request from which to extract parameters and perform the * The request from which to extract parameters and perform the
@ -387,11 +237,22 @@ public class AbstractOIDCAuthenticationFilter extends
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
*/ */
protected Authentication handleAuthorizationGrantResponse( protected Authentication handleAuthorizationGrantResponse(
String authorizationGrant, HttpServletRequest request, String authorizationCode, HttpServletRequest request,
OIDCServerConfiguration serverConfig) { OIDCServerConfiguration serverConfig) {
final boolean debug = logger.isDebugEnabled(); final boolean debug = logger.isDebugEnabled();
HttpSession session = request.getSession();
// check for state
String storedState = getStoredState(session);
if (!StringUtils.isBlank(storedState)) {
String state = request.getParameter("state");
if (!storedState.equals(state)) {
throw new AuthenticationServiceException("State parameter mismatch on return. Expected " + storedState + " got " + state);
}
}
// Handle Token Endpoint interaction // Handle Token Endpoint interaction
HttpClient httpClient = new DefaultHttpClient(); HttpClient httpClient = new DefaultHttpClient();
@ -414,9 +275,12 @@ public class AbstractOIDCAuthenticationFilter extends
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>(); MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("grant_type", "authorization_code"); form.add("grant_type", "authorization_code");
form.add("code", authorizationGrant); form.add("code", authorizationCode);
form.add("redirect_uri", AbstractOIDCAuthenticationFilter
.buildRedirectURI(request, null)); String redirectUri = getStoredRedirectUri(session);
if (redirectUri != null) {
form.add("redirect_uri", redirectUri);
}
// pass clientId and clientSecret in post of request // pass clientId and clientSecret in post of request
form.add("client_id", serverConfig.getClientId()); form.add("client_id", serverConfig.getClientId());
@ -457,9 +321,7 @@ public class AbstractOIDCAuthenticationFilter extends
logger.error("Token Endpoint returned: " + error); logger.error("Token Endpoint returned: " + error);
throw new AuthenticationServiceException( throw new AuthenticationServiceException("Unable to obtain Access Token. Token Endpoint returned: " + error);
"Unable to obtain Access Token. Token Endpoint returned: "
+ error);
} else { } else {
@ -527,41 +389,17 @@ public class AbstractOIDCAuthenticationFilter extends
logger.error("ID token did not contain a nonce claim."); logger.error("ID token did not contain a nonce claim.");
throw new AuthenticationServiceException( throw new AuthenticationServiceException("ID token did not contain a nonce claim.");
"ID token did not contain a nonce claim.");
} }
Cookie nonceSignatureCookie = WebUtils.getCookie(request, NONCE_SIGNATURE_COOKIE_NAME); String storedNonce = getStoredNonce(session);
if (!nonce.equals(storedNonce)) {
if (nonceSignatureCookie != null) { logger.error("Possible replay attack detected! The comparison of the nonce in the returned "
+ "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
String sigText = nonceSignatureCookie.getValue();
if (sigText != null && !sigText.isEmpty()) {
if (!verify(signer, publicKey, nonce, sigText)) {
logger.error("Possible replay attack detected! "
+ "The comparison of the nonce in the returned "
+ "ID Token to the signed session "
+ NONCE_SIGNATURE_COOKIE_NAME + " failed.");
throw new AuthenticationServiceException( throw new AuthenticationServiceException(
"Possible replay attack detected! " "Possible replay attack detected! The comparison of the nonce in the returned "
+ "The comparison of the nonce in the returned " + "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
+ "ID Token to the signed session "
+ NONCE_SIGNATURE_COOKIE_NAME
+ " failed.");
}
} else {
logger.error(NONCE_SIGNATURE_COOKIE_NAME + " cookie was found but value was null or empty");
throw new AuthenticationServiceException(NONCE_SIGNATURE_COOKIE_NAME + " cookie was found but value was null or empty");
}
} else {
logger.error(NONCE_SIGNATURE_COOKIE_NAME + " cookie was not found.");
throw new AuthenticationServiceException(NONCE_SIGNATURE_COOKIE_NAME + " cookie was not found.");
} }
// pull the user_id out as a claim on the id_token // pull the user_id out as a claim on the id_token
@ -594,8 +432,9 @@ public class AbstractOIDCAuthenticationFilter extends
* If an input or output exception occurs * If an input or output exception occurs
*/ */
protected void handleAuthorizationRequest(HttpServletRequest request, protected void handleAuthorizationRequest(HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response, OIDCServerConfiguration serverConfiguration) throws IOException {
OIDCServerConfiguration serverConfiguration) throws IOException {
HttpSession session = request.getSession();
Map<String, String> urlVariables = new HashMap<String, String>(); Map<String, String> urlVariables = new HashMap<String, String>();
@ -604,7 +443,10 @@ public class AbstractOIDCAuthenticationFilter extends
urlVariables.put("response_type", "code"); urlVariables.put("response_type", "code");
urlVariables.put("client_id", serverConfiguration.getClientId()); urlVariables.put("client_id", serverConfiguration.getClientId());
urlVariables.put("scope", scope); urlVariables.put("scope", scope);
urlVariables.put("redirect_uri", AbstractOIDCAuthenticationFilter.buildRedirectURI(request, null));
String redirectURI = buildRedirectURI(request, null);
urlVariables.put("redirect_uri", redirectURI);
session.setAttribute(REDIRECT_URI_SESION_VARIABLE, redirectURI);
// Create a string value used to associate a user agent session // Create a string value used to associate a user agent session
// with an ID Token to mitigate replay attacks. The value is // with an ID Token to mitigate replay attacks. The value is
@ -612,14 +454,12 @@ public class AbstractOIDCAuthenticationFilter extends
// store a random value as a signed session cookie, and pass the // store a random value as a signed session cookie, and pass the
// value in the nonce parameter. // value in the nonce parameter.
String nonce = new BigInteger(50, new SecureRandom()).toString(16); String nonce = createNonce(session);
Cookie nonceCookie = new Cookie(NONCE_SIGNATURE_COOKIE_NAME, sign(signer, privateKey, nonce.getBytes()));
response.addCookie(nonceCookie);
urlVariables.put("nonce", nonce); urlVariables.put("nonce", nonce);
String state = createState(session);
urlVariables.put("state", state);
// Optional parameters: // Optional parameters:
// TODO: display, prompt, request, request_uri // TODO: display, prompt, request, request_uri
@ -674,6 +514,73 @@ public class AbstractOIDCAuthenticationFilter extends
} }
/**
* Get the named stored session variable as a string. Return null if not found or not a string.
* @param session
* @param key
* @return
*/
private static String getStoredSessionString(HttpSession session, String key) {
Object o = session.getAttribute(key);
if (o != null && o instanceof String) {
return o.toString();
} else {
return null;
}
}
/**
* Create a cryptographically random nonce and store it in the session
* @param session
* @return
*/
protected static String createNonce(HttpSession session) {
String nonce = new BigInteger(50, new SecureRandom()).toString(16);
session.setAttribute(NONCE_SESSION_VARIABLE, nonce);
return nonce;
}
/**
* Get the nonce we stored in the session
* @param session
* @return
*/
protected static String getStoredNonce(HttpSession session) {
return getStoredSessionString(session, NONCE_SESSION_VARIABLE);
}
/**
* Create a cryptographically random state and store it in the session
* @param session
* @return
*/
protected static String createState(HttpSession session) {
String state = new BigInteger(50, new SecureRandom()).toString(16);
session.setAttribute(STATE_SESSION_VARIABLE, state);
return state;
}
/**
* Get the state we stored in the session
* @param session
* @return
*/
protected static String getStoredState(HttpSession session) {
return getStoredSessionString(session, STATE_SESSION_VARIABLE);
}
/**
* Get the stored redirect URI that we used on the way out
* @param serverConfig
* @return
*/
protected static String getStoredRedirectUri(HttpSession session) {
return getStoredSessionString(session, REDIRECT_URI_SESION_VARIABLE);
}
protected JwtSigningAndValidationService getValidatorForServer(OIDCServerConfiguration serverConfig) { protected JwtSigningAndValidationService getValidatorForServer(OIDCServerConfiguration serverConfig) {
if(getValidationServices().containsKey(serverConfig)){ if(getValidationServices().containsKey(serverConfig)){

View File

@ -96,7 +96,7 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter {
} else if (StringUtils.isNotBlank(request.getParameter("code"))) { } else if (StringUtils.isNotBlank(request.getParameter("code"))) {
try { try {
return handleAuthorizationGrantResponse(request.getParameter("code"), new SanatizedRequest(request, new String[] { "code" }), oidcServerConfig); return handleAuthorizationGrantResponse(request.getParameter("code"), request, oidcServerConfig);
} catch (Exception e) { } catch (Exception e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();

View File

@ -40,8 +40,7 @@ import org.springframework.web.util.WebUtils;
* @author nemonik * @author nemonik
* *
*/ */
public class OIDCAuthenticationUsingChooserFilter extends public class OIDCAuthenticationUsingChooserFilter extends AbstractOIDCAuthenticationFilter {
AbstractOIDCAuthenticationFilter {
protected final static String ISSUER_COOKIE_NAME = "issuer"; protected final static String ISSUER_COOKIE_NAME = "issuer";
@ -70,17 +69,11 @@ public class OIDCAuthenticationUsingChooserFilter extends
// Validating configuration // Validating configuration
Assert.notNull( Assert.notNull(oidcServerConfigs, "Server Configurations must be supplied if the Account Chooser UI Application is to be used.");
oidcServerConfigs,
"Server Configurations must be supplied if the Account Chooser UI Application is to be used.");
Assert.notNull( Assert.notNull(accountChooserURI, "Account Chooser URI must be supplied if the Account Chooser UI Application is to be used.");
accountChooserURI,
"Account Chooser URI must be supplied if the Account Chooser UI Application is to be used.");
Assert.notNull( Assert.notNull(accountChooserClientID, "Account Chooser Client ID must be supplied if the Account Chooser UI Application is to be used.");
accountChooserClientID,
"Account Chooser Client ID must be supplied if the Account Chooser UI Application is to be used.");
} }
/* /*
@ -92,9 +85,7 @@ public class OIDCAuthenticationUsingChooserFilter extends
* javax.servlet.http.HttpServletResponse) * javax.servlet.http.HttpServletResponse)
*/ */
@Override @Override
public Authentication attemptAuthentication(HttpServletRequest request, public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException, AuthenticationException, ServletException {
HttpServletResponse response) throws IOException,
AuthenticationException, ServletException {
// Enter AuthenticationFilter here... // Enter AuthenticationFilter here...
super.attemptAuthentication(request, response); super.attemptAuthentication(request, response);
@ -106,12 +97,10 @@ public class OIDCAuthenticationUsingChooserFilter extends
} else if (request.getParameter("code") != null) { } else if (request.getParameter("code") != null) {
// Which OIDC configuration? // Which OIDC configuration?
Cookie issuerCookie = WebUtils.getCookie(request, Cookie issuerCookie = WebUtils.getCookie(request, ISSUER_COOKIE_NAME);
ISSUER_COOKIE_NAME);
try { try {
return handleAuthorizationGrantResponse(request.getParameter("code"), new SanatizedRequest(request, new String[] { "code" }), return handleAuthorizationGrantResponse(request.getParameter("code"), request, oidcServerConfigs.get(issuerCookie.getValue()));
oidcServerConfigs.get(issuerCookie.getValue()));
} catch (Exception e) { } catch (Exception e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
@ -125,8 +114,7 @@ public class OIDCAuthenticationUsingChooserFilter extends
// Account Chooser UI provided and Issuer Identifier // Account Chooser UI provided and Issuer Identifier
OIDCServerConfiguration oidcServerConfig = oidcServerConfigs OIDCServerConfiguration oidcServerConfig = oidcServerConfigs.get(issuer);
.get(issuer);
if (oidcServerConfig != null) { if (oidcServerConfig != null) {
@ -136,18 +124,14 @@ public class OIDCAuthenticationUsingChooserFilter extends
Cookie issuerCookie = new Cookie(ISSUER_COOKIE_NAME, issuer); Cookie issuerCookie = new Cookie(ISSUER_COOKIE_NAME, issuer);
response.addCookie(issuerCookie); response.addCookie(issuerCookie);
handleAuthorizationRequest(new SanatizedRequest(request, handleAuthorizationRequest(request, response, oidcServerConfig);
new String[] { "issuer" }), response,
oidcServerConfig);
} else { } else {
// The Client is NOT configured to support this Issuer // The Client is NOT configured to support this Issuer
// Identifier // Identifier
throw new AuthenticationServiceException( throw new AuthenticationServiceException("Security Filter not configured for issuer: " + issuer);
"Security Filter not configured for issuer: "
+ issuer);
} }
} else { } else {
@ -157,9 +141,7 @@ public class OIDCAuthenticationUsingChooserFilter extends
Map<String, String> urlVariables = new HashMap<String, String>(); Map<String, String> urlVariables = new HashMap<String, String>();
urlVariables.put("redirect_uri", urlVariables.put("redirect_uri", buildRedirectURI(request, null));
OIDCAuthenticationUsingChooserFilter.buildRedirectURI(
request, null));
urlVariables.put("client_id", accountChooserClientID); urlVariables.put("client_id", accountChooserClientID);

View File

@ -11,6 +11,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.mitre.jwt.model.Jwt; import org.mitre.jwt.model.Jwt;
@ -68,7 +69,7 @@ public class OIDCSignedRequestFilter extends AbstractOIDCAuthenticationFilter {
} else if (StringUtils.isNotBlank(request.getParameter("code"))) { } else if (StringUtils.isNotBlank(request.getParameter("code"))) {
try { try {
return handleAuthorizationGrantResponse(request.getParameter("code"), new SanatizedRequest(request, new String[] { "code" }), oidcServerConfig); return handleAuthorizationGrantResponse(request.getParameter("code"), request, oidcServerConfig);
} catch (Exception e) { } catch (Exception e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
@ -100,6 +101,7 @@ public class OIDCSignedRequestFilter extends AbstractOIDCAuthenticationFilter {
} }
public Jwt createAndSignRequestJwt(HttpServletRequest request, HttpServletResponse response, OIDCServerConfiguration serverConfiguration) { public Jwt createAndSignRequestJwt(HttpServletRequest request, HttpServletResponse response, OIDCServerConfiguration serverConfiguration) {
HttpSession session = request.getSession();
Jwt jwt = new Jwt(); Jwt jwt = new Jwt();
JwtClaims claims = jwt.getClaims(); JwtClaims claims = jwt.getClaims();
@ -110,16 +112,20 @@ public class OIDCSignedRequestFilter extends AbstractOIDCAuthenticationFilter {
claims.setClaim("response_type", "code"); claims.setClaim("response_type", "code");
claims.setClaim("client_id", serverConfiguration.getClientId()); claims.setClaim("client_id", serverConfiguration.getClientId());
claims.setClaim("scope", scope); claims.setClaim("scope", scope);
claims.setClaim("redirect_uri", AbstractOIDCAuthenticationFilter.buildRedirectURI(request, null));
//create random nonce // build our redirect URI
String nonce = new BigInteger(50, new SecureRandom()).toString(16); String redirectUri = buildRedirectURI(request, null);
Cookie nonceCookie = new Cookie(NONCE_SIGNATURE_COOKIE_NAME, sign(signer, privateKey, nonce.getBytes())); claims.setClaim("redirect_uri", redirectUri);
session.setAttribute(REDIRECT_URI_SESION_VARIABLE, redirectUri);
response.addCookie(nonceCookie); //create random nonce and state, save them to the session
String nonce = createNonce(session);
claims.setClaim("nonce", nonce); claims.setClaim("nonce", nonce);
String state = createState(session);
claims.setClaim("state", state);
try { try {
signingAndValidationService.signJwt(jwt); signingAndValidationService.signJwt(jwt);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {