Skip to content

Commit aaef54d

Browse files
committed
Issue ESAPI#316 -- Deprecated existing HTTPUtilities.setRememberToken() for one that doesn't require user password.
1 parent 4d63b1d commit aaef54d

File tree

4 files changed

+87
-5
lines changed

4 files changed

+87
-5
lines changed

pom.xml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,17 @@
187187
<artifactId>antisamy</artifactId>
188188
<version>1.5.3</version>
189189
</dependency>
190-
191190
<dependency>
192191
<groupId>org.apache.xmlgraphics</groupId>
193192
<artifactId>batik-css</artifactId>
194193
<version>1.8</version>
195194
</dependency>
196-
197-
195+
<dependency>
196+
<groupId>org.mockito</groupId>
197+
<artifactId>mockito-all</artifactId>
198+
<version>1.10.19</version>
199+
<scope>test</scope>
200+
</dependency>
198201
</dependencies>
199202

200203
<build>

src/main/java/org/owasp/esapi/HTTPUtilities.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,12 +543,21 @@ public interface HTTPUtilities
543543

544544
/**
545545
* Calls setNoCacheHeaders with the *current* response.
546+
*
547+
* ~DEPRECATED~ Per Kevin Wall, storing passwords with reversible encryption is contrary to *many*
548+
* company's stated security policies.
546549
*
547550
* @see {@link HTTPUtilities#setCurrentHTTP(HttpServletRequest, HttpServletResponse)}
548551
*/
552+
@Deprecated
549553
String setRememberToken(String password, int maxAge, String domain, String path);
550554

555+
/**
556+
*
557+
*/
558+
String setRememberToken(HttpServletRequest request, HttpServletResponse response, int maxAge, String domain, String path);
551559

560+
552561
/**
553562
* Set a cookie containing the current User's remember me token for automatic authentication. The use of remember me tokens
554563
* is generally not recommended, but this method will help do it as safely as possible. The user interface should strongly warn
@@ -564,6 +573,9 @@ public interface HTTPUtilities
564573
* <p/>
565574
* The username can be retrieved with: User username = ESAPI.authenticator().getCurrentUser();
566575
*
576+
*~DEPRECATED~ Per Kevin Wall, storing passwords with reversible encryption is contrary to *many*
577+
* company's stated security policies.
578+
*
567579
* @param request
568580
* @param password the user's password
569581
* @param response
@@ -572,6 +584,7 @@ public interface HTTPUtilities
572584
* @param path the path to restrict the token to or null
573585
* @return encrypted "Remember Me" token stored as a String
574586
*/
587+
@Deprecated
575588
String setRememberToken(HttpServletRequest request, HttpServletResponse response, String password, int maxAge, String domain, String path);
576589

577590

src/main/java/org/owasp/esapi/reference/DefaultHTTPUtilities.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,36 @@ public String setRememberToken( HttpServletRequest request, HttpServletResponse
945945
return null;
946946
}
947947
}
948+
949+
950+
public String setRememberToken(HttpServletRequest request, HttpServletResponse response, int maxAge, String domain, String path){
951+
String rval = "";
952+
User user = ESAPI.authenticator().getCurrentUser();
953+
954+
try{
955+
killCookie(request,response, REMEMBER_TOKEN_COOKIE_NAME);
956+
// seal already contains random data
957+
String clearToken = user.getAccountName();
958+
long expiry = ESAPI.encryptor().getRelativeTimeStamp(maxAge * 1000);
959+
String cryptToken = ESAPI.encryptor().seal(clearToken, expiry);
960+
961+
// Do NOT URLEncode cryptToken before creating cookie. See Google Issue # 144,
962+
// which was marked as "WontFix".
963+
964+
Cookie cookie = new Cookie( REMEMBER_TOKEN_COOKIE_NAME, cryptToken );
965+
cookie.setMaxAge( maxAge );
966+
cookie.setDomain( domain );
967+
cookie.setPath( path );
968+
response.addCookie( cookie );
969+
logger.info(Logger.SECURITY_SUCCESS, "Enabled remember me token for " + user.getAccountName() );
970+
} catch( IntegrityException e){
971+
logger.warning(Logger.SECURITY_FAILURE, "Attempt to set remember me token failed for " + user.getAccountName(), e );
972+
return null;
973+
}
974+
975+
976+
return rval;
977+
}
948978

