blob: c24b1a08f86fc4c7f5ac91dc1829660a13cbd86f [file] [log] [blame]
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.acceptance.server.mail;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import com.google.common.io.BaseEncoding;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.server.mail.EmailTokenVerifier;
import com.google.gerrit.server.mail.EmailTokenVerifier.InvalidTokenException;
import com.google.gerrit.server.mail.SignedToken;
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
import com.google.gerrit.testing.ConfigSuite;
import java.nio.charset.StandardCharsets;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
import org.junit.Test;
public class SignedTokenEmailTokenVerifierIT extends AbstractDaemonTest {
@ConfigSuite.Default
public static Config defaultConfig() {
Config cfg = new Config();
cfg.setString("auth", null, "registerEmailPrivateKey", SignedToken.generateRandomKey());
return cfg;
}
private SignedTokenEmailTokenVerifier signedTokenEmailTokenVerifier;
@Before
public void setUp() throws Exception {
signedTokenEmailTokenVerifier =
server
.getTestInjector()
.getBinding(SignedTokenEmailTokenVerifier.class)
.getProvider()
.get();
}
/** Test encode */
@Test
public void encode() throws Exception {
String tokenString = signedTokenEmailTokenVerifier.encode(user.id(), user.email());
int index = tokenString.indexOf("$");
String text = tokenString.substring(index + 1);
String textDecoded = new String(BaseEncoding.base64Url().decode(text), StandardCharsets.UTF_8);
int pos = textDecoded.indexOf(":");
assertThat(textDecoded.substring(0, pos)).isEqualTo(user.id().toString());
assertThat(textDecoded.substring(pos + 1)).isEqualTo(user.email());
}
/** Test decode */
@Test
public void decode() throws Exception {
String tokenString = signedTokenEmailTokenVerifier.encode(user.id(), user.email());
String tokenKey = tokenString.substring(0, tokenString.indexOf("$"));
String text = user.id() + ":" + user.email();
String invalidTokenString =
tokenKey + "$" + BaseEncoding.base64Url().encode(text.getBytes(StandardCharsets.UTF_8));
EmailTokenVerifier.ParsedToken parsedToken =
signedTokenEmailTokenVerifier.decode(invalidTokenString);
assertThat(parsedToken.getAccountId()).isEqualTo(user.id());
assertThat(parsedToken.getEmailAddress()).isEqualTo(user.email());
}
/** Test token format is wrong(without '$' to split key and text) */
@Test
public void invalidFormat() throws Exception {
InvalidTokenException thrown =
assertThrows(
InvalidTokenException.class,
() -> signedTokenEmailTokenVerifier.decode("Invalid token"));
assertThat(thrown)
.hasCauseThat()
.hasMessageThat()
.isEqualTo("Token does not contain character '$'");
}
/** Test input token string is empty or null */
@Test
public void emptyInput() throws Exception {
InvalidTokenException thrownWithNull =
assertThrows(InvalidTokenException.class, () -> signedTokenEmailTokenVerifier.decode(null));
InvalidTokenException thrownWithEmpty =
assertThrows(InvalidTokenException.class, () -> signedTokenEmailTokenVerifier.decode(""));
assertThat(thrownWithNull).hasCauseThat().hasMessageThat().isEqualTo("Empty token");
assertThat(thrownWithEmpty).hasCauseThat().hasMessageThat().isEqualTo("Empty token");
}
/** Test token format is right but key is an illegal BASE64 string */
@Test
public void illegalTokenKey() throws Exception {
InvalidTokenException thrown =
assertThrows(
InvalidTokenException.class,
() -> signedTokenEmailTokenVerifier.decode("Illegal token key$...."));
assertThat(thrown).hasCauseThat().hasMessageThat().isEqualTo("Base64 decoding failed");
}
/** Test token text not match the required pattern */
@Test
public void tokenTextPatternMismatch() throws Exception {
String tokenString = signedTokenEmailTokenVerifier.encode(user.id(), user.email());
String tokenKey = tokenString.substring(0, tokenString.indexOf("$"));
String pattern = user.id() + ":" + user.email();
String invalidTokenTextPattern = tokenKey + "$" + pattern.replace(":", "");
InvalidTokenException thrown =
assertThrows(
InvalidTokenException.class,
() -> signedTokenEmailTokenVerifier.decode(invalidTokenTextPattern));
assertThat(thrown).hasCauseThat().hasMessageThat().isEqualTo("Token text mismatch");
}
}