diff --git a/authme-core/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java b/authme-core/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java index c7256af9e0..f6df3bc6b3 100644 --- a/authme-core/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java +++ b/authme-core/src/main/java/fr/xephi/authme/security/totp/TotpAuthenticator.java @@ -69,8 +69,9 @@ public boolean checkCode(String playerName, String totpKey, String inputCode) { public TotpGenerationResult generateTotpKey(Player player) { GoogleAuthenticatorKey credentials = authenticator.createCredentials(); - String otpAuthUrl = GoogleAuthenticatorQRGenerator.getOtpAuthTotpURL( - settings.getProperty(PluginSettings.SERVER_NAME), player.getName(), credentials); + // The otpauth label is "issuer:account", so the issuer must not contain a colon + String issuer = settings.getProperty(PluginSettings.SERVER_NAME).replace(':', '-'); + String otpAuthUrl = GoogleAuthenticatorQRGenerator.getOtpAuthTotpURL(issuer, player.getName(), credentials); String qrCodeUrl = "https://api.qrserver.com/v1/create-qr-code/?data=" + URLEncoder.encode(otpAuthUrl, StandardCharsets.UTF_8) + "&size=200x200&ecc=M&margin=10"; diff --git a/authme-core/src/test/java/fr/xephi/authme/security/totp/TotpAuthenticatorTest.java b/authme-core/src/test/java/fr/xephi/authme/security/totp/TotpAuthenticatorTest.java index da45004cf6..ac6c3ea937 100644 --- a/authme-core/src/test/java/fr/xephi/authme/security/totp/TotpAuthenticatorTest.java +++ b/authme-core/src/test/java/fr/xephi/authme/security/totp/TotpAuthenticatorTest.java @@ -15,6 +15,9 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + import static fr.xephi.authme.AuthMeMatchers.stringWithLength; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -69,6 +72,25 @@ void shouldGenerateTotpKey() { assertThat(key1.getTotpKey(), not(equalTo(key2.getTotpKey()))); } + @Test + void shouldGenerateTotpKeyForServerNameWithColon() { + // given + totpAuthenticator = new TotpAuthenticator(settings); + + Player player = mock(Player.class); + given(player.getName()).willReturn("Bobby"); + given(settings.getProperty(PluginSettings.SERVER_NAME)).willReturn("UT:Rebirth"); + + // when + TotpGenerationResult key = totpAuthenticator.generateTotpKey(player); + + // then + assertThat(key.getTotpKey(), stringWithLength(32)); + assertThat(key.getAuthenticatorQrCodeUrl(), containsString(URLEncoder.encode( + "otpauth://totp/UT-Rebirth:Bobby?secret=" + key.getTotpKey() + "&issuer=UT-Rebirth&", + StandardCharsets.UTF_8))); + } + @Test void shouldCheckCodeAndDeclareItValidOnlyOnce() { // given