added PKCE support to client
parent
ba0d0aab0b
commit
82c313f036
|
@ -23,6 +23,9 @@ import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_JWT;
|
|||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
@ -40,6 +43,7 @@ import org.apache.http.impl.client.HttpClientBuilder;
|
|||
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
|
||||
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
|
||||
import org.mitre.jwt.signer.service.impl.SymmetricKeyJWTValidatorCacheService;
|
||||
import org.mitre.oauth2.model.PKCEAlgorithm;
|
||||
import org.mitre.oauth2.model.RegisteredClient;
|
||||
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
|
||||
import org.mitre.openid.connect.client.service.AuthRequestOptionsService;
|
||||
|
@ -75,6 +79,7 @@ import com.nimbusds.jose.Algorithm;
|
|||
import com.nimbusds.jose.JWSAlgorithm;
|
||||
import com.nimbusds.jose.JWSHeader;
|
||||
import com.nimbusds.jose.util.Base64;
|
||||
import com.nimbusds.jose.util.Base64URL;
|
||||
import com.nimbusds.jwt.JWT;
|
||||
import com.nimbusds.jwt.JWTClaimsSet;
|
||||
import com.nimbusds.jwt.JWTParser;
|
||||
|
@ -90,10 +95,11 @@ import com.nimbusds.jwt.SignedJWT;
|
|||
public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
protected final static String REDIRECT_URI_SESION_VARIABLE = "redirect_uri";
|
||||
protected final static String CODE_VERIFIER_SESSION_VARIABLE = "code_verifier";
|
||||
protected final static String STATE_SESSION_VARIABLE = "state";
|
||||
protected final static String NONCE_SESSION_VARIABLE = "nonce";
|
||||
protected final static String ISSUER_SESSION_VARIABLE = "issuer";
|
||||
protected static final String TARGET_SESSION_VARIABLE = "target";
|
||||
protected final static String TARGET_SESSION_VARIABLE = "target";
|
||||
protected final static int HTTP_SOCKET_TIMEOUT = 30000;
|
||||
|
||||
public final static String FILTER_PROCESSES_URL = "/openid_connect_login";
|
||||
|
@ -262,6 +268,26 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
|
|||
String state = createState(session);
|
||||
|
||||
Map<String, String> options = authOptions.getOptions(serverConfig, clientConfig, request);
|
||||
|
||||
// if we're using PKCE, handle the challenge here
|
||||
if (clientConfig.getCodeChallengeMethod() != null) {
|
||||
String codeVerifier = createCodeVerifier(session);
|
||||
options.put("code_challenge_method", clientConfig.getCodeChallengeMethod().getName());
|
||||
if (clientConfig.getCodeChallengeMethod().equals(PKCEAlgorithm.plain)) {
|
||||
options.put("code_challenge", codeVerifier);
|
||||
} else if (clientConfig.getCodeChallengeMethod().equals(PKCEAlgorithm.S256)) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
String hash = Base64URL.encode(digest.digest(codeVerifier.getBytes(StandardCharsets.US_ASCII))).toString();
|
||||
options.put("code_challenge", hash);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
String authRequest = authRequestBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state, options, issResp.getLoginHint());
|
||||
|
||||
|
@ -302,6 +328,11 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
|
|||
form.add("grant_type", "authorization_code");
|
||||
form.add("code", authorizationCode);
|
||||
form.setAll(authOptions.getTokenOptions(serverConfig, clientConfig, request));
|
||||
|
||||
String codeVerifier = getStoredCodeVerifier(session);
|
||||
if (codeVerifier != null) {
|
||||
form.add("code_verifier", codeVerifier);
|
||||
}
|
||||
|
||||
String redirectUri = getStoredSessionString(session, REDIRECT_URI_SESION_VARIABLE);
|
||||
if (redirectUri != null) {
|
||||
|
@ -675,6 +706,26 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
|
|||
protected static String getStoredState(HttpSession session) {
|
||||
return getStoredSessionString(session, STATE_SESSION_VARIABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random code challenge and store it in the session
|
||||
* @param session
|
||||
* @return
|
||||
*/
|
||||
protected static String createCodeVerifier(HttpSession session) {
|
||||
String challenge = new BigInteger(50, new SecureRandom()).toString(16);
|
||||
session.setAttribute(CODE_VERIFIER_SESSION_VARIABLE, challenge);
|
||||
return challenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the stored challenge from our session
|
||||
* @param session
|
||||
* @return
|
||||
*/
|
||||
protected static String getStoredCodeVerifier(HttpSession session) {
|
||||
return getStoredSessionString(session, CODE_VERIFIER_SESSION_VARIABLE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue