Ver código fonte

Remove JwtEncoder and associated classes

Issue gh-596

Closes gh-724
Joe Grandja 3 anos atrás
pai
commit
a1fefd937b
25 arquivos alterados com 124 adições e 1741 exclusões
  1. 2 2
      oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2ConfigurerUtils.java
  2. 0 396
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JoseHeader.java
  3. 0 101
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JoseHeaderNames.java
  4. 0 204
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimsSet.java
  5. 0 56
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JwtEncoder.java
  6. 0 48
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JwtEncodingException.java
  7. 0 344
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwsEncoder.java
  8. 15 14
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContext.java
  9. 5 4
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/JwtGenerator.java
  10. 3 3
      oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationCodeGrantTests.java
  11. 7 6
      oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcClientRegistrationTests.java
  12. 6 6
      oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java
  13. 7 6
      oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcUserInfoTests.java
  14. 0 108
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/JoseHeaderTests.java
  15. 0 90
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/JwtClaimsSetTests.java
  16. 0 275
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwsEncoderTests.java
  17. 7 7
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/TestJwsHeaders.java
  18. 6 6
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContextTests.java
  19. 10 9
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/JwtClientAssertionAuthenticationProviderTests.java
  20. 22 21
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java
  21. 7 7
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProviderTests.java
  22. 8 8
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProviderTests.java
  23. 7 7
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProviderTests.java
  24. 5 5
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcClientRegistrationEndpointFilterTests.java
  25. 7 8
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/token/JwtGeneratorTests.java

+ 2 - 2
oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2ConfigurerUtils.java

@@ -28,7 +28,7 @@ import org.springframework.core.ResolvableType;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
 import org.springframework.security.oauth2.core.OAuth2Token;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.jwt.NimbusJwsEncoder;
+import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
 import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationConsentService;
 import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationService;
