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

io.jsonwebtoken.impl.security.AbstractFamilyJwkFactory Maven / Gradle / Ivy

/*
 * Copyright (C) 2021 jsonwebtoken.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.jsonwebtoken.impl.security;

import io.jsonwebtoken.impl.lang.CheckedFunction;
import io.jsonwebtoken.impl.lang.Parameter;
import io.jsonwebtoken.lang.Assert;
import io.jsonwebtoken.lang.Strings;
import io.jsonwebtoken.security.InvalidKeyException;
import io.jsonwebtoken.security.Jwk;
import io.jsonwebtoken.security.KeyException;

import java.security.Key;
import java.security.KeyFactory;
import java.util.Set;

abstract class AbstractFamilyJwkFactory> implements FamilyJwkFactory {

    protected static  void put(JwkContext ctx, Parameter param, T value) {
        ctx.put(param.getId(), param.applyTo(value));
    }

    private final String ktyValue;
    private final Class keyType;
    private final Set> params;

    AbstractFamilyJwkFactory(String ktyValue, Class keyType, Set> params) {
        this.ktyValue = Assert.hasText(ktyValue, "keyType argument cannot be null or empty.");
        this.keyType = Assert.notNull(keyType, "keyType class cannot be null.");
        this.params = Assert.notEmpty(params, "Parameters collection cannot be null or empty.");
    }

    @Override
    public String getId() {
        return this.ktyValue;
    }

    @Override
    public boolean supports(Key key) {
        return this.keyType.isInstance(key);
    }

    @Override
    public JwkContext newContext(JwkContext src, K key) {
        Assert.notNull(src, "Source JwkContext cannot be null.");
        return key != null ?
                new DefaultJwkContext<>(this.params, src, key) :
                new DefaultJwkContext(this.params, src, false);
    }

    @Override
    public boolean supports(JwkContext ctx) {
        return supports(ctx.getKey()) || supportsKeyValues(ctx);
    }

    protected boolean supportsKeyValues(JwkContext ctx) {
        return this.ktyValue.equals(ctx.getType());
    }

    protected K generateKey(final JwkContext ctx, final CheckedFunction fn) {
        return generateKey(ctx, this.keyType, fn);
    }

    protected String getKeyFactoryJcaName(final JwkContext ctx) {
        String jcaName = KeysBridge.findAlgorithm(ctx.getKey());
        return Strings.hasText(jcaName) ? jcaName : getId();
    }

    protected  T generateKey(final JwkContext ctx, final Class type, final CheckedFunction fn) {
        String jcaName = getKeyFactoryJcaName(ctx);
        JcaTemplate template = new JcaTemplate(jcaName, ctx.getProvider(), ctx.getRandom());
        return template.withKeyFactory(new CheckedFunction() {
            @Override
            public T apply(KeyFactory instance) {
                try {
                    return fn.apply(instance);
                } catch (KeyException keyException) {
                    throw keyException; // propagate
                } catch (Exception e) {
                    String msg = "Unable to create " + type.getSimpleName() + " from JWK " + ctx + ": " + e.getMessage();
                    throw new InvalidKeyException(msg, e);
                }
            }
        });
    }

    @Override
    public final J createJwk(JwkContext ctx) {
        Assert.notNull(ctx, "JwkContext argument cannot be null.");
        if (!supports(ctx)) { //should be asserted by caller, but assert just in case:
            String msg = "Unsupported JwkContext.";
            throw new IllegalArgumentException(msg);
        }
        K key = ctx.getKey();
        if (key != null) {
            ctx.setType(this.ktyValue);
            return createJwkFromKey(ctx);
        } else {
            return createJwkFromValues(ctx);
        }
    }

    //when called, ctx.getKey() is guaranteed to be non-null
    protected abstract J createJwkFromKey(JwkContext ctx);

    //when called ctx.getType() is guaranteed to equal this.ktyValue
    protected abstract J createJwkFromValues(JwkContext ctx);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy