Add system properties for persisting the 'remember me' key

This adds the 'airsonic.rememberMeKey' system property (can be set from
command-line with `-Dairsonic.rememberMeKey=<value>`) as well as a
'RememberMeKey' setting in airsonic.properties, so that the key used for
generating 'remember me' tokens can be persisted across server restarts.

It also adds a default, insecure key in case we are running in
development mode with the 'airsonic.development' property set.
master
François-Xavier Thomas 6 years ago
parent b663a2fb90
commit 8a90d9f77b
  1. 30
      airsonic-main/src/main/java/org/airsonic/player/security/GlobalSecurityConfig.java
  2. 22
      airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java

@ -33,6 +33,8 @@ public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter
static final String FAILURE_URL = "/login?error=1";
static final String DEVELOPMENT_REMEMBER_ME_KEY = "airsonic";
@Autowired
private SecurityService securityService;
@ -125,6 +127,32 @@ public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter
restAuthenticationFilter.setEventPublisher(eventPublisher);
http = http.addFilterBefore(restAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
// Try to load the 'remember me' key.
//
// Note that using a fixed key compromises security as perfect
// forward secrecy is not guaranteed anymore.
//
// An external entity can then re-use our authentication cookies before
// the expiration time, or even, given enough time, recover the password
// from the MD5 hash.
//
// See: https://docs.spring.io/spring-security/site/docs/3.0.x/reference/remember-me.html
String rememberMeKey = settingsService.getRememberMeKey();
boolean development = settingsService.isDevelopmentMode();
if (StringUtils.isBlank(rememberMeKey) && !development) {
// ...if it is empty, generate a random key on startup (default).
logger.debug("Generating a new ephemeral 'remember me' key in a secure way.");
rememberMeKey = generateRememberMeKey();
} else if (StringUtils.isBlank(rememberMeKey) && development) {
// ...if we are in development mode, we can use a fixed key.
logger.warn("Using a fixed 'remember me' key because we're in development mode, this is INSECURE.");
rememberMeKey = DEVELOPMENT_REMEMBER_ME_KEY;
} else {
// ...otherwise, use the custom key directly.
logger.info("Using a fixed 'remember me' key from system properties, this is insecure.");
}
http
.csrf()
.requireCsrfProtectionMatcher(csrfSecurityRequestMatcher)
@ -169,7 +197,7 @@ public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter
// see http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#csrf-logout
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")).logoutSuccessUrl(
"/login?logout")
.and().rememberMe().key(generateRememberMeKey());
.and().rememberMe().key(rememberMeKey);
}
}

@ -107,6 +107,7 @@ public class SettingsService {
private static final String KEY_SONOS_SERVICE_NAME = "SonosServiceName";
private static final String KEY_SONOS_SERVICE_ID = "SonosServiceId";
private static final String KEY_JWT_KEY = "JWTKey";
private static final String KEY_REMEMBER_ME_KEY = "RememberMeKey";
private static final String KEY_SMTP_SERVER = "SmtpServer";
private static final String KEY_SMTP_ENCRYPTION = "SmtpEncryption";
@ -794,6 +795,27 @@ public class SettingsService {
setString(KEY_MEDIA_LIBRARY_STATISTICS, statistics.format());
}
/**
* Returns whether we are running in Development mode.
*
* @return true if we are in Development mode.
*/
public boolean isDevelopmentMode() {
return System.getProperty("airsonic.development") != null;
}
/**
* Returns the custom 'remember me' key used for generating authentication tokens.
*
* @return The 'remember me' key.
*/
public String getRememberMeKey() {
String key = null;
if (StringUtils.isBlank(key)) key = getString(KEY_REMEMBER_ME_KEY, null);
if (StringUtils.isBlank(key)) key = System.getProperty("airsonic.rememberMeKey");
return key;
}
/**
* Returns the locale (for language, date format etc).
*

Loading…
Cancel
Save