@@ -138,7 +138,7 @@ final class OAuth2ConfigurerUtils {
 			if (jwtEncoder == null) {
 				JWKSource<SecurityContext> jwkSource = getJwkSource(builder);
 				if (jwkSource != null) {
-					jwtEncoder = new NimbusJwsEncoder(jwkSource);
+					jwtEncoder = new NimbusJwtEncoder(jwkSource);
 				}
 			}
 			if (jwtEncoder != null) {

+ 0 - 396
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JoseHeader.java

@@ -1,396 +0,0 @@
-/*
- * Copyright 2020-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-import java.net.URL;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Consumer;
-
-import org.springframework.security.oauth2.core.converter.ClaimConversionService;
-import org.springframework.security.oauth2.jose.JwaAlgorithm;
-import org.springframework.util.Assert;
-
-/**
- * The JOSE header is a JSON object representing the header parameters of a JSON Web Token,
- * whether the JWT is a JWS or JWE, that describe the cryptographic operations applied to the JWT
- * and optionally, additional properties of the JWT.
- *
- * @author Anoop Garlapati
- * @author Joe Grandja
- * @since 0.0.1
- * @see Jwt
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7519#section-5">JWT JOSE Header</a>
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7515#section-4">JWS JOSE Header</a>
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7516#section-4">JWE JOSE Header</a>
- * @deprecated See <a target="_blank" href="https://github.com/spring-projects/spring-authorization-server/issues/596">gh-596</a>
- */
-@Deprecated
-public final class JoseHeader {
-	private final Map<String, Object> headers;
-
-	private JoseHeader(Map<String, Object> headers) {
-		this.headers = Collections.unmodifiableMap(new HashMap<>(headers));
-	}
-
-	/**
-	 * Returns the {@link JwaAlgorithm JWA algorithm} used to digitally sign the JWS or encrypt the JWE.
-	 *
-	 * @return the {@link JwaAlgorithm}
-	 */
-	@SuppressWarnings("unchecked")
-	public <T extends JwaAlgorithm> T getAlgorithm() {
-		return (T) getHeader(JoseHeaderNames.ALG);
-	}
-
-	/**
-	 * Returns the JWK Set URL that refers to the resource of a set of JSON-encoded public keys,
-	 * one of which corresponds to the key used to digitally sign the JWS or encrypt the JWE.
-	 *
-	 * @return the JWK Set URL
-	 */
-	public URL getJwkSetUrl() {
-		return getHeader(JoseHeaderNames.JKU);
-	}
-
-	/**
-	 * Returns the JSON Web Key which is the public key that corresponds to the key
-	 * used to digitally sign the JWS or encrypt the JWE.
-	 *
-	 * @return the JSON Web Key
-	 */
-	public Map<String, Object> getJwk() {
-		return getHeader(JoseHeaderNames.JWK);
-	}
-
-	/**
-	 * Returns the key ID that is a hint indicating which key was used to secure the JWS or JWE.
-	 *
-	 * @return the key ID
-	 */
-	public String getKeyId() {
-		return getHeader(JoseHeaderNames.KID);
-	}
-
-	/**
-	 * Returns the X.509 URL that refers to the resource for the X.509 public key certificate
-	 * or certificate chain corresponding to the key used to digitally sign the JWS or encrypt the JWE.
-	 *
-	 * @return the X.509 URL
-	 */
-	public URL getX509Url() {
-		return getHeader(JoseHeaderNames.X5U);
-	}
-
-	/**
-	 * Returns the X.509 certificate chain that contains the X.509 public key certificate
-	 * or certificate chain corresponding to the key used to digitally sign the JWS or
-	 * encrypt the JWE. The certificate or certificate chain is represented as a
-	 * {@code List} of certificate value {@code String}s. Each {@code String} in the
-	 * {@code List} is a Base64-encoded DER PKIX certificate value.
-	 *
-	 * @return the X.509 certificate chain
-	 */
-	public List<String> getX509CertificateChain() {
-		return getHeader(JoseHeaderNames.X5C);
-	}
-
-	/**
-	 * Returns the X.509 certificate SHA-1 thumbprint that is a base64url-encoded SHA-1 thumbprint (a.k.a. digest)
-	 * of the DER encoding of the X.509 certificate corresponding to the key used to digitally sign the JWS or encrypt the JWE.
-	 *
-	 * @return the X.509 certificate SHA-1 thumbprint
-	 */
-	public String getX509SHA1Thumbprint() {
-		return getHeader(JoseHeaderNames.X5T);
-	}
-
-	/**
-	 * Returns the X.509 certificate SHA-256 thumbprint that is a base64url-encoded SHA-256 thumbprint (a.k.a. digest)
-	 * of the DER encoding of the X.509 certificate corresponding to the key used to digitally sign the JWS or encrypt the JWE.
-	 *
-	 * @return the X.509 certificate SHA-256 thumbprint
-	 */
-	public String getX509SHA256Thumbprint() {
-		return getHeader(JoseHeaderNames.X5T_S256);
-	}
-
-	/**
-	 * Returns the type header that declares the media type of the JWS/JWE.
-	 *
-	 * @return the type header
-	 */
-	public String getType() {
-		return getHeader(JoseHeaderNames.TYP);
-	}
-
-	/**
-	 * Returns the content type header that declares the media type of the secured content (the payload).
-	 *
-	 * @return the content type header
-	 */
-	public String getContentType() {
-		return getHeader(JoseHeaderNames.CTY);
-	}
-
-	/**
-	 * Returns the critical headers that indicates which extensions to the JWS/JWE/JWA specifications
-	 * are being used that MUST be understood and processed.
-	 *
-	 * @return the critical headers
-	 */
-	public Set<String> getCritical() {
-		return getHeader(JoseHeaderNames.CRIT);
-	}
-
-	/**
-	 * Returns the headers.
-	 *
-	 * @return the headers
-	 */
-	public Map<String, Object> getHeaders() {
-		return this.headers;
-	}
-
-	/**
-	 * Returns the header value.
-	 *
-	 * @param name the header name
-	 * @param <T> the type of the header value
-	 * @return the header value
-	 */
-	@SuppressWarnings("unchecked")
-	public <T> T getHeader(String name) {
-		Assert.hasText(name, "name cannot be empty");
-		return (T) getHeaders().get(name);
-	}
-
-	/**
-	 * Returns a new {@link Builder}.
-	 *
-	 * @return the {@link Builder}
-	 */
-	public static Builder builder() {
-		return new Builder();
-	}
-
-	/**
-	 * Returns a new {@link Builder}, initialized with the provided {@link JwaAlgorithm}.
-	 *
-	 * @param jwaAlgorithm the {@link JwaAlgorithm}
-	 * @return the {@link Builder}
-	 */
-	public static Builder withAlgorithm(JwaAlgorithm jwaAlgorithm) {
-		return new Builder(jwaAlgorithm);
-	}
-
-	/**
-	 * Returns a new {@link Builder}, initialized with the provided {@code headers}.
-	 *
-	 * @param headers the headers
-	 * @return the {@link Builder}
-	 */
-	public static Builder from(JoseHeader headers) {
-		return new Builder(headers);
-	}
-
-	/**
-	 * A builder for {@link JoseHeader}.
-	 */
-	public static final class Builder {
-		private final Map<String, Object> headers = new HashMap<>();
-
-		private Builder() {
-		}
-
-		private Builder(JwaAlgorithm jwaAlgorithm) {
-			algorithm(jwaAlgorithm);
-		}
-
-		private Builder(JoseHeader headers) {
-			Assert.notNull(headers, "headers cannot be null");
-			this.headers.putAll(headers.getHeaders());
-		}
-
-		/**
-		 * Sets the {@link JwaAlgorithm JWA algorithm} used to digitally sign the JWS or encrypt the JWE.
-		 *
-		 * @param jwaAlgorithm the {@link JwaAlgorithm}
-		 * @return the {@link Builder}
-		 */
-		public Builder algorithm(JwaAlgorithm jwaAlgorithm) {
-			Assert.notNull(jwaAlgorithm, "jwaAlgorithm cannot be null");
-			return header(JoseHeaderNames.ALG, jwaAlgorithm);
-		}
-
-		/**
-		 * Sets the JWK Set URL that refers to the resource of a set of JSON-encoded public keys,
-		 * one of which corresponds to the key used to digitally sign the JWS or encrypt the JWE.
-		 *
-		 * @param jwkSetUrl the JWK Set URL
-		 * @return the {@link Builder}
-		 */
-		public Builder jwkSetUrl(String jwkSetUrl) {
-			return header(JoseHeaderNames.JKU, convertAsURL(JoseHeaderNames.JKU, jwkSetUrl));
-		}
-
-		/**
-		 * Sets the JSON Web Key which is the public key that corresponds to the key
-		 * used to digitally sign the JWS or encrypt the JWE.
-		 *
-		 * @param jwk the JSON Web Key
-		 * @return the {@link Builder}
-		 */
-		public Builder jwk(Map<String, Object> jwk) {
-			return header(JoseHeaderNames.JWK, jwk);
-		}
-
-		/**
-		 * Sets the key ID that is a hint indicating which key was used to secure the JWS or JWE.
-		 *
-		 * @param keyId the key ID
-		 * @return the {@link Builder}
-		 */
-		public Builder keyId(String keyId) {
-			return header(JoseHeaderNames.KID, keyId);
-		}
-
-		/**
-		 * Sets the X.509 URL that refers to the resource for the X.509 public key certificate
-		 * or certificate chain corresponding to the key used to digitally sign the JWS or encrypt the JWE.
-		 *
-		 * @param x509Url the X.509 URL
-		 * @return the {@link Builder}
-		 */
-		public Builder x509Url(String x509Url) {
-			return header(JoseHeaderNames.X5U, convertAsURL(JoseHeaderNames.X5U, x509Url));
-		}
-
-		/**
-		 * Sets the X.509 certificate chain that contains the X.509 public key certificate
-		 * or certificate chain corresponding to the key used to digitally sign the JWS or
-		 * encrypt the JWE. The certificate or certificate chain is represented as a
-		 * {@code List} of certificate value {@code String}s. Each {@code String} in the
-		 * {@code List} is a Base64-encoded DER PKIX certificate value.
-		 *
-		 * @param x509CertificateChain the X.509 certificate chain
-		 * @return the {@link Builder}
-		 */
-		public Builder x509CertificateChain(List<String> x509CertificateChain) {
-			return header(JoseHeaderNames.X5C, x509CertificateChain);
-		}
-
-		/**
-		 * Sets the X.509 certificate SHA-1 thumbprint that is a base64url-encoded SHA-1 thumbprint (a.k.a. digest)
-		 * of the DER encoding of the X.509 certificate corresponding to the key used to digitally sign the JWS or encrypt the JWE.
-		 *
-		 * @param x509SHA1Thumbprint the X.509 certificate SHA-1 thumbprint
-		 * @return the {@link Builder}
-		 */
-		public Builder x509SHA1Thumbprint(String x509SHA1Thumbprint) {
-			return header(JoseHeaderNames.X5T, x509SHA1Thumbprint);
-		}
-
-		/**
-		 * Sets the X.509 certificate SHA-256 thumbprint that is a base64url-encoded SHA-256 thumbprint (a.k.a. digest)
-		 * of the DER encoding of the X.509 certificate corresponding to the key used to digitally sign the JWS or encrypt the JWE.
-		 *
-		 * @param x509SHA256Thumbprint the X.509 certificate SHA-256 thumbprint
-		 * @return the {@link Builder}
-		 */
-		public Builder x509SHA256Thumbprint(String x509SHA256Thumbprint) {
-			return header(JoseHeaderNames.X5T_S256, x509SHA256Thumbprint);
-		}
-
-		/**
-		 * Sets the type header that declares the media type of the JWS/JWE.
-		 *
-		 * @param type the type header
-		 * @return the {@link Builder}
-		 */
-		public Builder type(String type) {
-			return header(JoseHeaderNames.TYP, type);
-		}
-
-		/**
-		 * Sets the content type header that declares the media type of the secured content (the payload).
-		 *
-		 * @param contentType the content type header
-		 * @return the {@link Builder}
-		 */
-		public Builder contentType(String contentType) {
-			return header(JoseHeaderNames.CTY, contentType);
-		}
-
-		/**
-		 * Sets the critical headers that indicates which extensions to the JWS/JWE/JWA specifications
-		 * are being used that MUST be understood and processed.
-		 *
-		 * @param headerNames the critical header names
-		 * @return the {@link Builder}
-		 */
-		public Builder critical(Set<String> headerNames) {
-			return header(JoseHeaderNames.CRIT, headerNames);
-		}
-
-		/**
-		 * Sets the header.
-		 *
-		 * @param name the header name
-		 * @param value the header value
-		 * @return the {@link Builder}
-		 */
-		public Builder header(String name, Object value) {
-			Assert.hasText(name, "name cannot be empty");
-			Assert.notNull(value, "value cannot be null");
-			this.headers.put(name, value);
-			return this;
-		}
-
-		/**
-		 * A {@code Consumer} to be provided access to the headers
-		 * allowing the ability to add, replace, or remove.
-		 *
-		 * @param headersConsumer a {@code Consumer} of the headers
-		 * @return the {@link Builder}
-		 */
-		public Builder headers(Consumer<Map<String, Object>> headersConsumer) {
-			headersConsumer.accept(this.headers);
-			return this;
-		}
-
-		/**
-		 * Builds a new {@link JoseHeader}.
-		 *
-		 * @return a {@link JoseHeader}
-		 */
-		public JoseHeader build() {
-			Assert.notEmpty(this.headers, "headers cannot be empty");
-			return new JoseHeader(this.headers);
-		}
-
-		private static URL convertAsURL(String header, String value) {
-			URL convertedValue = ClaimConversionService.getSharedInstance().convert(value, URL.class);
-			Assert.isTrue(convertedValue != null,
-					() -> "Unable to convert header '" + header + "' of type '" + value.getClass() + "' to URL.");
-			return convertedValue;
-		}
-
-	}
-}

+ 0 - 101
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JoseHeaderNames.java

@@ -1,101 +0,0 @@
-/*
- * Copyright 2020-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-/**
- * The Registered Header Parameter Names defined by the JSON Web Token (JWT),
- * JSON Web Signature (JWS) and JSON Web Encryption (JWE) specifications
- * that may be contained in the JOSE Header of a JWT.
- *
- * @author Anoop Garlapati
- * @author Joe Grandja
- * @since 0.0.1
- * @see JoseHeader
- * @see <a target="_blank" href="https://tools.ietf.org/html/rfc7519#section-5">JWT JOSE Header</a>
- * @see <a target="_blank" href="https://tools.ietf.org/html/rfc7515#section-4">JWS JOSE Header</a>
- * @see <a target="_blank" href="https://tools.ietf.org/html/rfc7516#section-4">JWE JOSE Header</a>
- * @deprecated See <a target="_blank" href="https://github.com/spring-projects/spring-authorization-server/issues/596">gh-596</a>
- */
-@Deprecated
-public final class JoseHeaderNames {
-
-	/**
-	 * {@code alg} - the algorithm header identifies the cryptographic algorithm used to secure a JWS or JWE
-	 */
-	public static final String ALG = "alg";
-
-	/**
-	 * {@code jku} - the JWK Set URL header is a URI that refers to a resource for a set of JSON-encoded public keys,
-	 * one of which corresponds to the key used to digitally sign a JWS or encrypt a JWE
-	 */
-	public static final String JKU = "jku";
-
-	/**
-	 * {@code jwk} - the JSON Web Key header is the public key that corresponds to the key
-	 * used to digitally sign a JWS or encrypt a JWE
-	 */
-	public static final String JWK = "jwk";
-
-	/**
-	 * {@code kid} - the key ID header is a hint indicating which key was used to secure a JWS or JWE
-	 */
-	public static final String KID = "kid";
-
-	/**
-	 * {@code x5u} - the X.509 URL header is a URI that refers to a resource for the X.509 public key certificate
-	 * or certificate chain corresponding to the key used to digitally sign a JWS or encrypt a JWE
-	 */
-	public static final String X5U = "x5u";
-
-	/**
-	 * {@code x5c} - the X.509 certificate chain header contains the X.509 public key certificate
-	 * or certificate chain corresponding to the key used to digitally sign a JWS or encrypt a JWE
-	 */
-	public static final String X5C = "x5c";
-
-	/**
-	 * {@code x5t} - the X.509 certificate SHA-1 thumbprint header is a base64url-encoded SHA-1 thumbprint (a.k.a. digest)
-	 * of the DER encoding of the X.509 certificate corresponding to the key used to digitally sign a JWS or encrypt a JWE
-	 */
-	public static final String X5T = "x5t";
-
-	/**
-	 * {@code x5t#S256} - the X.509 certificate SHA-256 thumbprint header is a base64url-encoded SHA-256 thumbprint (a.k.a. digest)
-	 * of the DER encoding of the X.509 certificate corresponding to the key used to digitally sign a JWS or encrypt a JWE
-	 */
-	public static final String X5T_S256 = "x5t#S256";
-
-	/**
-	 * {@code typ} - the type header is used by JWS/JWE applications to declare the media type of a JWS/JWE
-	 */
-	public static final String TYP = "typ";
-
-	/**
-	 * {@code cty} - the content type header is used by JWS/JWE applications to declare the media type
-	 * of the secured content (the payload)
-	 */
-	public static final String CTY = "cty";
-
-	/**
-	 * {@code crit} - the critical header indicates that extensions to the JWS/JWE/JWA specifications
-	 * are being used that MUST be understood and processed
-	 */
-	public static final String CRIT = "crit";
-
-	private JoseHeaderNames() {
-	}
-
-}

+ 0 - 204
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimsSet.java

@@ -1,204 +0,0 @@
-/*
- * Copyright 2020-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-import java.net.URL;
-import java.time.Instant;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
-import org.springframework.security.oauth2.core.converter.ClaimConversionService;
-import org.springframework.util.Assert;
-
-/**
- * The {@link Jwt JWT} Claims Set is a JSON object representing the claims conveyed by a JSON Web Token.
- *
- * @author Anoop Garlapati
- * @author Joe Grandja
- * @since 0.0.1
- * @see Jwt
- * @see JwtClaimAccessor
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7519#section-4">JWT Claims Set</a>
- * @deprecated See <a target="_blank" href="https://github.com/spring-projects/spring-authorization-server/issues/596">gh-596</a>
- */
-@Deprecated
-public final class JwtClaimsSet implements JwtClaimAccessor {
-	private final Map<String, Object> claims;
-
-	private JwtClaimsSet(Map<String, Object> claims) {
-		this.claims = Collections.unmodifiableMap(new HashMap<>(claims));
-	}
-
-	@Override
-	public Map<String, Object> getClaims() {
-		return this.claims;
-	}
-
-	/**
-	 * Returns a new {@link Builder}.
-	 *
-	 * @return the {@link Builder}
-	 */
-	public static Builder builder() {
-		return new Builder();
-	}
-
-	/**
-	 * Returns a new {@link Builder}, initialized with the provided {@code claims}.
-	 *
-	 * @param claims a JWT claims set
-	 * @return the {@link Builder}
-	 */
-	public static Builder from(JwtClaimsSet claims) {
-		return new Builder(claims);
-	}
-
-	/**
-	 * A builder for {@link JwtClaimsSet}.
-	 */
-	public static final class Builder {
-		private final Map<String, Object> claims = new HashMap<>();
-
-		private Builder() {
-		}
-
-		private Builder(JwtClaimsSet claims) {
-			Assert.notNull(claims, "claims cannot be null");
-			this.claims.putAll(claims.getClaims());
-		}
-
-		/**
-		 * Sets the issuer {@code (iss)} claim, which identifies the principal that issued the JWT.
-		 *
-		 * @param issuer the issuer identifier
-		 * @return the {@link Builder}
-		 */
-		public Builder issuer(String issuer) {
-			return claim(JwtClaimNames.ISS, issuer);
-		}
-
-		/**
-		 * Sets the subject {@code (sub)} claim, which identifies the principal that is the subject of the JWT.
-		 *
-		 * @param subject the subject identifier
-		 * @return the {@link Builder}
-		 */
-		public Builder subject(String subject) {
-			return claim(JwtClaimNames.SUB, subject);
-		}
-
-		/**
-		 * Sets the audience {@code (aud)} claim, which identifies the recipient(s) that the JWT is intended for.
-		 *
-		 * @param audience the audience that this JWT is intended for
-		 * @return the {@link Builder}
-		 */
-		public Builder audience(List<String> audience) {
-			return claim(JwtClaimNames.AUD, audience);
-		}
-
-		/**
-		 * Sets the expiration time {@code (exp)} claim, which identifies the time
-		 * on or after which the JWT MUST NOT be accepted for processing.
-		 *
-		 * @param expiresAt the time on or after which the JWT MUST NOT be accepted for processing
-		 * @return the {@link Builder}
-		 */
-		public Builder expiresAt(Instant expiresAt) {
-			return claim(JwtClaimNames.EXP, expiresAt);
-		}
-
-		/**
-		 * Sets the not before {@code (nbf)} claim, which identifies the time
-		 * before which the JWT MUST NOT be accepted for processing.
-		 *
-		 * @param notBefore the time before which the JWT MUST NOT be accepted for processing
-		 * @return the {@link Builder}
-		 */
-		public Builder notBefore(Instant notBefore) {
-			return claim(JwtClaimNames.NBF, notBefore);
-		}
-
-		/**
-		 * Sets the issued at {@code (iat)} claim, which identifies the time at which the JWT was issued.
-		 *
-		 * @param issuedAt the time at which the JWT was issued
-		 * @return the {@link Builder}
-		 */
-		public Builder issuedAt(Instant issuedAt) {
-			return claim(JwtClaimNames.IAT, issuedAt);
-		}
-
-		/**
-		 * Sets the JWT ID {@code (jti)} claim, which provides a unique identifier for the JWT.
-		 *
-		 * @param jti the unique identifier for the JWT
-		 * @return the {@link Builder}
-		 */
-		public Builder id(String jti) {
-			return claim(JwtClaimNames.JTI, jti);
-		}
-
-		/**
-		 * Sets the claim.
-		 *
-		 * @param name the claim name
-		 * @param value the claim value
-		 * @return the {@link Builder}
-		 */
-		public Builder claim(String name, Object value) {
-			Assert.hasText(name, "name cannot be empty");
-			Assert.notNull(value, "value cannot be null");
-			this.claims.put(name, value);
-			return this;
-		}
-
-		/**
-		 * A {@code Consumer} to be provided access to the claims
-		 * allowing the ability to add, replace, or remove.
-		 *
-		 * @param claimsConsumer a {@code Consumer} of the claims
-		 */
-		public Builder claims(Consumer<Map<String, Object>> claimsConsumer) {
-			claimsConsumer.accept(this.claims);
-			return this;
-		}
-
-		/**
-		 * Builds a new {@link JwtClaimsSet}.
-		 *
-		 * @return a {@link JwtClaimsSet}
-		 */
-		public JwtClaimsSet build() {
-			Assert.notEmpty(this.claims, "claims cannot be empty");
-
-			// The value of the 'iss' claim is a String or URL (StringOrURI).
-			// Attempt to convert to URL.
-			Object issuer = this.claims.get(JwtClaimNames.ISS);
-			if (issuer != null) {
-				URL convertedValue = ClaimConversionService.getSharedInstance().convert(issuer, URL.class);
-				if (convertedValue != null) {
-					this.claims.put(JwtClaimNames.ISS, convertedValue);
-				}
-			}
-
-			return new JwtClaimsSet(this.claims);
-		}
-	}
-}

+ 0 - 56
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JwtEncoder.java

@@ -1,56 +0,0 @@
-/*
- * Copyright 2020-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-/**
- * Implementations of this interface are responsible for encoding
- * a JSON Web Token (JWT) to it's compact claims representation format.
- *
- * <p>
- * JWTs may be represented using the JWS Compact Serialization format for a
- * JSON Web Signature (JWS) structure or JWE Compact Serialization format for a
- * JSON Web Encryption (JWE) structure. Therefore, implementors are responsible
- * for signing a JWS and/or encrypting a JWE.
- *
- * @author Anoop Garlapati
- * @author Joe Grandja
- * @since 0.0.1
- * @see Jwt
- * @see JoseHeader
- * @see JwtClaimsSet
- * @see JwtDecoder
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7519">JSON Web Token (JWT)</a>
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7515">JSON Web Signature (JWS)</a>
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7516">JSON Web Encryption (JWE)</a>
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7515#section-3.1">JWS Compact Serialization</a>
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7516#section-3.1">JWE Compact Serialization</a>
- * @deprecated See <a target="_blank" href="https://github.com/spring-projects/spring-authorization-server/issues/596">gh-596</a>
- */
-@Deprecated
-@FunctionalInterface
-public interface JwtEncoder {
-
-	/**
-	 * Encode the JWT to it's compact claims representation format.
-	 *
-	 * @param headers the JOSE header
-	 * @param claims the JWT Claims Set
-	 * @return a {@link Jwt}
-	 * @throws JwtEncodingException if an error occurs while attempting to encode the JWT
-	 */
-	Jwt encode(JoseHeader headers, JwtClaimsSet claims) throws JwtEncodingException;
-
-}

+ 0 - 48
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JwtEncodingException.java

@@ -1,48 +0,0 @@
-/*
- * Copyright 2020-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-/**
- * This exception is thrown when an error occurs
- * while attempting to encode a JSON Web Token (JWT).
- *
- * @author Joe Grandja
- * @since 0.0.1
- * @deprecated See <a target="_blank" href="https://github.com/spring-projects/spring-authorization-server/issues/596">gh-596</a>
- */
-@Deprecated
-public class JwtEncodingException extends JwtException {
-
-	/**
-	 * Constructs a {@code JwtEncodingException} using the provided parameters.
-	 *
-	 * @param message the detail message
-	 */
-	public JwtEncodingException(String message) {
-		super(message);
-	}
-
-	/**
-	 * Constructs a {@code JwtEncodingException} using the provided parameters.
-	 *
-	 * @param message the detail message
-	 * @param cause the root cause
-	 */
-	public JwtEncodingException(String message, Throwable cause) {
-		super(message, cause);
-	}
-
-}

+ 0 - 344
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwsEncoder.java

@@ -1,344 +0,0 @@
-/*
- * Copyright 2020-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-import java.net.URI;
-import java.net.URL;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.JOSEObjectType;
-import com.nimbusds.jose.JWSAlgorithm;
-import com.nimbusds.jose.JWSHeader;
-import com.nimbusds.jose.JWSSigner;
-import com.nimbusds.jose.crypto.factories.DefaultJWSSignerFactory;
-import com.nimbusds.jose.jwk.JWK;
-import com.nimbusds.jose.jwk.JWKMatcher;
-import com.nimbusds.jose.jwk.JWKSelector;
-import com.nimbusds.jose.jwk.KeyType;
-import com.nimbusds.jose.jwk.KeyUse;
-import com.nimbusds.jose.jwk.source.JWKSource;
-import com.nimbusds.jose.proc.SecurityContext;
-import com.nimbusds.jose.produce.JWSSignerFactory;
-import com.nimbusds.jose.util.Base64;
-import com.nimbusds.jose.util.Base64URL;
-import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.SignedJWT;
-
-import org.springframework.core.convert.converter.Converter;
-import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
-
-/**
- * An implementation of a {@link JwtEncoder} that encodes a JSON Web Token (JWT) using the
- * JSON Web Signature (JWS) Compact Serialization format. The private/secret key used for
- * signing the JWS is supplied by the {@code com.nimbusds.jose.jwk.source.JWKSource}
- * provided via the constructor.
- *
- * <p>
- * <b>NOTE:</b> This implementation uses the Nimbus JOSE + JWT SDK.
- *
- * @author Joe Grandja
- * @since 0.0.1
- * @see JwtEncoder
- * @see com.nimbusds.jose.jwk.source.JWKSource
- * @see com.nimbusds.jose.jwk.JWK
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7519">JSON Web Token (JWT)</a>
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7515">JSON Web Signature (JWS)</a>
- * @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7515#section-3.1">JWS Compact Serialization</a>
- * @see <a target="_blank" href="https://connect2id.com/products/nimbus-jose-jwt">Nimbus JOSE + JWT SDK</a>
- * @deprecated See <a target="_blank" href="https://github.com/spring-projects/spring-authorization-server/issues/596">gh-596</a>
- */
-@Deprecated
-public final class NimbusJwsEncoder implements JwtEncoder {
-	private static final String ENCODING_ERROR_MESSAGE_TEMPLATE = "An error occurred while attempting to encode the Jwt: %s";
-	private static final Converter<JoseHeader, JWSHeader> JWS_HEADER_CONVERTER = new JwsHeaderConverter();
-	private static final Converter<JwtClaimsSet, JWTClaimsSet> JWT_CLAIMS_SET_CONVERTER = new JwtClaimsSetConverter();
-	private static final JWSSignerFactory JWS_SIGNER_FACTORY = new DefaultJWSSignerFactory();
-	private final Map<JWK, JWSSigner> jwsSigners = new ConcurrentHashMap<>();
-	private final JWKSource<SecurityContext> jwkSource;
-
-	/**
-	 * Constructs a {@code NimbusJwsEncoder} using the provided parameters.
-	 * @param jwkSource the {@code com.nimbusds.jose.jwk.source.JWKSource}
-	 */
-	public NimbusJwsEncoder(JWKSource<SecurityContext> jwkSource) {
-		Assert.notNull(jwkSource, "jwkSource cannot be null");
-		this.jwkSource = jwkSource;
-	}
-
-	@Override
-	public Jwt encode(JoseHeader headers, JwtClaimsSet claims) throws JwtEncodingException {
-		Assert.notNull(headers, "headers cannot be null");
-		Assert.notNull(claims, "claims cannot be null");
-
-		JWK jwk = selectJwk(headers);
-		headers = addKeyIdentifierHeadersIfNecessary(headers, jwk);
-
-		String jws = serialize(headers, claims, jwk);
-
-		return new Jwt(jws, claims.getIssuedAt(), claims.getExpiresAt(), headers.getHeaders(), claims.getClaims());
-	}
-
-	private JWK selectJwk(JoseHeader headers) {
-		List<JWK> jwks;
-		try {
-			JWKSelector jwkSelector = new JWKSelector(createJwkMatcher(headers));
-			jwks = this.jwkSource.get(jwkSelector, null);
-		} catch (Exception ex) {
-			throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
-					"Failed to select a JWK signing key -> " + ex.getMessage()), ex);
-		}
-
-		if (jwks.size() > 1) {
-			throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
-					"Found multiple JWK signing keys for algorithm '" + headers.getAlgorithm().getName() + "'"));
-		}
-
-		if (jwks.isEmpty()) {
-			throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
-					"Failed to select a JWK signing key"));
-		}
-
-		return jwks.get(0);
-	}
-
-	private String serialize(JoseHeader headers, JwtClaimsSet claims, JWK jwk) {
-		JWSHeader jwsHeader = JWS_HEADER_CONVERTER.convert(headers);
-		JWTClaimsSet jwtClaimsSet = JWT_CLAIMS_SET_CONVERTER.convert(claims);
-
-		JWSSigner jwsSigner = this.jwsSigners.computeIfAbsent(jwk, NimbusJwsEncoder::createSigner);
-
-		SignedJWT signedJwt = new SignedJWT(jwsHeader, jwtClaimsSet);
-		try {
-			signedJwt.sign(jwsSigner);
-		} catch (JOSEException ex) {
-			throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
-					"Failed to sign the JWT -> " + ex.getMessage()), ex);
-		}
-		return signedJwt.serialize();
-	}
-
-	private static JWKMatcher createJwkMatcher(JoseHeader headers) {
-		JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(headers.getAlgorithm().getName());
-
-		if (JWSAlgorithm.Family.RSA.contains(jwsAlgorithm) || JWSAlgorithm.Family.EC.contains(jwsAlgorithm)) {
-			// @formatter:off
-			return new JWKMatcher.Builder()
-					.keyType(KeyType.forAlgorithm(jwsAlgorithm))
-					.keyID(headers.getKeyId())
-					.keyUses(KeyUse.SIGNATURE, null)
-					.algorithms(jwsAlgorithm, null)
-					.x509CertSHA256Thumbprint(Base64URL.from(headers.getX509SHA256Thumbprint()))
-					.build();
-			// @formatter:on
-		} else if (JWSAlgorithm.Family.HMAC_SHA.contains(jwsAlgorithm)) {
-			// @formatter:off
-			return new JWKMatcher.Builder()
-					.keyType(KeyType.forAlgorithm(jwsAlgorithm))
-					.keyID(headers.getKeyId())
-					.privateOnly(true)
-					.algorithms(jwsAlgorithm, null)
-					.build();
-			// @formatter:on
-		}
-
-		return null;
-	}
-
-	private static JoseHeader addKeyIdentifierHeadersIfNecessary(JoseHeader headers, JWK jwk) {
-		// Check if headers have already been added
-		if (StringUtils.hasText(headers.getKeyId()) && StringUtils.hasText(headers.getX509SHA256Thumbprint())) {
-			return headers;
-		}
-		// Check if headers can be added from JWK
-		if (!StringUtils.hasText(jwk.getKeyID()) && jwk.getX509CertSHA256Thumbprint() == null) {
-			return headers;
-		}
-
-		JoseHeader.Builder headersBuilder = JoseHeader.from(headers);
-		if (!StringUtils.hasText(headers.getKeyId()) && StringUtils.hasText(jwk.getKeyID())) {
-			headersBuilder.keyId(jwk.getKeyID());
-		}
-		if (!StringUtils.hasText(headers.getX509SHA256Thumbprint()) && jwk.getX509CertSHA256Thumbprint() != null) {
-			headersBuilder.x509SHA256Thumbprint(jwk.getX509CertSHA256Thumbprint().toString());
-		}
-
-		return headersBuilder.build();
-	}
-
-	private static JWSSigner createSigner(JWK jwk) {
-		try {
-			return JWS_SIGNER_FACTORY.createJWSSigner(jwk);
-		} catch (JOSEException ex) {
-			throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
-					"Failed to create a JWS Signer -> " + ex.getMessage()), ex);
-		}
-	}
-
-	private static class JwsHeaderConverter implements Converter<JoseHeader, JWSHeader> {
-
-		@Override
-		public JWSHeader convert(JoseHeader headers) {
-			JWSHeader.Builder builder = new JWSHeader.Builder(JWSAlgorithm.parse(headers.getAlgorithm().getName()));
-
-			if (headers.getJwkSetUrl() != null) {
-				builder.jwkURL(convertAsURI(JoseHeaderNames.JKU, headers.getJwkSetUrl()));
-			}
-
-			Map<String, Object> jwk = headers.getJwk();
-			if (!CollectionUtils.isEmpty(jwk)) {
-				try {
-					builder.jwk(JWK.parse(jwk));
-				} catch (Exception ex) {
-					throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
-							"Unable to convert '" + JoseHeaderNames.JWK + "' JOSE header"), ex);
-				}
-			}
-
-			String keyId = headers.getKeyId();
-			if (StringUtils.hasText(keyId)) {
-				builder.keyID(keyId);
-			}
-
-			if (headers.getX509Url() != null) {
-				builder.x509CertURL(convertAsURI(JoseHeaderNames.X5U, headers.getX509Url()));
-			}
-
-			List<String> x509CertificateChain = headers.getX509CertificateChain();
-			if (!CollectionUtils.isEmpty(x509CertificateChain)) {
-				List<Base64> x5cList = new ArrayList<>();
-				x509CertificateChain.forEach((x5c) -> x5cList.add(new Base64(x5c)));
-				if (!x5cList.isEmpty()) {
-					builder.x509CertChain(x5cList);
-				}
-			}
-
-			String x509SHA1Thumbprint = headers.getX509SHA1Thumbprint();
-			if (StringUtils.hasText(x509SHA1Thumbprint)) {
-				builder.x509CertThumbprint(new Base64URL(x509SHA1Thumbprint));
-			}
-
-			String x509SHA256Thumbprint = headers.getX509SHA256Thumbprint();
-			if (StringUtils.hasText(x509SHA256Thumbprint)) {
-				builder.x509CertSHA256Thumbprint(new Base64URL(x509SHA256Thumbprint));
-			}
-
-			String type = headers.getType();
-			if (StringUtils.hasText(type)) {
-				builder.type(new JOSEObjectType(type));
-			}
-
-			String contentType = headers.getContentType();
-			if (StringUtils.hasText(contentType)) {
-				builder.contentType(contentType);
-			}
-
-			Set<String> critical = headers.getCritical();
-			if (!CollectionUtils.isEmpty(critical)) {
-				builder.criticalParams(critical);
-			}
-
-			Map<String, Object> customHeaders = new HashMap<>();
-			headers.getHeaders().forEach((name, value) -> {
-				if (!JWSHeader.getRegisteredParameterNames().contains(name)) {
-					customHeaders.put(name, value);
-				}
-			});
-			if (!customHeaders.isEmpty()) {
-				builder.customParams(customHeaders);
-			}
-
-			return builder.build();
-		}
-
-		private static URI convertAsURI(String header, URL url) {
-			try {
-				return url.toURI();
-			} catch (Exception ex) {
-				throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
-						"Unable to convert '" + header + "' JOSE header to a URI"), ex);
-			}
-		}
-
-	}
-
-	private static class JwtClaimsSetConverter implements Converter<JwtClaimsSet, JWTClaimsSet> {
-
-		@Override
-		public JWTClaimsSet convert(JwtClaimsSet claims) {
-			JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
-
-			// NOTE: The value of the 'iss' claim is a String or URL (StringOrURI).
-			Object issuer = claims.getClaim(JwtClaimNames.ISS);
-			if (issuer != null) {
-				builder.issuer(issuer.toString());
-			}
-
-			String subject = claims.getSubject();
-			if (StringUtils.hasText(subject)) {
-				builder.subject(subject);
-			}
-
-			List<String> audience = claims.getAudience();
-			if (!CollectionUtils.isEmpty(audience)) {
-				builder.audience(audience);
-			}
-
-			Instant expiresAt = claims.getExpiresAt();
-			if (expiresAt != null) {
-				builder.expirationTime(Date.from(expiresAt));
-			}
-
-			Instant notBefore = claims.getNotBefore();
-			if (notBefore != null) {
-				builder.notBeforeTime(Date.from(notBefore));
-			}
-
-			Instant issuedAt = claims.getIssuedAt();
-			if (issuedAt != null) {
-				builder.issueTime(Date.from(issuedAt));
-			}
-
-			String jwtId = claims.getId();
-			if (StringUtils.hasText(jwtId)) {
-				builder.jwtID(jwtId);
-			}
-
-			Map<String, Object> customClaims = new HashMap<>();
-			claims.getClaims().forEach((name, value) -> {
-				if (!JWTClaimsSet.getRegisteredNames().contains(name)) {
-					customClaims.put(name, value);
-				}
-			});
-			if (!customClaims.isEmpty()) {
-				customClaims.forEach(builder::claim);
-			}
-
-			return builder.build();
-		}
-
-	}
-
-}

+ 15 - 14
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContext.java

@@ -21,10 +21,11 @@ import java.util.Map;
 import java.util.function.Consumer;
 
 import org.springframework.lang.Nullable;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
+import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
 import org.springframework.util.Assert;
 
 /**
@@ -33,9 +34,9 @@ import org.springframework.util.Assert;
  * @author Joe Grandja
  * @since 0.1.0
  * @see OAuth2TokenContext
- * @see JoseHeader.Builder
+ * @see JwsHeader.Builder
  * @see JwtClaimsSet.Builder
- * @see JwtEncoder#encode(JoseHeader, JwtClaimsSet)
+ * @see JwtEncoder#encode(JwtEncoderParameters)
  */
 public final class JwtEncodingContext implements OAuth2TokenContext {
 	private final Map<Object, Object> context;
@@ -58,13 +59,13 @@ public final class JwtEncodingContext implements OAuth2TokenContext {
 	}
 
 	/**
-	 * Returns the {@link JoseHeader.Builder headers}
+	 * Returns the {@link JwsHeader.Builder headers}
 	 * allowing the ability to add, replace, or remove.
 	 *
-	 * @return the {@link JoseHeader.Builder}
+	 * @return the {@link JwsHeader.Builder}
 	 */
-	public JoseHeader.Builder getHeaders() {
-		return get(JoseHeader.Builder.class);
+	public JwsHeader.Builder getHeaders() {
+		return get(JwsHeader.Builder.class);
 	}
 
 	/**
@@ -84,7 +85,7 @@ public final class JwtEncodingContext implements OAuth2TokenContext {
 	 * @param claimsBuilder the claims to initialize the builder
 	 * @return the {@link Builder}
 	 */
-	public static Builder with(JoseHeader.Builder headersBuilder, JwtClaimsSet.Builder claimsBuilder) {
+	public static Builder with(JwsHeader.Builder headersBuilder, JwtClaimsSet.Builder claimsBuilder) {
 		return new Builder(headersBuilder, claimsBuilder);
 	}
 
@@ -93,24 +94,24 @@ public final class JwtEncodingContext implements OAuth2TokenContext {
 	 */
 	public static final class Builder extends AbstractBuilder<JwtEncodingContext, Builder> {
 
-		private Builder(JoseHeader.Builder headersBuilder, JwtClaimsSet.Builder claimsBuilder) {
+		private Builder(JwsHeader.Builder headersBuilder, JwtClaimsSet.Builder claimsBuilder) {
 			Assert.notNull(headersBuilder, "headersBuilder cannot be null");
 			Assert.notNull(claimsBuilder, "claimsBuilder cannot be null");
-			put(JoseHeader.Builder.class, headersBuilder);
+			put(JwsHeader.Builder.class, headersBuilder);
 			put(JwtClaimsSet.Builder.class, claimsBuilder);
 		}
 
 		/**
-		 * A {@code Consumer} of the {@link JoseHeader.Builder headers}
+		 * A {@code Consumer} of the {@link JwsHeader.Builder headers}
 		 * allowing the ability to add, replace, or remove.
 		 *
 		 * @deprecated Use {@link #getHeaders()} instead
-		 * @param headersConsumer a {@code Consumer} of the {@link JoseHeader.Builder headers}
+		 * @param headersConsumer a {@code Consumer} of the {@link JwsHeader.Builder headers}
 		 * @return the {@link Builder} for further configuration
 		 */
 		@Deprecated
-		public Builder headers(Consumer<JoseHeader.Builder> headersConsumer) {
-			headersConsumer.accept(get(JoseHeader.Builder.class));
+		public Builder headers(Consumer<JwsHeader.Builder> headersConsumer) {
+			headersConsumer.accept(get(JwsHeader.Builder.class));
 			return this;
 		}
 

+ 5 - 4
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/JwtGenerator.java

@@ -30,10 +30,11 @@ import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
 import org.springframework.security.oauth2.core.oidc.OidcIdToken;
 import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
 import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
+import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
 import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
@@ -127,7 +128,7 @@ public final class JwtGenerator implements OAuth2TokenGenerator<Jwt> {
 		}
 		// @formatter:on
 
-		JoseHeader.Builder headersBuilder = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256);
+		JwsHeader.Builder headersBuilder = JwsHeader.with(SignatureAlgorithm.RS256);
 
 		if (this.jwtCustomizer != null) {
 			// @formatter:off
@@ -150,10 +151,10 @@ public final class JwtGenerator implements OAuth2TokenGenerator<Jwt> {
 			this.jwtCustomizer.customize(jwtContext);
 		}
 
-		JoseHeader headers = headersBuilder.build();
+		JwsHeader headers = headersBuilder.build();
 		JwtClaimsSet claims = claimsBuilder.build();
 
-		Jwt jwt = this.jwtEncoder.encode(headers, claims);
+		Jwt jwt = this.jwtEncoder.encode(JwtEncoderParameters.from(headers, claims));
 
 		return jwt;
 	}

+ 3 - 3
oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationCodeGrantTests.java

@@ -81,7 +81,7 @@ import org.springframework.security.oauth2.jose.TestJwks;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.jwt.NimbusJwsEncoder;
+import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
 import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationConsentService;
 import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
@@ -161,7 +161,7 @@ public class OAuth2AuthorizationCodeGrantTests {
 
 	private static EmbeddedDatabase db;
 	private static JWKSource<SecurityContext> jwkSource;
-	private static NimbusJwsEncoder jwtEncoder;
+	private static NimbusJwtEncoder jwtEncoder;
 	private static ProviderSettings providerSettings;
 	private static HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
 			new OAuth2AccessTokenResponseHttpMessageConverter();
@@ -197,7 +197,7 @@ public class OAuth2AuthorizationCodeGrantTests {
 	public static void init() {
 		JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
 		jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
-		jwtEncoder = new NimbusJwsEncoder(jwkSource);
+		jwtEncoder = new NimbusJwtEncoder(jwkSource);
 		providerSettings = ProviderSettings.builder()
 				.authorizationEndpoint("/test/authorize")
 				.tokenEndpoint("/test/token")

+ 7 - 6
oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcClientRegistrationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 the original author or authors.
+ * Copyright 2020-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -64,12 +64,13 @@ import org.springframework.security.oauth2.core.oidc.OidcClientRegistration;
 import org.springframework.security.oauth2.core.oidc.http.converter.OidcClientRegistrationHttpMessageConverter;
 import org.springframework.security.oauth2.jose.TestJwks;
 import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.jwt.NimbusJwsEncoder;
+import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
+import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
 import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
 import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
@@ -135,7 +136,7 @@ public class OidcClientRegistrationTests {
 		JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
 		jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
 		clientJwkSet = new JWKSet(TestJwks.generateRsaJwk().build());
-		jwtClientAssertionEncoder = new NimbusJwsEncoder((jwkSelector, securityContext) -> jwkSelector.select(clientJwkSet));
+		jwtClientAssertionEncoder = new NimbusJwtEncoder((jwkSelector, securityContext) -> jwkSelector.select(clientJwkSet));
 		db = new EmbeddedDatabaseBuilder()
 				.generateUniqueName(true)
 				.setType(EmbeddedDatabaseType.HSQL)
@@ -280,12 +281,12 @@ public class OidcClientRegistrationTests {
 		this.registeredClientRepository.save(clientRegistrar);
 
 		// @formatter:off
-		JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256)
+		JwsHeader jwsHeader = JwsHeader.with(SignatureAlgorithm.RS256)
 				.build();
 		JwtClaimsSet jwtClaimsSet = jwtClientAssertionClaims(clientRegistrar)
 				.build();
 		// @formatter:on
-		Jwt jwtAssertion = jwtClientAssertionEncoder.encode(joseHeader, jwtClaimsSet);
+		Jwt jwtAssertion = jwtClientAssertionEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet));
 
 		MvcResult mvcResult = this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
 				.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())

+ 6 - 6
oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java

@@ -69,17 +69,13 @@ import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames
 import org.springframework.security.oauth2.jose.TestJwks;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
-import org.springframework.security.oauth2.jwt.NimbusJwsEncoder;
-import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
+import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
 import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
 import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
-import org.springframework.security.oauth2.server.authorization.token.JwtGenerator;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2RefreshTokenGenerator;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
 import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
 import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
@@ -88,6 +84,10 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
 import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
 import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
+import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.JwtGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2RefreshTokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
 import org.springframework.security.web.SecurityFilterChain;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.test.web.servlet.MockMvc;
@@ -415,7 +415,7 @@ public class OidcTests {
 
 		@Bean
 		OAuth2TokenGenerator<?> tokenGenerator() {
-			JwtGenerator jwtGenerator = new JwtGenerator(new NimbusJwsEncoder(jwkSource()));
+			JwtGenerator jwtGenerator = new JwtGenerator(new NimbusJwtEncoder(jwkSource()));
 			jwtGenerator.setJwtCustomizer(jwtCustomizer());
 			OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
 			OAuth2TokenGenerator<OAuth2Token> delegatingTokenGenerator =

+ 7 - 6
oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcUserInfoTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 the original author or authors.
+ * Copyright 2020-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -45,12 +45,13 @@ import org.springframework.security.oauth2.core.oidc.OidcScopes;
 import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
 import org.springframework.security.oauth2.jose.TestJwks;
 import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.jwt.NimbusJwsEncoder;
+import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
+import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
 import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationService;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
@@ -207,13 +208,13 @@ public class OidcUserInfoTests {
 	}
 
 	private OAuth2Authorization createAuthorization() {
-		JoseHeader headers = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
+		JwsHeader headers = JwsHeader.with(SignatureAlgorithm.RS256).build();
 		// @formatter:off
 		JwtClaimsSet claimSet = JwtClaimsSet.builder()
 				.claims(claims -> claims.putAll(createUserInfo().getClaims()))
 				.build();
 		// @formatter:on
-		Jwt jwt = this.jwtEncoder.encode(headers, claimSet);
+		Jwt jwt = this.jwtEncoder.encode(JwtEncoderParameters.from(headers, claimSet));
 
 		Instant now = Instant.now();
 		Set<String> scopes = new HashSet<>(Arrays.asList(
@@ -371,7 +372,7 @@ public class OidcUserInfoTests {
 
 		@Bean
 		JwtEncoder jwtEncoder(JWKSource<SecurityContext> jwkSource) {
-			return new NimbusJwsEncoder(jwkSource);
+			return new NimbusJwtEncoder(jwkSource);
 		}
 
 		@Bean

+ 0 - 108
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/JoseHeaderTests.java

@@ -1,108 +0,0 @@
-/*
- * Copyright 2020-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-import org.junit.Test;
-
-import org.springframework.security.oauth2.jose.JwaAlgorithm;
-import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-/**
- * Tests for {@link JoseHeader}.
- *
- * @author Joe Grandja
- */
-public class JoseHeaderTests {
-
-	@Test
-	public void withAlgorithmWhenNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JoseHeader.withAlgorithm(null))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("jwaAlgorithm cannot be null");
-	}
-
-	@Test
-	public void buildWhenAllHeadersProvidedThenAllHeadersAreSet() {
-		JoseHeader expectedJoseHeader = TestJoseHeaders.joseHeader().build();
-
-		JoseHeader joseHeader = JoseHeader.withAlgorithm(expectedJoseHeader.getAlgorithm())
-				.jwkSetUrl(expectedJoseHeader.getJwkSetUrl().toExternalForm())
-				.jwk(expectedJoseHeader.getJwk())
-				.keyId(expectedJoseHeader.getKeyId())
-				.x509Url(expectedJoseHeader.getX509Url().toExternalForm())
-				.x509CertificateChain(expectedJoseHeader.getX509CertificateChain())
-				.x509SHA1Thumbprint(expectedJoseHeader.getX509SHA1Thumbprint())
-				.x509SHA256Thumbprint(expectedJoseHeader.getX509SHA256Thumbprint())
-				.type(expectedJoseHeader.getType())
-				.contentType(expectedJoseHeader.getContentType())
-				.headers(headers -> headers.put("custom-header-name", "custom-header-value"))
-				.build();
-
-		assertThat(joseHeader.<JwaAlgorithm>getAlgorithm()).isEqualTo(expectedJoseHeader.getAlgorithm());
-		assertThat(joseHeader.getJwkSetUrl()).isEqualTo(expectedJoseHeader.getJwkSetUrl());
-		assertThat(joseHeader.getJwk()).isEqualTo(expectedJoseHeader.getJwk());
-		assertThat(joseHeader.getKeyId()).isEqualTo(expectedJoseHeader.getKeyId());
-		assertThat(joseHeader.getX509Url()).isEqualTo(expectedJoseHeader.getX509Url());
-		assertThat(joseHeader.getX509CertificateChain()).isEqualTo(expectedJoseHeader.getX509CertificateChain());
-		assertThat(joseHeader.getX509SHA1Thumbprint()).isEqualTo(expectedJoseHeader.getX509SHA1Thumbprint());
-		assertThat(joseHeader.getX509SHA256Thumbprint()).isEqualTo(expectedJoseHeader.getX509SHA256Thumbprint());
-		assertThat(joseHeader.getCritical()).isEqualTo(expectedJoseHeader.getCritical());
-		assertThat(joseHeader.getType()).isEqualTo(expectedJoseHeader.getType());
-		assertThat(joseHeader.getContentType()).isEqualTo(expectedJoseHeader.getContentType());
-		assertThat(joseHeader.<String>getHeader("custom-header-name")).isEqualTo("custom-header-value");
-		assertThat(joseHeader.getHeaders()).isEqualTo(expectedJoseHeader.getHeaders());
-	}
-
-	@Test
-	public void fromWhenNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JoseHeader.from(null))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("headers cannot be null");
-	}
-
-	@Test
-	public void fromWhenHeadersProvidedThenCopied() {
-		JoseHeader expectedJoseHeader = TestJoseHeaders.joseHeader().build();
-		JoseHeader joseHeader = JoseHeader.from(expectedJoseHeader).build();
-		assertThat(joseHeader.getHeaders()).isEqualTo(expectedJoseHeader.getHeaders());
-	}
-
-	@Test
-	public void headerWhenNameNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).header(null, "value"))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("name cannot be empty");
-	}
-
-	@Test
-	public void headerWhenValueNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).header("name", null))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("value cannot be null");
-	}
-
-	@Test
-	public void getHeaderWhenNullThenThrowIllegalArgumentException() {
-		JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
-
-		assertThatThrownBy(() -> joseHeader.getHeader(null))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("name cannot be empty");
-	}
-}

+ 0 - 90
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/JwtClaimsSetTests.java

@@ -1,90 +0,0 @@
-/*
- * Copyright 2020 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-/**
- * Tests for {@link JwtClaimsSet}.
- *
- * @author Joe Grandja
- */
-public class JwtClaimsSetTests {
-
-	@Test
-	public void buildWhenClaimsEmptyThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JwtClaimsSet.builder().build())
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("claims cannot be empty");
-	}
-
-	@Test
-	public void buildWhenAllClaimsProvidedThenAllClaimsAreSet() {
-		JwtClaimsSet expectedJwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-
-		JwtClaimsSet jwtClaimsSet = JwtClaimsSet.builder()
-				.issuer(expectedJwtClaimsSet.getIssuer().toExternalForm())
-				.subject(expectedJwtClaimsSet.getSubject())
-				.audience(expectedJwtClaimsSet.getAudience())
-				.issuedAt(expectedJwtClaimsSet.getIssuedAt())
-				.notBefore(expectedJwtClaimsSet.getNotBefore())
-				.expiresAt(expectedJwtClaimsSet.getExpiresAt())
-				.id(expectedJwtClaimsSet.getId())
-				.claims(claims -> claims.put("custom-claim-name", "custom-claim-value"))
-				.build();
-
-		assertThat(jwtClaimsSet.getIssuer()).isEqualTo(expectedJwtClaimsSet.getIssuer());
-		assertThat(jwtClaimsSet.getSubject()).isEqualTo(expectedJwtClaimsSet.getSubject());
-		assertThat(jwtClaimsSet.getAudience()).isEqualTo(expectedJwtClaimsSet.getAudience());
-		assertThat(jwtClaimsSet.getIssuedAt()).isEqualTo(expectedJwtClaimsSet.getIssuedAt());
-		assertThat(jwtClaimsSet.getNotBefore()).isEqualTo(expectedJwtClaimsSet.getNotBefore());
-		assertThat(jwtClaimsSet.getExpiresAt()).isEqualTo(expectedJwtClaimsSet.getExpiresAt());
-		assertThat(jwtClaimsSet.getId()).isEqualTo(expectedJwtClaimsSet.getId());
-		assertThat(jwtClaimsSet.<String>getClaim("custom-claim-name")).isEqualTo("custom-claim-value");
-		assertThat(jwtClaimsSet.getClaims()).isEqualTo(expectedJwtClaimsSet.getClaims());
-	}
-
-	@Test
-	public void fromWhenNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JwtClaimsSet.from(null))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("claims cannot be null");
-	}
-
-	@Test
-	public void fromWhenClaimsProvidedThenCopied() {
-		JwtClaimsSet expectedJwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-		JwtClaimsSet jwtClaimsSet = JwtClaimsSet.from(expectedJwtClaimsSet).build();
-		assertThat(jwtClaimsSet.getClaims()).isEqualTo(expectedJwtClaimsSet.getClaims());
-	}
-
-	@Test
-	public void claimWhenNameNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JwtClaimsSet.builder().claim(null, "value"))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("name cannot be empty");
-	}
-
-	@Test
-	public void claimWhenValueNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JwtClaimsSet.builder().claim("name", null))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("value cannot be null");
-	}
-}