949979
/**
950980
* {@inheritDoc}

src/test/java/org/owasp/esapi/reference/HTTPUtilitiesTest.java

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.io.File;
1919
import java.io.IOException;
20+
import java.lang.reflect.Field;
2021
import java.util.ArrayList;
2122
import java.util.HashMap;
2223
import java.util.Iterator;
@@ -25,6 +26,7 @@
2526

2627
import javax.servlet.http.Cookie;
2728
import javax.servlet.http.HttpServletRequest;
29+
import javax.servlet.http.HttpServletResponse;
2830
import javax.servlet.http.HttpSession;
2931

3032
import org.owasp.esapi.Authenticator;
@@ -47,7 +49,6 @@
4749
import junit.framework.Test;
4850
import junit.framework.TestCase;
4951
import junit.framework.TestSuite;
50-
5152
/**
5253
* The Class HTTPUtilitiesTest.
5354
*
@@ -465,7 +466,7 @@ public void testSetNoCacheHeaders() {
465466
*
466467
* @throws org.owasp.esapi.errors.AuthenticationException
467468
*/
468-
public void testSetRememberToken() throws AuthenticationException {
469+
public void testDeprecatedSetRememberToken() throws AuthenticationException {
469470
System.out.println("setRememberToken");
470471
Authenticator instance = (Authenticator)ESAPI.authenticator();
471472
String accountName=ESAPI.randomizer().getRandomString(8, EncoderConstants.CHAR_ALPHANUMERICS);
@@ -485,6 +486,41 @@ public void testSetRememberToken() throws AuthenticationException {
485486
// String value = response.getCookie( Authenticator.REMEMBER_TOKEN_COOKIE_NAME ).getValue();
486487
// assertEquals( user.getRememberToken(), value );
487488
}
489+
490+
/**
491+
*
492+
* @throws org.owasp.esapi.errors.AuthenticationException
493+
*/
494+
public void testSetRememberToken() throws Exception {
495+
System.out.println("setRememberToken");
496+
Authenticator instance = (Authenticator)ESAPI.authenticator();
497+
String accountName=ESAPI.randomizer().getRandomString(8, EncoderConstants.CHAR_ALPHANUMERICS);
498+
String password = instance.generateStrongPassword();
499+
User user = instance.createUser(accountName, password, password);
500+
user.enable();
501+
MockHttpServletRequest request = new MockHttpServletRequest();
502+
request.addParameter("username", accountName);
503+
request.addParameter("password", password);
504+
HttpServletResponse response = new MockHttpServletResponse();
505+
ESAPI.httpUtilities().setCurrentHTTP(request, response);
506+
instance.login( request, response);
507+
508+
int maxAge = ( 60 * 60 * 24 * 14 );
509+
510+
ESAPI.httpUtilities().setRememberToken( request, response, maxAge, "domain", "/" );
511+
512+
Field field = response.getClass().getDeclaredField("cookies");
513+
field.setAccessible(true);
514+
List<Cookie> cookies = (List<Cookie>) field.get(response);
515+
Cookie cookie = null;
516+
for(Cookie c: cookies){
517+
if(c.getName().equals(HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME)){
518+
cookie = c;
519+
break;
520+
}
521+
}
522+
assertEquals(HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME, cookie.getName());
523+
}
488524

489525
public void testGetSessionAttribute() throws Exception {
490526
HttpServletRequest request = new MockHttpServletRequest();

0 commit comments

Comments
 (0)