001    package com.nimbusds.oauth2.sdk.auth;
002    
003    
004    import java.util.Date;
005    
006    import org.apache.commons.lang3.RandomStringUtils;
007    
008    import com.nimbusds.oauth2.sdk.util.StringUtils;
009    
010    
011    /**
012     * Secret or password. The secret should be {@link #erase erased} when no 
013     * longer in use.
014     *
015     * @author Vladimir Dzhuvinov
016     * @version $version$ (2013-03-05)
017     */
018    public class Secret {
019    
020    
021            /**
022             * The secret value.
023             */
024            private String value;
025    
026    
027            /**
028             * Optional expiration date.
029             */
030            private final Date expDate;
031    
032    
033            /**
034             * Creates a new secret with the specified value.
035             *
036             * @param value The value. Must not be {@code null} or empty string.
037             */
038            public Secret(final String value) {
039    
040                    this(value, null);
041            }
042    
043    
044            /**
045             * Creates a new secret with the specified value and expiration date.
046             *
047             * @param value   The value. Must not be {@code null} or empty string.
048             * @param expDate The expiration date, {@code null} if not specified.
049             */
050            public Secret(final String value, final Date expDate) {
051    
052                    if (StringUtils.isUndefined(value))
053                            throw new IllegalArgumentException("The value must not be null or empty string");
054    
055                    this.value = value;
056    
057                    this.expDate = expDate;
058            }
059    
060    
061            /**
062             * Creates a new secret with a randomly generated value of the 
063             * specified length. The value will be made up of mixed-case 
064             * alphanumeric ASCII characters.
065             *
066             * @param length The number of characters. Must be a positive integer.
067             */
068            public Secret(final int length) {
069            
070                    this(RandomStringUtils.randomAlphanumeric(length));
071            }
072            
073            
074            /**
075             * Creates a new secret with a randomly generated value. The value will
076             * be made up of 32 mixed-case alphanumeric ASCII characters.
077             */
078            public Secret() {
079    
080                    this(32);
081            }
082    
083    
084            /**
085             * Gets the value of this secret.
086             *
087             * @return The value, {@code null} if it has been erased.
088             */
089            public String getValue() {
090    
091                    return value;
092            }
093    
094    
095            /**
096             * Erases of the value of this secret.
097             */
098            public void erase() {
099    
100                    value = null;
101            }
102    
103    
104            /**
105             * Gets the expiration date of this secret.
106             *
107             * @return The expiration date, {@code null} if not specified.
108             */
109            public Date getExpirationDate() {
110    
111                    return expDate;
112            }
113    
114    
115            /**
116             * Checks is this secret has expired.
117             *
118             * @return {@code true} if the secret has an associated expiration date
119             *         which is in the past (according to the current system time), 
120             *         else returns {@code false}.
121             */
122            public boolean expired() {
123    
124                    if (expDate == null)
125                            return false;
126    
127                    final Date now = new Date();
128    
129                    if (expDate.after(now))
130                            return false;
131                    else
132                            return true;
133            }
134    
135            
136            
137            /**
138             * Overrides {@code Object.equals()}.
139             *
140             * @param object The object to compare to.
141             *
142             * @return {@code true} if the objects are secrets the same value, 
143             *         otherwise {@code false}.
144             */
145            @Override
146            public boolean equals(final Object object) {
147            
148                    return object != null && 
149                           object instanceof Secret && 
150                           this.getValue().equals(((Secret)object).getValue());
151            }
152    }