+ 0 - 275
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwsEncoderTests.java

@@ -1,275 +0,0 @@
-/*
- * Copyright 2020-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.jwt;
-
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import com.nimbusds.jose.KeySourceException;
-import com.nimbusds.jose.jwk.ECKey;
-import com.nimbusds.jose.jwk.JWK;
-import com.nimbusds.jose.jwk.JWKSelector;
-import com.nimbusds.jose.jwk.JWKSet;
-import com.nimbusds.jose.jwk.KeyUse;
-import com.nimbusds.jose.jwk.OctetSequenceKey;
-import com.nimbusds.jose.jwk.RSAKey;
-import com.nimbusds.jose.jwk.source.JWKSource;
-import com.nimbusds.jose.proc.SecurityContext;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import org.springframework.security.oauth2.jose.TestJwks;
-import org.springframework.security.oauth2.jose.TestKeys;
-import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.willAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-
-/**
- * Tests for {@link NimbusJwsEncoder}.
- *
- * @author Joe Grandja
- */
-public class NimbusJwsEncoderTests {
-
-	private List<JWK> jwkList;
-
-	private JWKSource<SecurityContext> jwkSource;
-
-	private NimbusJwsEncoder jwsEncoder;
-
-	@Before
-	public void setUp() {
-		this.jwkList = new ArrayList<>();
-		this.jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(new JWKSet(this.jwkList));
-		this.jwsEncoder = new NimbusJwsEncoder(this.jwkSource);
-	}
-
-	@Test
-	public void constructorWhenJwkSourceNullThenThrowIllegalArgumentException() {
-		assertThatIllegalArgumentException().isThrownBy(() -> new NimbusJwsEncoder(null))
-				.withMessage("jwkSource cannot be null");
-	}
-
-	@Test
-	public void encodeWhenHeadersNullThenThrowIllegalArgumentException() {
-		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-
-		assertThatIllegalArgumentException().isThrownBy(() -> this.jwsEncoder.encode(null, jwtClaimsSet))
-				.withMessage("headers cannot be null");
-	}
-
-	@Test
-	public void encodeWhenClaimsNullThenThrowIllegalArgumentException() {
-		JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
-
-		assertThatIllegalArgumentException().isThrownBy(() -> this.jwsEncoder.encode(joseHeader, null))
-				.withMessage("claims cannot be null");
-	}
-
-	@Test
-	public void encodeWhenJwkSelectFailedThenThrowJwtEncodingException() throws Exception {
-		this.jwkSource = mock(JWKSource.class);
-		this.jwsEncoder = new NimbusJwsEncoder(this.jwkSource);
-		given(this.jwkSource.get(any(), any())).willThrow(new KeySourceException("key source error"));
-
-		JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
-		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-
-		assertThatExceptionOfType(JwtEncodingException.class)
-				.isThrownBy(() -> this.jwsEncoder.encode(joseHeader, jwtClaimsSet))
-				.withMessageContaining("Failed to select a JWK signing key -> key source error");
-	}
-
-	@Test
-	public void encodeWhenJwkMultipleSelectedThenThrowJwtEncodingException() throws Exception {
-		RSAKey rsaJwk = TestJwks.DEFAULT_RSA_JWK;
-		this.jwkList.add(rsaJwk);
-		this.jwkList.add(rsaJwk);
-
-		JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
-		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-
-		assertThatExceptionOfType(JwtEncodingException.class)
-				.isThrownBy(() -> this.jwsEncoder.encode(joseHeader, jwtClaimsSet))
-				.withMessageContaining("Found multiple JWK signing keys for algorithm 'RS256'");
-	}
-
-	@Test
-	public void encodeWhenJwkSelectEmptyThenThrowJwtEncodingException() {
-		JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
-		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-
-		assertThatExceptionOfType(JwtEncodingException.class)
-				.isThrownBy(() -> this.jwsEncoder.encode(joseHeader, jwtClaimsSet))
-				.withMessageContaining("Failed to select a JWK signing key");
-	}
-
-	@Test
-	public void encodeWhenJwkUseEncryptionThenThrowJwtEncodingException() throws Exception {
-		// @formatter:off
-		RSAKey rsaJwk = TestJwks.jwk(TestKeys.DEFAULT_PUBLIC_KEY, TestKeys.DEFAULT_PRIVATE_KEY)
-				.keyUse(KeyUse.ENCRYPTION)
-				.build();
-		// @formatter:on
-
-		this.jwkSource = mock(JWKSource.class);
-		this.jwsEncoder = new NimbusJwsEncoder(this.jwkSource);
-		given(this.jwkSource.get(any(), any())).willReturn(Collections.singletonList(rsaJwk));
-
-		JoseHeader joseHeader = TestJoseHeaders.joseHeader().build();
-		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-
-		assertThatExceptionOfType(JwtEncodingException.class)
-				.isThrownBy(() -> this.jwsEncoder.encode(joseHeader, jwtClaimsSet)).withMessageContaining(
-				"Failed to create a JWS Signer -> The JWK use must be sig (signature) or unspecified");
-	}
-
-	@Test
-	public void encodeWhenSuccessThenDecodes() throws Exception {
-		RSAKey rsaJwk = TestJwks.DEFAULT_RSA_JWK;
-		this.jwkList.add(rsaJwk);
-
-		JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
-		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-
-		Jwt encodedJws = this.jwsEncoder.encode(joseHeader, jwtClaimsSet);
-
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.ALG)).isEqualTo(joseHeader.getAlgorithm());
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.JKU)).isNull();
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.JWK)).isNull();
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.KID)).isEqualTo(rsaJwk.getKeyID());
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.X5U)).isNull();
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.X5C)).isNull();
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.X5T)).isNull();
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.X5T_S256)).isNull();
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.TYP)).isNull();
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.CTY)).isNull();
-		assertThat(encodedJws.getHeaders().get(JoseHeaderNames.CRIT)).isNull();
-
-		assertThat(encodedJws.getIssuer()).isEqualTo(jwtClaimsSet.getIssuer());
-		assertThat(encodedJws.getSubject()).isEqualTo(jwtClaimsSet.getSubject());
-		assertThat(encodedJws.getAudience()).isEqualTo(jwtClaimsSet.getAudience());
-		assertThat(encodedJws.getExpiresAt()).isEqualTo(jwtClaimsSet.getExpiresAt());
-		assertThat(encodedJws.getNotBefore()).isEqualTo(jwtClaimsSet.getNotBefore());
-		assertThat(encodedJws.getIssuedAt()).isEqualTo(jwtClaimsSet.getIssuedAt());
-		assertThat(encodedJws.getId()).isEqualTo(jwtClaimsSet.getId());
-		assertThat(encodedJws.<String>getClaim("custom-claim-name")).isEqualTo("custom-claim-value");
-
-		NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey(rsaJwk.toRSAPublicKey()).build();
-		jwtDecoder.decode(encodedJws.getTokenValue());
-	}
-
-	@Test
-	public void encodeWhenKeysRotatedThenNewKeyUsed() throws Exception {
-		TestJWKSource jwkSource = new TestJWKSource();
-		JWKSource<SecurityContext> jwkSourceDelegate = spy(new JWKSource<SecurityContext>() {
-			@Override
-			public List<JWK> get(JWKSelector jwkSelector, SecurityContext context) {
-				return jwkSource.get(jwkSelector, context);
-			}
-		});
-		NimbusJwsEncoder jwsEncoder = new NimbusJwsEncoder(jwkSourceDelegate);
-
-		JwkListResultCaptor jwkListResultCaptor = new JwkListResultCaptor();
-		willAnswer(jwkListResultCaptor).given(jwkSourceDelegate).get(any(), any());
-
-		JoseHeader joseHeader = JoseHeader.withAlgorithm(SignatureAlgorithm.RS256).build();
-		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet().build();
-
-		Jwt encodedJws = jwsEncoder.encode(joseHeader, jwtClaimsSet);
-
-		JWK jwk1 = jwkListResultCaptor.getResult().get(0);
-		NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey(((RSAKey) jwk1).toRSAPublicKey()).build();
-		jwtDecoder.decode(encodedJws.getTokenValue());
-
-		jwkSource.rotate(); // Trigger key rotation
-
-		encodedJws = jwsEncoder.encode(joseHeader, jwtClaimsSet);
-
-		JWK jwk2 = jwkListResultCaptor.getResult().get(0);
-		jwtDecoder = NimbusJwtDecoder.withPublicKey(((RSAKey) jwk2).toRSAPublicKey()).build();
-		jwtDecoder.decode(encodedJws.getTokenValue());
-
-		assertThat(jwk1.getKeyID()).isNotEqualTo(jwk2.getKeyID());
-	}
-
-	private static final class JwkListResultCaptor implements Answer<List<JWK>> {
-
-		private List<JWK> result;
-
-		private List<JWK> getResult() {
-			return this.result;
-		}
-
-		@SuppressWarnings("unchecked")
-		@Override
-		public List<JWK> answer(InvocationOnMock invocationOnMock) throws Throwable {
-			this.result = (List<JWK>) invocationOnMock.callRealMethod();
-			return this.result;
-		}
-
-	}
-
-	private static final class TestJWKSource implements JWKSource<SecurityContext> {
-
-		private int keyId = 1000;
-
-		private JWKSet jwkSet;
-
-		private TestJWKSource() {
-			init();
-		}
-
-		@Override
-		public List<JWK> get(JWKSelector jwkSelector, SecurityContext context) {
-			return jwkSelector.select(this.jwkSet);
-		}
-
-		private void init() {
-			// @formatter:off
-			RSAKey rsaJwk = TestJwks.jwk(TestKeys.DEFAULT_PUBLIC_KEY, TestKeys.DEFAULT_PRIVATE_KEY)
-					.keyID("rsa-jwk-" + this.keyId++)
-					.build();
-			ECKey ecJwk = TestJwks.jwk((ECPublicKey) TestKeys.DEFAULT_EC_KEY_PAIR.getPublic(), (ECPrivateKey) TestKeys.DEFAULT_EC_KEY_PAIR.getPrivate())
-					.keyID("ec-jwk-" + this.keyId++)
-					.build();
-			OctetSequenceKey secretJwk = TestJwks.jwk(TestKeys.DEFAULT_SECRET_KEY)
-					.keyID("secret-jwk-" + this.keyId++)
-					.build();
-			// @formatter:on
-			this.jwkSet = new JWKSet(Arrays.asList(rsaJwk, ecJwk, secretJwk));
-		}
-
-		private void rotate() {
-			init();
-		}
-
-	}
-
-}

