312                 String authorizationCode = request.getParameter(
"code");
   314                 HttpSession session = request.getSession();
   318                 String requestState = request.getParameter(
"state");
   319                 if (storedState == null || !storedState.equals(requestState)) {
   320                         throw new AuthenticationServiceException(
"State parameter mismatch on return. Expected " + storedState + 
" got " + requestState);
   330                 MultiValueMap<String, String> form = 
new LinkedMultiValueMap<>();
   331                 form.add(
"grant_type", 
"authorization_code");
   332                 form.add(
"code", authorizationCode);
   336                 if (codeVerifier != null) {
   337                         form.add(
"code_verifier", codeVerifier);
   341                 if (redirectUri != null) {
   342                         form.add(
"redirect_uri", redirectUri);
   349                                         .useSystemProperties()
   350                                         .setDefaultRequestConfig(RequestConfig.custom()
   356                 HttpComponentsClientHttpRequestFactory factory = 
new HttpComponentsClientHttpRequestFactory(
httpClient);
   358                 RestTemplate restTemplate;
   360                 if (SECRET_BASIC.equals(clientConfig.getTokenEndpointAuthMethod())){
   362                         restTemplate = 
new RestTemplate(factory) {
   365                                 protected ClientHttpRequest createRequest(URI url, HttpMethod method) 
throws IOException {
   366                                         ClientHttpRequest httpRequest = super.createRequest(url, method);
   367                                         httpRequest.getHeaders().add(
"Authorization",
   368                                                         String.format(
"Basic %s", Base64.encode(String.format(
"%s:%s",
   369                                                                         UriUtils.encodePathSegment(clientConfig.getClientId(), 
"UTF-8"),
   370                                                                         UriUtils.encodePathSegment(clientConfig.getClientSecret(), 
"UTF-8")))));
   377                         restTemplate = 
new RestTemplate(factory);
   379                         if (SECRET_JWT.equals(clientConfig.getTokenEndpointAuthMethod()) || PRIVATE_KEY.equals(clientConfig.getTokenEndpointAuthMethod())) {
   383                                 JWTSigningAndValidationService signer = null;
   384                                 JWSAlgorithm alg = clientConfig.getTokenEndpointAuthSigningAlg();
   386                                 if (SECRET_JWT.equals(clientConfig.getTokenEndpointAuthMethod()) &&
   387                                                 (JWSAlgorithm.HS256.equals(alg)
   388                                                                 || JWSAlgorithm.HS384.equals(alg)
   389                                                                 || JWSAlgorithm.HS512.equals(alg))) {
   394                                 } 
else if (PRIVATE_KEY.equals(clientConfig.getTokenEndpointAuthMethod())) {
   404                                 if (signer == null) {
   405                                         throw new AuthenticationServiceException(
"Couldn't find required signer service for use with private key auth.");
   408                                 JWTClaimsSet.Builder claimsSet = 
new JWTClaimsSet.Builder();
   410                                 claimsSet.issuer(clientConfig.getClientId());
   411                                 claimsSet.subject(clientConfig.getClientId());
   412                                 claimsSet.audience(Lists.newArrayList(serverConfig.getTokenEndpointUri()));
   413                                 claimsSet.jwtID(UUID.randomUUID().toString());
   416                                 Date exp = 
new Date(System.currentTimeMillis() + (60 * 1000)); 
   417                                 claimsSet.expirationTime(exp);
   419                                 Date now = 
new Date(System.currentTimeMillis());
   420                                 claimsSet.issueTime(now);
   421                                 claimsSet.notBeforeTime(now);
   423                                 JWSHeader header = 
new JWSHeader(alg, null, null, null, null, null, null, null, null, null,
   424                                                 signer.getDefaultSignerKeyId(),
   426                                 SignedJWT jwt = 
new SignedJWT(header, claimsSet.build());
   428                                 signer.signJwt(jwt, alg);
   430                                 form.add(
"client_assertion_type", 
"urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
   431                                 form.add(
"client_assertion", jwt.serialize());
   434                                 form.add(
"client_id", clientConfig.getClientId());
   435                                 form.add(
"client_secret", clientConfig.getClientSecret());
   440                 logger.debug(
"tokenEndpointURI = " + serverConfig.getTokenEndpointUri());
   441                 logger.debug(
"form = " + form);
   443                 String jsonString = null;
   446                         jsonString = restTemplate.postForObject(serverConfig.getTokenEndpointUri(), form, String.class);
   447                 } 
catch (RestClientException e) {
   451                         logger.error(
"Token Endpoint error response:  " + e.getMessage());
   453                         throw new AuthenticationServiceException(
"Unable to obtain Access Token: " + e.getMessage());
   456                 logger.debug(
"from TokenEndpoint jsonString = " + jsonString);
   458                 JsonElement jsonRoot = 
new JsonParser().parse(jsonString);
   459                 if (!jsonRoot.isJsonObject()) {
   460                         throw new AuthenticationServiceException(
"Token Endpoint did not return a JSON object: " + jsonRoot);
   463                 JsonObject tokenResponse = jsonRoot.getAsJsonObject();
   465                 if (tokenResponse.get(
"error") != null) {
   469                         String error = tokenResponse.get(
"error").getAsString();
   471                         logger.error(
"Token Endpoint returned: " + error);
   473                         throw new AuthenticationServiceException(
"Unable to obtain Access Token.  Token Endpoint returned: " + error);
   481                         String accessTokenValue = null;
   482                         String idTokenValue = null;
   483                         String refreshTokenValue = null;
   485                         if (tokenResponse.has(
"access_token")) {
   486                                 accessTokenValue = tokenResponse.get(
"access_token").getAsString();
   488                                 throw new AuthenticationServiceException(
"Token Endpoint did not return an access_token: " + jsonString);
   491                         if (tokenResponse.has(
"id_token")) {
   492                                 idTokenValue = tokenResponse.get(
"id_token").getAsString();
   494                                 logger.error(
"Token Endpoint did not return an id_token");
   495                                 throw new AuthenticationServiceException(
"Token Endpoint did not return an id_token");
   498                         if (tokenResponse.has(
"refresh_token")) {
   499                                 refreshTokenValue = tokenResponse.get(
"refresh_token").getAsString();
   503                                 JWT idToken = JWTParser.parse(idTokenValue);
   506                                 JWTClaimsSet idClaims = idToken.getJWTClaimsSet();
   509                                 JWTSigningAndValidationService jwtValidator = null;
   511                                 Algorithm tokenAlg = idToken.getHeader().getAlgorithm();
   513                                 Algorithm clientAlg = clientConfig.getIdTokenSignedResponseAlg();
   515                                 if (clientAlg != null) {
   516                                         if (!clientAlg.equals(tokenAlg)) {
   517                                                 throw new AuthenticationServiceException(
"Token algorithm " + tokenAlg + 
" does not match expected algorithm " + clientAlg);
   521                                 if (idToken instanceof PlainJWT) {
   523                                         if (clientAlg == null) {
   524                                                 throw new AuthenticationServiceException(
"Unsigned ID tokens can only be used if explicitly configured in client.");
   527                                         if (tokenAlg != null && !tokenAlg.equals(Algorithm.NONE)) {
   528                                                 throw new AuthenticationServiceException(
"Unsigned token received, expected signature with " + tokenAlg);
   530                                 } 
else if (idToken instanceof SignedJWT) {
   532                                         SignedJWT signedIdToken = (SignedJWT)idToken;
   534                                         if (tokenAlg.equals(JWSAlgorithm.HS256)
   535                                                         || tokenAlg.equals(JWSAlgorithm.HS384)
   536                                                         || tokenAlg.equals(JWSAlgorithm.HS512)) {
   545                                         if (jwtValidator != null) {
   546                                                 if(!jwtValidator.validateSignature(signedIdToken)) {
   547                                                         throw new AuthenticationServiceException(
"Signature validation failed");
   550                                                 logger.error(
"No validation service found. Skipping signature validation");
   551                                                 throw new AuthenticationServiceException(
"Unable to find an appropriate signature validator for ID Token.");
   556                                 if (idClaims.getIssuer() == null) {
   557                                         throw new AuthenticationServiceException(
"Id Token Issuer is null");
   558                                 } 
else if (!idClaims.getIssuer().equals(serverConfig.getIssuer())){
   559                                         throw new AuthenticationServiceException(
"Issuers do not match, expected " + serverConfig.getIssuer() + 
" got " + idClaims.getIssuer());
   563                                 if (idClaims.getExpirationTime() == null) {
   564                                         throw new AuthenticationServiceException(
"Id Token does not have required expiration claim");
   568                                         if (now.after(idClaims.getExpirationTime())) {
   569                                                 throw new AuthenticationServiceException(
"Id Token is expired: " + idClaims.getExpirationTime());
   574                                 if (idClaims.getNotBeforeTime() != null) {
   576                                         if (now.before(idClaims.getNotBeforeTime())){
   577                                                 throw new AuthenticationServiceException(
"Id Token not valid untill: " + idClaims.getNotBeforeTime());
   582                                 if (idClaims.getIssueTime() == null) {
   583                                         throw new AuthenticationServiceException(
"Id Token does not have required issued-at claim");
   587                                         if (now.before(idClaims.getIssueTime())) {
   588                                                 throw new AuthenticationServiceException(
"Id Token was issued in the future: " + idClaims.getIssueTime());
   593                                 if (idClaims.getAudience() == null) {
   594                                         throw new AuthenticationServiceException(
"Id token audience is null");
   595                                 } 
else if (!idClaims.getAudience().contains(clientConfig.getClientId())) {
   596                                         throw new AuthenticationServiceException(
"Audience does not match, expected " + clientConfig.getClientId() + 
" got " + idClaims.getAudience());
   600                                 String nonce = idClaims.getStringClaim(
"nonce");
   601                                 if (Strings.isNullOrEmpty(nonce)) {
   603                                         logger.error(
"ID token did not contain a nonce claim.");
   605                                         throw new AuthenticationServiceException(
"ID token did not contain a nonce claim.");
   609                                 if (!nonce.equals(storedNonce)) {
   610                                         logger.error(
"Possible replay attack detected! The comparison of the nonce in the returned "   611                                                         + 
"ID Token to the session " + 
NONCE_SESSION_VARIABLE + 
" failed. Expected " + storedNonce + 
" got " + nonce + 
".");
   613                                         throw new AuthenticationServiceException(
   614                                                         "Possible replay attack detected! The comparison of the nonce in the returned "   615                                                                         + 
"ID Token to the session " + 
NONCE_SESSION_VARIABLE + 
" failed. Expected " + storedNonce + 
" got " + nonce + 
".");
   620                                 PendingOIDCAuthenticationToken token = 
new PendingOIDCAuthenticationToken(idClaims.getSubject(), idClaims.getIssuer(),
   622                                                 idToken, accessTokenValue, refreshTokenValue);
   624                                 Authentication authentication = this.getAuthenticationManager().authenticate(token);
   626                                 return authentication;
   627                         } 
catch (ParseException e) {
   628                                 throw new AuthenticationServiceException(
"Couldn't parse idToken: ", e);
 JWKSetCacheService validationServices
Definition: OIDCAuthenticationFilter.java:113
JWSAlgorithm getDefaultSigningAlgorithm()
Map< String, String > getTokenOptions(ServerConfiguration server, RegisteredClient client, HttpServletRequest request)
static String getStoredState(HttpSession session)
Definition: OIDCAuthenticationFilter.java:709
int timeSkewAllowance
Definition: OIDCAuthenticationFilter.java:109
JWTSigningAndValidationService authenticationSignerService
Definition: OIDCAuthenticationFilter.java:121
static final String REDIRECT_URI_SESION_VARIABLE
Definition: OIDCAuthenticationFilter.java:98
ClientConfigurationService clients
Definition: OIDCAuthenticationFilter.java:134
JWTSigningAndValidationService getSymmetricValidtor(ClientDetailsEntity client)
Definition: SymmetricKeyJWTValidatorCacheService.java:72
static final String ISSUER_SESSION_VARIABLE
Definition: OIDCAuthenticationFilter.java:102
ServerConfigurationService servers
Definition: OIDCAuthenticationFilter.java:132
HttpClient httpClient
Definition: OIDCAuthenticationFilter.java:124
RegisteredClient getClientConfiguration(ServerConfiguration issuer)
JWTSigningAndValidationService getValidator(String jwksUri)
Definition: JWKSetCacheService.java:85
static final String NONCE_SESSION_VARIABLE
Definition: OIDCAuthenticationFilter.java:101
static String getStoredSessionString(HttpSession session, String key)
Definition: OIDCAuthenticationFilter.java:662
static String getStoredCodeVerifier(HttpSession session)
Definition: OIDCAuthenticationFilter.java:729
static String getStoredNonce(HttpSession session)
Definition: OIDCAuthenticationFilter.java:688
SymmetricKeyJWTValidatorCacheService symmetricCacheService
Definition: OIDCAuthenticationFilter.java:117
ServerConfiguration getServerConfiguration(String issuer)
AuthRequestOptionsService authOptions
Definition: OIDCAuthenticationFilter.java:136
int httpSocketTimeout
Definition: OIDCAuthenticationFilter.java:144