diff --git a/conf/openmetadata.yaml b/conf/openmetadata.yaml index dedceb705dd..cf7f07b7f28 100644 --- a/conf/openmetadata.yaml +++ b/conf/openmetadata.yaml @@ -180,6 +180,7 @@ authenticationConfiguration: # This will only be valid when provider type specified is customOidc providerName: ${CUSTOM_OIDC_AUTHENTICATION_PROVIDER_NAME:-""} publicKeyUrls: ${AUTHENTICATION_PUBLIC_KEYS:-[http://localhost:8585/api/v1/system/config/jwks]} + tokenValidationAlgorithm: ${AUTHENTICATION_TOKEN_VALIDATION_ALGORITHM:-"RS256"} authority: ${AUTHENTICATION_AUTHORITY:-https://accounts.google.com} clientId: ${AUTHENTICATION_CLIENT_ID:-""} callbackUrl: ${AUTHENTICATION_CALLBACK_URL:-""} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/OpenMetadataApplication.java b/openmetadata-service/src/main/java/org/openmetadata/service/OpenMetadataApplication.java index fdb07d0bcba..8efa36c4bc4 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/OpenMetadataApplication.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/OpenMetadataApplication.java @@ -190,7 +190,10 @@ public class OpenMetadataApplication extends Application DEFAULT_PUBLIC_KEY_URLS = Arrays.asList( @@ -123,6 +125,7 @@ public class JwtFilter implements ContainerRequestFilter { this.principalDomain = authorizerConfiguration.getPrincipalDomain(); this.enforcePrincipalDomain = authorizerConfiguration.getEnforcePrincipalDomain(); this.useRolesFromProvider = authorizerConfiguration.getUseRolesFromProvider(); + this.tokenValidationAlgorithm = authenticationConfiguration.getTokenValidationAlgorithm(); } @VisibleForTesting @@ -224,7 +227,8 @@ public class JwtFilter implements ContainerRequestFilter { // Validate JWT with public key Jwk jwk = jwkProvider.get(jwt.getKeyId()); - Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null); + Algorithm algorithm = + getAlgorithm(tokenValidationAlgorithm, (RSAPublicKey) jwk.getPublicKey(), null); try { algorithm.verify(jwt); } catch (RuntimeException runtimeException) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/jwt/JWTTokenGenerator.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/jwt/JWTTokenGenerator.java index 86817532646..21aaeeeef9b 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/jwt/JWTTokenGenerator.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/jwt/JWTTokenGenerator.java @@ -37,6 +37,7 @@ import java.util.List; import java.util.Set; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.openmetadata.schema.api.security.AuthenticationConfiguration; import org.openmetadata.schema.api.security.jwt.JWTTokenConfiguration; import org.openmetadata.schema.auth.JWTAuthMechanism; import org.openmetadata.schema.auth.JWTTokenExpiry; @@ -56,6 +57,7 @@ public class JWTTokenGenerator { @Getter private RSAPublicKey publicKey; private String issuer; private String kid; + private AuthenticationConfiguration.TokenValidationAlgorithm tokenValidationAlgorithm; private JWTTokenGenerator() { /* Private constructor for singleton */ @@ -66,7 +68,9 @@ public class JWTTokenGenerator { } /** Expected to be initialized only once during application start */ - public void init(JWTTokenConfiguration jwtTokenConfiguration) { + public void init( + AuthenticationConfiguration.TokenValidationAlgorithm algorithm, + JWTTokenConfiguration jwtTokenConfiguration) { try { if (jwtTokenConfiguration.getRsaprivateKeyFilePath() != null && !jwtTokenConfiguration.getRsaprivateKeyFilePath().isEmpty() @@ -84,6 +88,7 @@ public class JWTTokenGenerator { publicKey = (RSAPublicKey) kf.generatePublic(spec); issuer = jwtTokenConfiguration.getJwtissuer(); kid = jwtTokenConfiguration.getKeyId(); + tokenValidationAlgorithm = algorithm; } } catch (Exception ex) { LOG.error("Failed to initialize JWTTokenGenerator ", ex); @@ -141,7 +146,7 @@ public class JWTTokenGenerator { } } JWTAuthMechanism jwtAuthMechanism = new JWTAuthMechanism().withJWTTokenExpiry(expiry); - Algorithm algorithm = Algorithm.RSA256(null, privateKey); + Algorithm algorithm = getAlgorithm(tokenValidationAlgorithm, null, privateKey); String token = JWT.create() .withIssuer(issuer) @@ -214,4 +219,15 @@ public class JWTTokenGenerator { return jwt.getExpiresAt(); } + + public static Algorithm getAlgorithm( + AuthenticationConfiguration.TokenValidationAlgorithm algorithm, + RSAPublicKey publicKey, + RSAPrivateKey privateKey) { + return switch (algorithm) { + case RS_256 -> Algorithm.RSA256(publicKey, privateKey); + case RS_384 -> Algorithm.RSA384(publicKey, privateKey); + case RS_512 -> Algorithm.RSA512(publicKey, privateKey); + }; + } } diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/security/JWTTokenGeneratorTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/security/JWTTokenGeneratorTest.java index b7d935f5c62..555a079ddd3 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/security/JWTTokenGeneratorTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/security/JWTTokenGeneratorTest.java @@ -15,6 +15,7 @@ import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; +import org.openmetadata.schema.api.security.AuthenticationConfiguration; import org.openmetadata.schema.api.security.jwt.JWTTokenConfiguration; import org.openmetadata.schema.auth.JWTAuthMechanism; import org.openmetadata.schema.auth.JWTTokenExpiry; @@ -38,7 +39,8 @@ class JWTTokenGeneratorTest { jwtTokenConfiguration.setRsaprivateKeyFilePath(rsaPrivateKeyPath); jwtTokenConfiguration.setRsapublicKeyFilePath(rsaPublicKeyPath); jwtTokenGenerator = JWTTokenGenerator.getInstance(); - jwtTokenGenerator.init(jwtTokenConfiguration); + jwtTokenGenerator.init( + AuthenticationConfiguration.TokenValidationAlgorithm.RS_256, jwtTokenConfiguration); } @Test diff --git a/openmetadata-spec/src/main/resources/json/schema/configuration/authenticationConfiguration.json b/openmetadata-spec/src/main/resources/json/schema/configuration/authenticationConfiguration.json index 670401107ca..ac7d5075eca 100644 --- a/openmetadata-spec/src/main/resources/json/schema/configuration/authenticationConfiguration.json +++ b/openmetadata-spec/src/main/resources/json/schema/configuration/authenticationConfiguration.json @@ -46,6 +46,12 @@ "type": "string" } }, + "tokenValidationAlgorithm": { + "description": "Token Validation Algorithm to use.", + "type": "string", + "enum": ["RS256", "RS384", "RS512"], + "default": "RS256" + }, "authority": { "description": "Authentication Authority", "type": "string" diff --git a/openmetadata-ui/src/main/resources/ui/src/generated/configuration/authenticationConfiguration.ts b/openmetadata-ui/src/main/resources/ui/src/generated/configuration/authenticationConfiguration.ts index c21521c1562..41f559faee8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/generated/configuration/authenticationConfiguration.ts +++ b/openmetadata-ui/src/main/resources/ui/src/generated/configuration/authenticationConfiguration.ts @@ -10,9 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - - /** +/** * This schema defines the Authentication Configuration. */ export interface AuthenticationConfiguration { @@ -69,6 +67,10 @@ export interface AuthenticationConfiguration { * Saml Configuration that is applicable only when the provider is Saml */ samlConfiguration?: SamlSSOClientConfig; + /** + * Token Validation Algorithm to use. + */ + tokenValidationAlgorithm?: TokenValidationAlgorithm; } /** @@ -492,3 +494,12 @@ export interface SP { */ spX509Certificate?: string; } + +/** + * Token Validation Algorithm to use. + */ +export enum TokenValidationAlgorithm { + Rs256 = "RS256", + Rs384 = "RS384", + Rs512 = "RS512", +}