+ 7 - 7
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/TestJoseHeaders.java → oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/TestJwsHeaders.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 the original author or authors.
+ * Copyright 2020-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,18 +24,18 @@ import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 /**
  * @author Joe Grandja
  */
-public final class TestJoseHeaders {
+public final class TestJwsHeaders {
 
-	private TestJoseHeaders() {
+	private TestJwsHeaders() {
 	}
 
-	public static JoseHeader.Builder joseHeader() {
-		return joseHeader(SignatureAlgorithm.RS256);
+	public static JwsHeader.Builder jwsHeader() {
+		return jwsHeader(SignatureAlgorithm.RS256);
 	}
 
-	public static JoseHeader.Builder joseHeader(SignatureAlgorithm signatureAlgorithm) {
+	public static JwsHeader.Builder jwsHeader(SignatureAlgorithm signatureAlgorithm) {
 		// @formatter:off
-		return JoseHeader.withAlgorithm(signatureAlgorithm)
+		return JwsHeader.with(signatureAlgorithm)
 				.jwkSetUrl("https://provider.com/oauth2/jwks")
 				.jwk(rsaJwk())
 				.keyId("keyId")

+ 6 - 6
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContextTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 the original author or authors.
+ * Copyright 2020-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,9 +23,9 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
 import org.springframework.security.oauth2.core.OAuth2TokenType;
 import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
-import org.springframework.security.oauth2.jwt.TestJoseHeaders;
+import org.springframework.security.oauth2.jwt.TestJwsHeaders;
 import org.springframework.security.oauth2.jwt.TestJwtClaimsSets;
 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationToken;
 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationGrantAuthenticationToken;
@@ -52,7 +52,7 @@ public class JwtEncodingContextTests {
 
 	@Test
 	public void withWhenClaimsNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> JwtEncodingContext.with(TestJoseHeaders.joseHeader(), null))
+		assertThatThrownBy(() -> JwtEncodingContext.with(TestJwsHeaders.jwsHeader(), null))
 				.isInstanceOf(IllegalArgumentException.class)
 				.hasMessage("claimsBuilder cannot be null");
 	}
@@ -60,7 +60,7 @@ public class JwtEncodingContextTests {
 	@Test
 	public void setWhenValueNullThenThrowIllegalArgumentException() {
 		JwtEncodingContext.Builder builder = JwtEncodingContext
-				.with(TestJoseHeaders.joseHeader(), TestJwtClaimsSets.jwtClaimsSet());
+				.with(TestJwsHeaders.jwsHeader(), TestJwtClaimsSets.jwtClaimsSet());
 		assertThatThrownBy(() -> builder.registeredClient(null))
 				.isInstanceOf(IllegalArgumentException.class);
 		assertThatThrownBy(() -> builder.principal(null))
@@ -79,7 +79,7 @@ public class JwtEncodingContextTests {
 
 	@Test
 	public void buildWhenAllValuesProvidedThenAllValuesAreSet() {
-		JoseHeader.Builder headers = TestJoseHeaders.joseHeader();
+		JwsHeader.Builder headers = TestJwsHeaders.jwsHeader();
 		JwtClaimsSet.Builder claims = TestJwtClaimsSets.jwtClaimsSet();
 		RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
 		TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "password");

+ 10 - 9
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/JwtClientAssertionAuthenticationProviderTests.java

@@ -44,12 +44,13 @@ import org.springframework.security.oauth2.jose.TestKeys;
 import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
 import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 import org.springframework.security.oauth2.jwt.BadJwtException;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
+import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
 import org.springframework.security.oauth2.jwt.JwtValidationException;
-import org.springframework.security.oauth2.jwt.NimbusJwsEncoder;
+import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
 import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
@@ -303,7 +304,7 @@ public class JwtClientAssertionAuthenticationProviderTests {
 				.thenReturn(registeredClient);
 
 		// @formatter:off
-		JoseHeader joseHeader = JoseHeader.withAlgorithm(MacAlgorithm.HS256)
+		JwsHeader jwsHeader = JwsHeader.with(MacAlgorithm.HS256)
 				.build();
 		JwtClaimsSet jwtClaimsSet = JwtClaimsSet.builder()
 				.issuer("invalid-iss")
@@ -313,7 +314,7 @@ public class JwtClientAssertionAuthenticationProviderTests {
 		// @formatter:on
 
 		JwtEncoder jwsEncoder = createEncoder(TestKeys.DEFAULT_ENCODED_SECRET_KEY, "HmacSHA256");
-		Jwt jwtAssertion = jwsEncoder.encode(joseHeader, jwtClaimsSet);
+		Jwt jwtAssertion = jwsEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet));
 
 		OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
 				registeredClient.getClientId(), JWT_CLIENT_ASSERTION_AUTHENTICATION_METHOD, jwtAssertion.getTokenValue(), null);
@@ -346,14 +347,14 @@ public class JwtClientAssertionAuthenticationProviderTests {
 				.thenReturn(registeredClient);
 
 		// @formatter:off
-		JoseHeader joseHeader = JoseHeader.withAlgorithm(MacAlgorithm.HS256)
+		JwsHeader jwsHeader = JwsHeader.with(MacAlgorithm.HS256)
 				.build();
 		JwtClaimsSet jwtClaimsSet = jwtClientAssertionClaims(registeredClient)
 				.build();
 		// @formatter:on
 
 		JwtEncoder jwsEncoder = createEncoder(TestKeys.DEFAULT_ENCODED_SECRET_KEY, "HmacSHA256");
-		Jwt jwtAssertion = jwsEncoder.encode(joseHeader, jwtClaimsSet);
+		Jwt jwtAssertion = jwsEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet));
 
 		OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
 				registeredClient.getClientId(), JWT_CLIENT_ASSERTION_AUTHENTICATION_METHOD, jwtAssertion.getTokenValue(), null);
@@ -392,14 +393,14 @@ public class JwtClientAssertionAuthenticationProviderTests {
 		Map<String, Object> parameters = createPkceTokenParameters(S256_CODE_VERIFIER);
 
 		// @formatter:off
-		JoseHeader joseHeader = JoseHeader.withAlgorithm(MacAlgorithm.HS256)
+		JwsHeader jwsHeader = JwsHeader.with(MacAlgorithm.HS256)
 				.build();
 		JwtClaimsSet jwtClaimsSet = jwtClientAssertionClaims(registeredClient)
 				.build();
 		// @formatter:on
 
 		JwtEncoder jwsEncoder = createEncoder(TestKeys.DEFAULT_ENCODED_SECRET_KEY, "HmacSHA256");
-		Jwt jwtAssertion = jwsEncoder.encode(joseHeader, jwtClaimsSet);
+		Jwt jwtAssertion = jwsEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet));
 
 		OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
 				registeredClient.getClientId(), JWT_CLIENT_ASSERTION_AUTHENTICATION_METHOD, jwtAssertion.getTokenValue(), parameters);
@@ -430,7 +431,7 @@ public class JwtClientAssertionAuthenticationProviderTests {
 		OctetSequenceKey secretKeyJwk = TestJwks.jwk(secretKey).build();
 		JWKSource<SecurityContext> jwkSource = (jwkSelector, securityContext) ->
 				jwkSelector.select(new JWKSet(secretKeyJwk));
-		return new NimbusJwsEncoder(jwkSource);
+		return new NimbusJwtEncoder(jwkSource);
 	}
 
 	private static String asUrl(String uri, String path) {

+ 22 - 21
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java

@@ -50,17 +50,12 @@ import org.springframework.security.oauth2.jwt.JoseHeaderNames;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
+import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
 import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
-import org.springframework.security.oauth2.server.authorization.token.JwtGenerator;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2AccessTokenGenerator;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2RefreshTokenGenerator;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -68,6 +63,12 @@ import org.springframework.security.oauth2.server.authorization.config.ProviderS
 import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
 import org.springframework.security.oauth2.server.authorization.context.ProviderContext;
 import org.springframework.security.oauth2.server.authorization.context.ProviderContextHolder;
+import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.JwtGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2AccessTokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2RefreshTokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -351,7 +352,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		OAuth2AuthorizationCodeAuthenticationToken authentication =
 				new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
 
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt());
 
 		doAnswer(answer -> {
 			OAuth2TokenContext context = answer.getArgument(0);
@@ -385,7 +386,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		OAuth2AuthorizationCodeAuthenticationToken authentication =
 				new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
 
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt());
 
 		doAnswer(answer -> {
 			OAuth2TokenContext context = answer.getArgument(0);
@@ -419,7 +420,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		OAuth2AuthorizationCodeAuthenticationToken authentication =
 				new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
 
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt());
 
 		OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
 				(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@@ -438,9 +439,9 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		assertThat(jwtEncodingContext.getHeaders()).isNotNull();
 		assertThat(jwtEncodingContext.getClaims()).isNotNull();
 
-		ArgumentCaptor<JwtClaimsSet> jwtClaimsSetCaptor = ArgumentCaptor.forClass(JwtClaimsSet.class);
-		verify(this.jwtEncoder).encode(any(), jwtClaimsSetCaptor.capture());
-		JwtClaimsSet jwtClaimsSet = jwtClaimsSetCaptor.getValue();
+		ArgumentCaptor<JwtEncoderParameters> jwtEncoderParametersCaptor = ArgumentCaptor.forClass(JwtEncoderParameters.class);
+		verify(this.jwtEncoder).encode(jwtEncoderParametersCaptor.capture());
+		JwtClaimsSet jwtClaimsSet = jwtEncoderParametersCaptor.getValue().getClaims();
 
 		Set<String> scopes = jwtClaimsSet.getClaim(OAuth2ParameterNames.SCOPE);
 		assertThat(scopes).isEqualTo(authorization.getAttribute(OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME));
@@ -475,7 +476,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		OAuth2AuthorizationCodeAuthenticationToken authentication =
 				new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
 
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt());
 
 		OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
 				(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@@ -511,7 +512,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		assertThat(idTokenContext.getHeaders()).isNotNull();
 		assertThat(idTokenContext.getClaims()).isNotNull();
 
-		verify(this.jwtEncoder, times(2)).encode(any(), any());		// Access token and ID Token
+		verify(this.jwtEncoder, times(2)).encode(any());		// Access token and ID Token
 
 		ArgumentCaptor<OAuth2Authorization> authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class);
 		verify(this.authorizationService).save(authorizationCaptor.capture());
@@ -549,7 +550,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		OAuth2AuthorizationCodeAuthenticationToken authentication =
 				new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
 
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt());
 
 		OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
 				(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@@ -568,9 +569,9 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		assertThat(jwtEncodingContext.getHeaders()).isNotNull();
 		assertThat(jwtEncodingContext.getClaims()).isNotNull();
 
-		ArgumentCaptor<JwtClaimsSet> jwtClaimsSetCaptor = ArgumentCaptor.forClass(JwtClaimsSet.class);
-		verify(this.jwtEncoder).encode(any(), jwtClaimsSetCaptor.capture());
-		JwtClaimsSet jwtClaimsSet = jwtClaimsSetCaptor.getValue();
+		ArgumentCaptor<JwtEncoderParameters> jwtEncoderParametersCaptor = ArgumentCaptor.forClass(JwtEncoderParameters.class);
+		verify(this.jwtEncoder).encode(jwtEncoderParametersCaptor.capture());
+		JwtClaimsSet jwtClaimsSet = jwtEncoderParametersCaptor.getValue().getClaims();
 
 		Set<String> scopes = jwtClaimsSet.getClaim(OAuth2ParameterNames.SCOPE);
 		assertThat(scopes).isEqualTo(authorization.getAttribute(OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME));
@@ -614,7 +615,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 
 		Instant accessTokenIssuedAt = Instant.now();
 		Instant accessTokenExpiresAt = accessTokenIssuedAt.plus(accessTokenTTL);
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt(accessTokenIssuedAt, accessTokenExpiresAt));
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt(accessTokenIssuedAt, accessTokenExpiresAt));
 
 		OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
 				(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@@ -651,7 +652,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		OAuth2AuthorizationCodeAuthenticationToken authentication =
 				new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
 
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt());
 
 		OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
 				(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@@ -666,7 +667,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		when(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
 				.thenReturn(authorization);
 
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt());
 
 		@SuppressWarnings("unchecked")
 		Supplier<String> refreshTokenGenerator = spy(new Supplier<String>() {

+ 7 - 7
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProviderTests.java

@@ -39,22 +39,22 @@ import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 import org.springframework.security.oauth2.jwt.JoseHeaderNames;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
-import org.springframework.security.oauth2.server.authorization.token.JwtGenerator;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2AccessTokenGenerator;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
 import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
 import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
 import org.springframework.security.oauth2.server.authorization.context.ProviderContext;
 import org.springframework.security.oauth2.server.authorization.context.ProviderContextHolder;
+import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.JwtGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2AccessTokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -217,7 +217,7 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
 		OAuth2ClientCredentialsAuthenticationToken authentication =
 				new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, requestedScope, null);
 
-		when(this.jwtEncoder.encode(any(), any()))
+		when(this.jwtEncoder.encode(any()))
 				.thenReturn(createJwt(Collections.singleton("mapped-scoped")));
 
 		OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
@@ -252,7 +252,7 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
 		OAuth2ClientCredentialsAuthenticationToken authentication =
 				new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
 
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt(registeredClient.getScopes()));
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt(registeredClient.getScopes()));
 
 		OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
 				(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);

+ 8 - 8
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProviderTests.java

@@ -48,17 +48,11 @@ import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 import org.springframework.security.oauth2.jwt.JoseHeaderNames;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
-import org.springframework.security.oauth2.server.authorization.token.JwtGenerator;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2AccessTokenGenerator;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2RefreshTokenGenerator;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
-import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -66,6 +60,12 @@ import org.springframework.security.oauth2.server.authorization.config.ProviderS
 import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
 import org.springframework.security.oauth2.server.authorization.context.ProviderContext;
 import org.springframework.security.oauth2.server.authorization.context.ProviderContextHolder;
+import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.JwtGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2AccessTokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2RefreshTokenGenerator;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
+import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -99,7 +99,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
 	public void setUp() {
 		this.authorizationService = mock(OAuth2AuthorizationService.class);
 		this.jwtEncoder = mock(JwtEncoder.class);
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt(Collections.singleton("scope1")));
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwt(Collections.singleton("scope1")));
 		this.jwtCustomizer = mock(OAuth2TokenCustomizer.class);
 		JwtGenerator jwtGenerator = new JwtGenerator(this.jwtEncoder);
 		jwtGenerator.setJwtCustomizer(this.jwtCustomizer);
@@ -265,7 +265,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
 		assertThat(idTokenContext.getHeaders()).isNotNull();
 		assertThat(idTokenContext.getClaims()).isNotNull();
 
-		verify(this.jwtEncoder, times(2)).encode(any(), any());		// Access token and ID Token
+		verify(this.jwtEncoder, times(2)).encode(any());		// Access token and ID Token
 
 		ArgumentCaptor<OAuth2Authorization> authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class);
 		verify(this.authorizationService).save(authorizationCaptor.capture());

+ 7 - 7
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProviderTests.java

@@ -42,11 +42,11 @@ import org.springframework.security.oauth2.core.oidc.OidcClientMetadataClaimName
 import org.springframework.security.oauth2.core.oidc.OidcClientRegistration;
 import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
 import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.jwt.TestJoseHeaders;
+import org.springframework.security.oauth2.jwt.TestJwsHeaders;
 import org.springframework.security.oauth2.jwt.TestJwtClaimsSets;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
@@ -451,7 +451,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
 		when(this.authorizationService.findByToken(
 				eq(jwtAccessToken.getTokenValue()), eq(OAuth2TokenType.ACCESS_TOKEN)))
 				.thenReturn(authorization);
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwtClientConfiguration());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwtClientConfiguration());
 
 		JwtAuthenticationToken principal = new JwtAuthenticationToken(
 				jwt, AuthorityUtils.createAuthorityList("SCOPE_client.create"));
@@ -538,7 +538,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
 		when(this.authorizationService.findByToken(
 				eq(jwtAccessToken.getTokenValue()), eq(OAuth2TokenType.ACCESS_TOKEN)))
 				.thenReturn(authorization);
-		when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwtClientConfiguration());
+		when(this.jwtEncoder.encode(any())).thenReturn(createJwtClientConfiguration());
 
 		JwtAuthenticationToken principal = new JwtAuthenticationToken(
 				jwt, AuthorityUtils.createAuthorityList("SCOPE_client.create"));
@@ -565,7 +565,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
 				eq(jwtAccessToken.getTokenValue()), eq(OAuth2TokenType.ACCESS_TOKEN));
 		verify(this.registeredClientRepository).save(registeredClientCaptor.capture());
 		verify(this.authorizationService, times(2)).save(authorizationCaptor.capture());
-		verify(this.jwtEncoder).encode(any(), any());
+		verify(this.jwtEncoder).encode(any());
 
 		// assert "registration" access token, which should be used for subsequent calls to client configuration endpoint
 		OAuth2Authorization authorizationResult = authorizationCaptor.getAllValues().get(0);
@@ -834,13 +834,13 @@ public class OidcClientRegistrationAuthenticationProviderTests {
 
 	private static Jwt createJwt(Set<String> scopes) {
 		// @formatter:off
-		JoseHeader joseHeader = TestJoseHeaders.joseHeader()
+		JwsHeader jwsHeader = TestJwsHeaders.jwsHeader()
 				.build();
 		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet()
 				.claim(OAuth2ParameterNames.SCOPE, scopes)
 				.build();
 		Jwt jwt = Jwt.withTokenValue("jwt-access-token")
-				.headers(headers -> headers.putAll(joseHeader.getHeaders()))
+				.headers(headers -> headers.putAll(jwsHeader.getHeaders()))
 				.claims(claims -> claims.putAll(jwtClaimsSet.getClaims()))
 				.build();
 		// @formatter:on

+ 5 - 5
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcClientRegistrationEndpointFilterTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 the original author or authors.
+ * Copyright 2020-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,10 +47,10 @@ import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMe
 import org.springframework.security.oauth2.core.oidc.OidcClientRegistration;
 import org.springframework.security.oauth2.core.oidc.http.converter.OidcClientRegistrationHttpMessageConverter;
 import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
-import org.springframework.security.oauth2.jwt.TestJoseHeaders;
+import org.springframework.security.oauth2.jwt.TestJwsHeaders;
 import org.springframework.security.oauth2.jwt.TestJwtClaimsSets;
 import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcClientRegistrationAuthenticationToken;
 import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
@@ -473,13 +473,13 @@ public class OidcClientRegistrationEndpointFilterTests {
 
 	private static Jwt createJwt(String scope) {
 		// @formatter:off
-		JoseHeader joseHeader = TestJoseHeaders.joseHeader()
+		JwsHeader jwsHeader = TestJwsHeaders.jwsHeader()
 				.build();
 		JwtClaimsSet jwtClaimsSet = TestJwtClaimsSets.jwtClaimsSet()
 				.claim(OAuth2ParameterNames.SCOPE, Collections.singleton(scope))
 				.build();
 		Jwt jwt = Jwt.withTokenValue("jwt-access-token")
-				.headers(headers -> headers.putAll(joseHeader.getHeaders()))
+				.headers(headers -> headers.putAll(jwsHeader.getHeaders()))
 				.claims(claims -> claims.putAll(jwtClaimsSet.getClaims()))
 				.build();
 		// @formatter:on

+ 7 - 8
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/token/JwtGeneratorTests.java

@@ -36,11 +36,11 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
 import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
 import org.springframework.security.oauth2.core.oidc.OidcScopes;
 import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
-import org.springframework.security.oauth2.jose.jws.JwsAlgorithm;
 import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
-import org.springframework.security.oauth2.jwt.JoseHeader;
+import org.springframework.security.oauth2.jwt.JwsHeader;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
+import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
 import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2TokenContext;
@@ -200,14 +200,13 @@ public class JwtGeneratorTests {
 		assertThat(jwtEncodingContext.getAuthorizationGrantType()).isEqualTo(tokenContext.getAuthorizationGrantType());
 		assertThat(jwtEncodingContext.<Authentication>getAuthorizationGrant()).isEqualTo(tokenContext.getAuthorizationGrant());
 
-		ArgumentCaptor<JoseHeader> joseHeaderCaptor = ArgumentCaptor.forClass(JoseHeader.class);
-		ArgumentCaptor<JwtClaimsSet> jwtClaimsSetCaptor = ArgumentCaptor.forClass(JwtClaimsSet.class);
-		verify(this.jwtEncoder).encode(joseHeaderCaptor.capture(), jwtClaimsSetCaptor.capture());
+		ArgumentCaptor<JwtEncoderParameters> jwtEncoderParametersCaptor = ArgumentCaptor.forClass(JwtEncoderParameters.class);
+		verify(this.jwtEncoder).encode(jwtEncoderParametersCaptor.capture());
 
-		JoseHeader joseHeader = joseHeaderCaptor.getValue();
-		assertThat(joseHeader.<JwsAlgorithm>getAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
+		JwsHeader jwsHeader = jwtEncoderParametersCaptor.getValue().getJwsHeader();
+		assertThat(jwsHeader.getAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
 
-		JwtClaimsSet jwtClaimsSet = jwtClaimsSetCaptor.getValue();
+		JwtClaimsSet jwtClaimsSet = jwtEncoderParametersCaptor.getValue().getClaims();
 		assertThat(jwtClaimsSet.getIssuer().toExternalForm()).isEqualTo(tokenContext.getProviderContext().getIssuer());
 		assertThat(jwtClaimsSet.getSubject()).isEqualTo(tokenContext.getAuthorization().getPrincipalName());
 		assertThat(jwtClaimsSet.getAudience()).containsExactly(tokenContext.getRegisteredClient().getClientId());