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

jakarta.security.enterprise.identitystore.openid.JwtClaims Maven / Gradle / Ivy

/*
 * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 *
 */

/*
 *
 * Contributors:
 *   2021 : Payara Foundation and/or its affiliates
 *      Initially authored in Security Connectors
 */

package jakarta.security.enterprise.identitystore.openid;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;

/**
 * Standard JWT claims. A token typically.
 *
 */
public interface JwtClaims extends Claims {

    /**
     * The principal that issued the JWT
     * @return value of {@code iss} claim
     */
    default Optional getIssuer() {
        return getStringClaim("iss");
    }

    /**
     * The principal that is the
     *    subject of the JWT.  The claims in a JWT are normally statements
     *    about the subject.
     * @return value of {@code sub} claim
     */
    default Optional getSubject() {
        return getStringClaim("sub");
    }

    /**
     * The recipients that the JWT is intended for. To ease work with the field, audience is always represented as list,
     * also in special cases -- it is singleton list when it was a string in the token, and empty set if it was not present.
     * @return non-null set representing the values of {@code aud} claim
     */
    default List getAudience() {
        return getArrayStringClaim("aud");
    }

    /**
     * Expiration time on or after which the JWT MUST NOT be accepted for processing.
     * @return value of {@code exp} claim
     */
    default Optional getExpirationTime() {
        return getNumericDateClaim("exp");
    }

    /**
     * Check if JWT is expired
     * @param clock Clock representing reference time of checking
     * @param required indication whether the claim is required, i. e. whether token with claim is considered expired
     * @param skew allowed clock skew to account for drift between provider and us
     * @return {@code} true when current time is past expiration time, or {@code exp} claim is not present and {@code required} is {@code true}
     */
    default boolean isExpired(Clock clock, boolean required, Duration skew) {
        return getExpirationTime().map(exp -> clock.millis() - exp.toEpochMilli() > skew.toMillis())
                .orElse(required);
    }

    /**
     * The time before which the JWT MUST NOT be accepted for processing.
     * @return
     */
    default Optional getNotBeforeTime() {
        return getNumericDateClaim("nbf");
    }

    /**
     * Check if JWT is before its defined validity
     * @param clock Clock representing reference time of checking
     * @param required indication, whether the claim is required, i. e. whether token without nbf is considered before validity
     * @param skew allowed clock skew to account for drift between provider and us
     * @return
     */
    default boolean isBeforeValidity(Clock clock, boolean required, Duration skew) {
        return getNotBeforeTime().map(nbf -> nbf.toEpochMilli() - clock.millis() > skew.toMillis())
                .orElse(required);
    }

    /**
     * Check JWT validity against current time with 1MIN clock skew.
     * @return true if exp token is present and within limits and nbf is within limits when present
     */
    default boolean isValid() {
        Duration skew = Duration.ofMinutes(1);
        return !isExpired(Clock.systemUTC(), true, skew) && !isBeforeValidity(Clock.systemUTC(), false, skew);
    }

    /**
     * The time at which the JWT was issued.
     * @return value of {@code exp} claim
     */
    default Optional getIssuedAt() {
        return getNumericDateClaim("iat");
    }

    /**
     * Unique identifier for the JWT
     * @return value of {@code jti} claim
     */
    default Optional getJwtId() {
        return getStringClaim("jti");
    }

    /**
     * Singleton instance representing no claims
     */
    JwtClaims NONE = new JwtClaims() {
        @Override
        public Optional getStringClaim(String name) {
            return Optional.empty();
        }

        @Override
        public Optional getNumericDateClaim(String name) {
            return Optional.empty();
        }

        @Override
        public List getArrayStringClaim(String name) {
            return Collections.emptyList();
        }

        @Override
        public OptionalInt getIntClaim(String name) {
            return OptionalInt.empty();
        }

        @Override
        public OptionalLong getLongClaim(String name) {
            return OptionalLong.empty();
        }

        @Override
        public OptionalDouble getDoubleClaim(String name) {
            return OptionalDouble.empty();
        }

        @Override
        public Optional getNested(String name) {
            return Optional.empty();
        }
    };
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy