All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gravitee.am.jwt.DefaultJWTBuilder Maven / Gradle / Ivy

There is a newer version: 4.6.0-alpha.3
Show newest version
/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * 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.gravitee.am.jwt;

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.KeyLengthException;
import com.nimbusds.jose.crypto.ECDSASigner;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton;
import com.nimbusds.jose.jca.JCASupport;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import io.gravitee.am.common.exception.jwt.MalformedJWTException;
import io.gravitee.am.common.exception.jwt.SignatureException;
import io.gravitee.am.common.jwt.Claims;
import io.gravitee.am.common.jwt.JWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.SecretKey;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.PrivateKey;
import java.security.interfaces.ECPrivateKey;
import java.text.ParseException;

/**
 * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com)
 * @author GraviteeSource Team
 */
public class DefaultJWTBuilder implements JWTBuilder {

    private static final Logger logger = LoggerFactory.getLogger(DefaultJWTBuilder.class);
    private final JWSSigner signer;
    private final JWSHeader header;
    private String issuer;

    public DefaultJWTBuilder(final Key key,
                             final String signatureAlgorithm,
                             final String keyId) throws InvalidKeyException {
        if (key instanceof PrivateKey) {
            if ( key.getAlgorithm().equals("RSA")){
                signer = new RSASSASigner((PrivateKey) key, true);
            } else {
                try {
                    signer = new ECDSASigner((ECPrivateKey) key);
                } catch (JOSEException e) {
                    throw new InvalidKeyException(e);
                }
            }
            // if JCA doesn't support at least the PS256 algorithm (jdk <= 8)
            // add BouncyCastle JCA provider
            if (!JCASupport.isSupported(JWSAlgorithm.PS256)) {
                signer.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
            }
        } else if (key instanceof SecretKey secretKey) {
            try {
                signer = new MACSigner(secretKey);
            } catch (KeyLengthException e) {
                throw new InvalidKeyException(e);
            }
        } else {
            throw new InvalidKeyException("No matching JWT signer for key : " + key);
        }
        header = new JWSHeader.Builder(new JWSAlgorithm(signatureAlgorithm)).keyID(keyId).type(JOSEObjectType.JWT).build();
    }

    public DefaultJWTBuilder(final Key key,
                             final String signatureAlgorithm,
                             final String keyId,
                             final String issuer) throws InvalidKeyException {
        this(key, signatureAlgorithm, keyId);
        this.issuer = issuer;
    }


    @Override
    public String sign(JWT payload) {
        try {
            if (issuer != null && !payload.containsKey(Claims.ISS)) {
                payload.setIss(issuer);
            }
            SignedJWT signedJWT = new SignedJWT(header, JWTClaimsSet.parse(payload));
            signedJWT.sign(signer);
            return signedJWT.serialize();
        } catch (ParseException ex) {
            logger.debug("Signing JWT token: {} has failed", payload);
            throw new MalformedJWTException("Signing JWT token has failed", ex);
        } catch (JOSEException ex) {
            logger.debug("Signing JWT token: {} has failed", payload);
            throw new SignatureException("Signing JWT token has failed", ex);
        } catch (Exception ex) {
            logger.error("An error occurs while signing JWT token : {}", payload, ex);
            throw ex;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy