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}