001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2016, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.jose.jwk.source; 019 020 021import java.util.Date; 022import java.util.concurrent.TimeUnit; 023 024import com.nimbusds.jose.jwk.JWKSet; 025 026 027/** 028 * JSON Web Key (JWK) set cache implementation. 029 * 030 * @author Vladimir Dzhuvinov 031 * @author Sarvesh Sharma 032 * @version 2020-03-11 033 */ 034public class DefaultJWKSetCache implements JWKSetCache { 035 036 037 /** 038 * The default lifespan for cached JWK sets (15 minutes). 039 */ 040 public static final long DEFAULT_LIFESPAN_MINUTES = 15; 041 042 043 /** 044 * The default refresh time for cached JWK sets (5 minutes). 045 */ 046 public static final long DEFAULT_REFRESH_TIME_MINUTES = 5; 047 048 049 /** 050 * The lifespan of the cached JWK set, in {@link #timeUnit}s, negative 051 * means no expiration. 052 */ 053 private final long lifespan; 054 055 056 /** 057 * The refresh time of the cached JWK set, in {@link #timeUnit}s, 058 * negative means no refresh time. 059 */ 060 private final long refreshTime; 061 062 063 /** 064 * The time unit, may be {@code null} if no expiration / refresh time. 065 */ 066 private final TimeUnit timeUnit; 067 068 069 /** 070 * The cache put timestamp, negative if not specified. 071 */ 072 private long putTimestamp = -1; 073 074 075 /** 076 * Creates a new JWK set, the default lifespan of the cached JWK set is 077 * set to 15 minutes, the refresh time to 5 minutes. 078 */ 079 public DefaultJWKSetCache() { 080 081 this(DEFAULT_LIFESPAN_MINUTES, DEFAULT_REFRESH_TIME_MINUTES, TimeUnit.MINUTES); 082 } 083 084 085 /** 086 * Creates a new JWK set cache. 087 * 088 * @param lifespan The lifespan of the cached JWK set before it 089 * expires, negative means no expiration. 090 * @param refreshTime The time after which the cached JWK set is marked 091 * for refresh, negative if not specified. Should be 092 * shorter or equal to the lifespan. 093 * @param timeUnit The lifespan time unit, may be {@code null} if no 094 * expiration or refresh time. 095 */ 096 public DefaultJWKSetCache(final long lifespan, final long refreshTime, final TimeUnit timeUnit) { 097 098 this.lifespan = lifespan; 099 this.refreshTime = refreshTime; 100 101 if ((lifespan > -1 || refreshTime > -1) && timeUnit == null) { 102 throw new IllegalArgumentException("A time unit must be specified for non-negative lifespans or refresh times"); 103 } 104 105 this.timeUnit = timeUnit; 106 } 107 108 109 /** 110 * The cached JWK set, {@code null} if none. 111 */ 112 private JWKSet jwkSet; 113 114 115 @Override 116 public void put(final JWKSet jwkSet) { 117 118 this.jwkSet = jwkSet; 119 120 if (jwkSet != null) { 121 putTimestamp = new Date().getTime(); 122 } else { 123 // cache cleared 124 putTimestamp = -1; 125 } 126 } 127 128 129 @Override 130 public JWKSet get() { 131 132 if (isExpired()) { 133 jwkSet = null; // clear 134 } 135 136 return jwkSet; 137 } 138 139 140 @Override 141 public boolean requiresRefresh() { 142 143 return putTimestamp > -1 && 144 refreshTime > -1 && 145 new Date().getTime() > putTimestamp + TimeUnit.MILLISECONDS.convert(refreshTime, timeUnit); 146 } 147 148 149 /** 150 * Returns the cache put timestamp. 151 * 152 * @return The cache put timestamp, negative if not specified. 153 */ 154 public long getPutTimestamp() { 155 156 return putTimestamp; 157 } 158 159 160 /** 161 * Returns {@code true} if the cached JWK set is expired. 162 * 163 * @return {@code true} if expired. 164 */ 165 public boolean isExpired() { 166 167 return putTimestamp > -1 && 168 lifespan > -1 && 169 new Date().getTime() > putTimestamp + TimeUnit.MILLISECONDS.convert(lifespan, timeUnit); 170 } 171 172 173 /** 174 * Returns the configured lifespan of the cached JWK. 175 * 176 * @param timeUnit The time unit to use. 177 * 178 * @return The configured lifespan, negative means no expiration. 179 */ 180 public long getLifespan(final TimeUnit timeUnit) { 181 182 if (lifespan < 0) { 183 return lifespan; 184 } 185 186 return timeUnit.convert(lifespan, timeUnit); 187 } 188 189 190 /** 191 * Returns the configured refresh time of the cached JWK. 192 * 193 * @param timeUnit The time unit to use. 194 * 195 * @return The configured refresh time, negative means no expiration. 196 */ 197 public long getRefreshTime(final TimeUnit timeUnit) { 198 199 if (refreshTime < 0) { 200 return refreshTime; 201 } 202 203 return timeUnit.convert(refreshTime, timeUnit); 204 } 205}