001package com.nimbusds.openid.connect.provider.spi.grants; 002 003 004import com.nimbusds.oauth2.sdk.ParseException; 005import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 006import net.jcip.annotations.Immutable; 007import net.minidev.json.JSONObject; 008 009import java.util.Optional; 010 011 012/** 013 * Refresh token specification. 014 */ 015@Immutable 016public class RefreshTokenSpec extends OptionalTokenSpec { 017 018 019 /** 020 * Default refresh token specification (no issue). 021 */ 022 public static final RefreshTokenSpec DEFAULT = new RefreshTokenSpec(); 023 024 025 /** 026 * The maximum idle time, in seconds. Zero means no idle time 027 * expiration. 028 */ 029 private final long maxIdleTime; 030 031 032 /** 033 * The rotation preference. 034 */ 035 private final Optional<Boolean> rotate; 036 037 038 /** 039 * Creates a new default refresh token specification (no issue). 040 */ 041 public RefreshTokenSpec() { 042 043 this(false, -1L); 044 } 045 046 047 /** 048 * Creates a new refresh token specification. 049 * 050 * @param issue Controls the refresh token issue. If {@code true} 051 * a refresh token must be issued (requires a 052 * long-lived authorisation), {@code false} to prohibit 053 * issue. 054 * @param lifetime The refresh token maximum lifetime, in seconds. Zero 055 * means no lifetime limit. Negative means not 056 * specified (to let the Connect2id server apply the 057 * default configured refresh token lifetime). Applies 058 * only when a refresh token is issued. 059 */ 060 public RefreshTokenSpec(final boolean issue, final long lifetime) { 061 062 this(issue, lifetime, Optional.empty()); 063 } 064 065 066 /** 067 * Creates a new refresh token specification. 068 * 069 * @param issue Controls the refresh token issue. If {@code true} 070 * a refresh token must be issued (requires a 071 * long-lived authorisation), {@code false} to prohibit 072 * issue. 073 * @param lifetime The refresh token maximum lifetime, in seconds. Zero 074 * means no lifetime limit. Negative means not 075 * specified (to let the Connect2id server apply the 076 * default configured refresh token lifetime). Applies 077 * only when a refresh token is issued. 078 * @param rotate The optional rotation preference, if none the 079 * default refresh token rotation policy will apply. 080 */ 081 public RefreshTokenSpec(final boolean issue, final long lifetime, final Optional<Boolean> rotate) { 082 083 this(issue, lifetime, 0L, rotate); 084 } 085 086 087 /** 088 * Creates a new refresh token specification. 089 * 090 * @param issue Controls the refresh token issue. If {@code true} 091 * a refresh token must be issued (requires a 092 * long-lived authorisation), {@code false} to 093 * prohibit issue. 094 * @param lifetime The refresh token maximum lifetime, in seconds. 095 * Zero means no lifetime limit. Negative means not 096 * specified (to let the Connect2id server apply the 097 * default configured refresh token lifetime). 098 * Applies only when a refresh token is issued. 099 * @param maxIdleTime The refresh token maximum idle time, in seconds. 100 * Zero means no idle time expiration. 101 * @param rotate The optional rotation preference, if none the 102 * default refresh token rotation policy will apply. 103 */ 104 public RefreshTokenSpec(final boolean issue, 105 final long lifetime, 106 final long maxIdleTime, 107 final Optional<Boolean> rotate) { 108 109 super(issue, lifetime, null, null); 110 this.maxIdleTime = maxIdleTime; 111 this.rotate = rotate; 112 } 113 114 115 /** 116 * Returns the refresh token maximum idle time. 117 * 118 * @return The maximum idle time, in seconds. Zero means no idle time 119 * expiration. 120 */ 121 public long getMaxIdleTime() { 122 return maxIdleTime; 123 } 124 125 126 /** 127 * Returns the optional refresh token rotation preference. 128 * 129 * @return The rotation preference, if none the default refresh token 130 * rotation policy will apply. 131 */ 132 public Optional<Boolean> getRotate() { 133 return rotate; 134 } 135 136 137 @Override 138 public JSONObject toJSONObject() { 139 140 JSONObject o = super.toJSONObject(); 141 if (maxIdleTime > 0L) { 142 o.put("max_idle", maxIdleTime); 143 } 144 rotate.ifPresent(aBoolean -> o.put("rotate", aBoolean)); 145 return o; 146 } 147 148 149 /** 150 * Parses a refresh token specification from the specified JSON object. 151 * 152 * @param o The JSON object. Must not be {@code null}. 153 * 154 * @return The refresh token specification. 155 * 156 * @throws ParseException If parsing failed. 157 */ 158 public static RefreshTokenSpec parse(final JSONObject o) 159 throws ParseException { 160 161 OptionalTokenSpec optionalTokenSpec = OptionalTokenSpec.parse(o); 162 163 long maxIdleTime = 0L; 164 if (o.containsKey("max_idle")) { 165 maxIdleTime = JSONObjectUtils.getLong(o, "max_idle"); 166 } 167 168 Optional<Boolean> rotate; 169 if (o.get("rotate") != null) { 170 rotate = Optional.of(JSONObjectUtils.getBoolean(o, "rotate")); 171 } else { 172 rotate = Optional.empty(); 173 } 174 175 return new RefreshTokenSpec( 176 optionalTokenSpec.issue(), 177 optionalTokenSpec.getLifetime(), 178 maxIdleTime, 179 rotate); 180 } 181}