All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.smallrye.jwt.auth.principal.DefaultJWTParser Maven / Gradle / Ivy
/*
* Copyright 2019 Red Hat, Inc, and individual contributors.
*
* 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
*
* http://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 io.smallrye.jwt.auth.principal;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.util.Collections;
import java.util.Set;
import javax.crypto.SecretKey;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.jwt.Claims;
import org.eclipse.microprofile.jwt.JsonWebToken;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import io.smallrye.jwt.algorithm.KeyEncryptionAlgorithm;
import io.smallrye.jwt.algorithm.SignatureAlgorithm;
import io.smallrye.jwt.auth.cdi.JWTCallerPrincipalFactoryProducer;
import io.smallrye.jwt.util.KeyUtils;
/**
* A default implementation of {@link JWTParser}.
*/
@ApplicationScoped
public class DefaultJWTParser implements JWTParser {
private static final String ED_EC_PUBLIC_KEY_INTERFACE = "java.security.interfaces.EdECPublicKey";
private static final String XEC_PRIVATE_KEY_INTERFACE = "java.security.interfaces.XECPrivateKey";
@Inject
private JWTAuthContextInfo authContextInfo;
@Inject
private JWTCallerPrincipalFactory callerPrincipalFactory;
/**
* Default constructor which is required to support a JWTParser injection
*/
public DefaultJWTParser() {
}
/**
* Constructor which initializes DefaultJWTParser with the provided {@link JWTAuthContextInfo} and a new instance of
* {@link JWTCallerPrincipalFactory}
*
* @param authContextInfo {@link JWTAuthContextInfo}
*/
public DefaultJWTParser(JWTAuthContextInfo authContextInfo) {
this(authContextInfo, new JWTCallerPrincipalFactoryProducer().getFactory());
}
/**
* Constructor which initializes DefaultJWTParser with the provided {@link JWTCallerPrincipalFactory} and a new instance of
* {@link JWTAuthContextInfo}
*
* @param factory {@link JWTCallerPrincipalFactory}
*/
public DefaultJWTParser(JWTCallerPrincipalFactory factory) {
this(new JWTAuthContextInfo(), factory);
}
/**
* Constructor which initializes DefaultJWTParser with the provided {@link JWTAuthContextInfo} and
* {@link JWTCallerPrincipalFactory}
*
* @param authContextInfo {@link JWTAuthContextInfo}
* @param factory {@link JWTCallerPrincipalFactory}
*/
public DefaultJWTParser(JWTAuthContextInfo authContextInfo, JWTCallerPrincipalFactory factory) {
this.authContextInfo = authContextInfo;
this.callerPrincipalFactory = factory;
}
public JsonWebToken parse(final String bearerToken) throws ParseException {
return getCallerPrincipalFactory().parse(bearerToken, authContextInfo);
}
@Override
public JsonWebToken parse(String bearerToken, JWTAuthContextInfo newAuthContextInfo) throws ParseException {
JWTCallerPrincipalFactory factory = getCallerPrincipalFactory();
if (newAuthContextInfo.getPublicKeyLocation() != null || newAuthContextInfo.getPublicKeyContent() != null
|| newAuthContextInfo.getDecryptionKeyContent() != null
|| newAuthContextInfo.getDecryptionKeyLocation() != null) {
// in these cases a `KeyLocationResolver` is cached
try {
factory = factory.getClass().getDeclaredConstructor().newInstance();
} catch (Throwable t) {
PrincipalMessages.msg.newJWTCallerPrincipalFactoryFailure(t);
}
}
return factory.parse(bearerToken, newAuthContextInfo);
}
@Override
public JsonWebToken verify(String bearerToken, PublicKey key) throws ParseException {
JWTAuthContextInfo newAuthContextInfo = copyAuthContextInfo();
newAuthContextInfo.setPublicVerificationKey(key);
if (key instanceof ECPublicKey) {
setSignatureAlgorithmIfNeeded(newAuthContextInfo, "ES", SignatureAlgorithm.ES256);
} else if (isEdECPublicKey(key)) {
setSignatureAlgorithmIfNeeded(newAuthContextInfo, "EdDSA", SignatureAlgorithm.EDDSA);
} else {
setSignatureAlgorithmIfNeeded(newAuthContextInfo, "RS", SignatureAlgorithm.RS256);
}
return getCallerPrincipalFactory().parse(bearerToken, newAuthContextInfo);
}
@Override
public JsonWebToken verify(String bearerToken, SecretKey key) throws ParseException {
JWTAuthContextInfo newAuthContextInfo = copyAuthContextInfo();
newAuthContextInfo.setSecretVerificationKey(key);
setSignatureAlgorithmIfNeeded(newAuthContextInfo, "HS", SignatureAlgorithm.HS256);
return getCallerPrincipalFactory().parse(bearerToken, newAuthContextInfo);
}
@Override
public JsonWebToken verify(String bearerToken, String secret) throws ParseException {
return verify(bearerToken, KeyUtils.createSecretKeyFromSecret(secret));
}
@Override
public JsonWebToken decrypt(String bearerToken, PrivateKey key) throws ParseException {
JWTAuthContextInfo newAuthContextInfo = copyAuthContextInfo();
newAuthContextInfo.setPrivateDecryptionKey(key);
if (key instanceof ECPrivateKey || isXecPrivateKey(key)) {
setKeyEncryptionAlgorithmIfNeeded(newAuthContextInfo, "EC", KeyEncryptionAlgorithm.ECDH_ES_A256KW);
} else {
setKeyEncryptionAlgorithmIfNeeded(newAuthContextInfo, "RS", KeyEncryptionAlgorithm.RSA_OAEP);
}
return getCallerPrincipalFactory().parse(bearerToken, newAuthContextInfo);
}
@Override
public JsonWebToken decrypt(String bearerToken, SecretKey key) throws ParseException {
JWTAuthContextInfo newAuthContextInfo = copyAuthContextInfo();
newAuthContextInfo.setSecretDecryptionKey(key);
setKeyEncryptionAlgorithmIfNeeded(newAuthContextInfo, "A256KW", KeyEncryptionAlgorithm.A256KW);
return getCallerPrincipalFactory().parse(bearerToken, newAuthContextInfo);
}
@Override
public JsonWebToken decrypt(String bearerToken, String secret) throws ParseException {
return decrypt(bearerToken, KeyUtils.createSecretKeyFromSecret(secret));
}
private JWTCallerPrincipalFactory getCallerPrincipalFactory() {
if (callerPrincipalFactory == null) {
return JWTCallerPrincipalFactory.instance();
}
return callerPrincipalFactory;
}
private JWTAuthContextInfo copyAuthContextInfo() {
return authContextInfo != null ? new JWTAuthContextInfo(authContextInfo) : new JWTAuthContextInfo();
}
private void setSignatureAlgorithmIfNeeded(JWTAuthContextInfo newAuthContextInfo, String algoStart,
SignatureAlgorithm newAlgo) {
Set algo = newAuthContextInfo.getSignatureAlgorithm();
if (!algo.stream().anyMatch(s -> s.getAlgorithm().startsWith(algoStart))) {
newAuthContextInfo.setSignatureAlgorithm(Set.of(newAlgo));
}
}
private void setKeyEncryptionAlgorithmIfNeeded(JWTAuthContextInfo newAuthContextInfo, String algoStart,
KeyEncryptionAlgorithm newAlgo) {
Set algo = newAuthContextInfo.getKeyEncryptionAlgorithm();
if (!algo.stream().anyMatch(s -> s.getAlgorithm().startsWith(algoStart))) {
newAuthContextInfo.setKeyEncryptionAlgorithm(Collections.singleton(newAlgo));
}
}
private static boolean isEdECPublicKey(Key verificationKey) {
return KeyUtils.isSupportedKey(verificationKey, ED_EC_PUBLIC_KEY_INTERFACE);
}
private static boolean isXecPrivateKey(Key encKey) {
return KeyUtils.isSupportedKey(encKey, XEC_PRIVATE_KEY_INTERFACE);
}
@Override
public JsonWebToken parseOnly(String token) throws ParseException {
try {
JwtClaims claims = new JwtConsumerBuilder()
.setSkipSignatureVerification()
.setSkipAllValidators()
.build().processToClaims(token);
claims.setClaim(Claims.raw_token.name(), token);
return new DefaultJWTCallerPrincipal(claims);
} catch (InvalidJwtException e) {
PrincipalMessages.msg.failedToVerifyToken(e);
}
return null;
}
}