diff --git a/src/main/java/org/whispersystems/textsecuregcm/auth/DeviceAuthenticator.java b/src/main/java/org/whispersystems/textsecuregcm/auth/DeviceAuthenticator.java new file mode 100644 index 000000000..bb68abea3 --- /dev/null +++ b/src/main/java/org/whispersystems/textsecuregcm/auth/DeviceAuthenticator.java @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2013 Open WhisperSystems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.whispersystems.textsecuregcm.auth; + +import com.google.common.base.Optional; +import com.yammer.dropwizard.auth.AuthenticationException; +import com.yammer.dropwizard.auth.Authenticator; +import com.yammer.dropwizard.auth.basic.BasicCredentials; +import com.yammer.metrics.Metrics; +import com.yammer.metrics.core.Meter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.whispersystems.textsecuregcm.storage.Device; +import org.whispersystems.textsecuregcm.storage.AccountsManager; + +import java.util.concurrent.TimeUnit; + +public class DeviceAuthenticator implements Authenticator { + + private final Meter authenticationFailedMeter = Metrics.newMeter(DeviceAuthenticator.class, + "authentication", "failed", + TimeUnit.MINUTES); + + private final Meter authenticationSucceededMeter = Metrics.newMeter(DeviceAuthenticator.class, + "authentication", "succeeded", + TimeUnit.MINUTES); + + private final Logger logger = LoggerFactory.getLogger(DeviceAuthenticator.class); + + private final AccountsManager accountsManager; + + public DeviceAuthenticator(AccountsManager accountsManager) { + this.accountsManager = accountsManager; + } + + @Override + public Optional authenticate(BasicCredentials basicCredentials) + throws AuthenticationException + { + AuthorizationHeader authorizationHeader; + try { + authorizationHeader = AuthorizationHeader.fromUserAndPassword(basicCredentials.getUsername(), basicCredentials.getPassword()); + } catch (InvalidAuthorizationHeaderException iahe) { + return Optional.absent(); + } + Optional device = accountsManager.get(authorizationHeader.getNumber(), authorizationHeader.getDeviceId()); + + if (!device.isPresent()) { + return Optional.absent(); + } + + if (device.get().getAuthenticationCredentials().verify(basicCredentials.getPassword())) { + authenticationSucceededMeter.mark(); + return device; + } + + authenticationFailedMeter.mark(); + return Optional.absent(); + } +}