001package com.nimbusds.openid.connect.provider.spi.secrets; 002 003 004import java.util.Date; 005 006import net.jcip.annotations.Immutable; 007import org.checkerframework.checker.nullness.qual.Nullable; 008 009import com.nimbusds.oauth2.sdk.auth.Secret; 010 011 012/** 013 * Decoded secret. 014 */ 015@Immutable 016public class DecodedSecret extends Secret { 017 018 019 /** 020 * Verifier for hashed secrets. 021 */ 022 private final SecretVerifier verifier; 023 024 025 /** 026 * The encoded (stored) value, {@code null} if not specified. 027 */ 028 private final @Nullable String encodedValue; 029 030 031 /** 032 * Private constructor. 033 */ 034 private DecodedSecret(final String decodedValue, 035 final @Nullable Date expDate, 036 final SecretVerifier verifier, 037 final @Nullable String encodedValue) { 038 super(decodedValue, expDate); 039 this.verifier = verifier; 040 this.encodedValue = encodedValue; 041 } 042 043 044 /** 045 * Returns a new decoded secret with the specified expiration date. 046 * 047 * @param expDate The expiration date, {@code null} if not specified. 048 * 049 * @return The new decoded secret. 050 */ 051 public DecodedSecret withExpiration(final @Nullable Date expDate) { 052 if (getValue() != null) { 053 return new DecodedSecret(getValue(), expDate, null, encodedValue); 054 } else { 055 DecodedSecret decodedSecret = new DecodedSecret("erase", expDate, verifier, encodedValue); 056 decodedSecret.erase(); 057 return decodedSecret; 058 } 059 } 060 061 062 /** 063 * Returns the encoded (stored) value. 064 * 065 * @return The encoded value, {@code null} if not specified. 066 */ 067 public @Nullable String getEncodedValue() { 068 return encodedValue; 069 } 070 071 072 /** 073 * Returns a new decoded secret associating the specified encoded 074 * (stored) value with it. 075 * 076 * @param encodedValue The encoded (stored) value, {@code null} if not 077 * specified. 078 * 079 * @return The new decoded secret. 080 */ 081 public DecodedSecret withEncodedValue(final @Nullable String encodedValue) { 082 083 if (getValue() != null) { 084 return new DecodedSecret(getValue(), getExpirationDate(), null, encodedValue); 085 } else { 086 DecodedSecret decodedSecret = new DecodedSecret("erase", getExpirationDate(), verifier, encodedValue); 087 decodedSecret.erase(); 088 return decodedSecret; 089 } 090 } 091 092 093 @Override 094 public boolean equals(Object o) { 095 096 if (verifier != null && o instanceof Secret) { 097 return verifier.verify((Secret) o); 098 } 099 100 return super.equals(o); 101 } 102 103 104 /** 105 * Creates a new decoded plain secret. 106 * 107 * @param plainValue The plain secret value. Must not be empty or 108 * {@code null}. 109 * 110 * @return The decoded secret. 111 */ 112 public static DecodedSecret createForPlainSecret(final String plainValue) { 113 114 if (plainValue == null || plainValue.trim().isEmpty()) { 115 throw new IllegalArgumentException("The plain secret value must not be null or empty"); 116 } 117 118 return new DecodedSecret(plainValue, null, null, null); 119 } 120 121 122 /** 123 * Creates a new decoded hashed secret. 124 * 125 * @param verifier Verifier to check secrets against the hash. Must not 126 * be {@code null}. 127 * 128 * @return The decoded secret. 129 */ 130 public static DecodedSecret createForHashedSecret(final SecretVerifier verifier) { 131 132 if (verifier == null) { 133 throw new IllegalArgumentException("The secret verifier must not be null"); 134 } 135 136 DecodedSecret decodedSecret = new DecodedSecret("erase", null, verifier, null); 137 decodedSecret.erase(); 138 return decodedSecret; 139 } 140}