public class AccessToken {
    @Id
    String id;

    String userId;

    String token;

    Date lastUsed;

    public AccessToken(@NotNull String userId, @NotNull String token, @NotNull Date lastUsed) {
        this.userId = userId;
        this.token = token;
        this.lastUsed = lastUsed;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public Date getLastUsed() {
        return lastUsed;
    }

    public void setLastUsed(Date lastUsed) {
        this.lastUsed = lastUsed;
    }
} public static class AuthenticationInfo {
    @JsonProperty
    String type;

    @JsonProperty
    @JsonInclude(JsonInclude.Include.NON_NULL)
    List<String> stages;

    public void setStages(List<String> stages) {
        this.stages = stages;
    }

    public void setType(String type) {
        this.type = type;
    }

    public boolean validateKeys(AuthenticationSubmission authentication) {
        return true;
    }
} public static class AuthenticationResult {

    @JsonProperty("user_id")
    String user;

    @JsonProperty("access_token")
    String accessToken;

    public AuthenticationResult(String user, String accessToken) {
        this.user = user;
        this.accessToken = accessToken;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getAccessToken() {
        return accessToken;
    }
} public static class AuthenticationSubmission extends HashMap<String, String> {
    static final String TYPE = "type";
    static final String REMOTE_ADDR = "remoteAddr";

    public AuthenticationSubmission() {
    }

    public String getType() {
        return get(TYPE);
    }

    public void setRemoteAddr(String remoteAddr) {
        put(REMOTE_ADDR, remoteAddr);
    }

    public String getRemoteAddr() {
        return get(REMOTE_ADDR);
    }
} public class User {
    @Id
    String id;

    String userId;

    @JsonProperty("password")
    String hashedPassword;

    @JsonView(AvatarUrlSummary.class)
    @JsonProperty("avatar_url")
    String avatarUrl;

    @JsonView(DisplayNameSummary.class)
    @JsonProperty("displayname")
    String displayName;

    public User() {
    }

    public User(String userId, String hashedPassword) {
        this.userId = userId;
        this.hashedPassword = hashedPassword;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getHashedPassword() {
        return hashedPassword;
    }

    public void setHashedPassword(String password) {
        this.hashedPassword = password;
    }

    public String getAvatarUrl() {
        return avatarUrl;
    }

    public void setAvatarUrl(String avatarUrl) {
        this.avatarUrl = avatarUrl;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public interface DisplayNameSummary {}

    public interface AvatarUrlSummary {}
} public interface AccessTokenService {
    public boolean isTokenAssigned(String userId, String token);

    public AccessToken createOrUpdateToken(AccessToken accessToken);
} public class InvalidRequestException extends RuntimeException {
    public InvalidRequestException(final String message) {
        super(message);
    }
} public interface AuthenticationProvider {
    AuthenticationInfo getFlow();

    AuthenticationResult register(AuthenticationSubmission authentication);

    AuthenticationResult login(AuthenticationSubmission authentication);
} public interface UserService {
    public User createUser(User user);

    public User findUserById(String userId);

    public void saveDisplayName(String userId, String displayName, String accessToken);

    public void saveAvatarUrl(String userId, String avatarUrl, String accessToken);

    public User findLoggedUserById(String userId, String accessToken);
} @Component
public class UserUtils {
    public String generateUserId(String userIdOrLocalPart) {
        String userIdRegular = String.format("^@\\S*:%s$", StringUtils.replace(DOMAIN, ".", "\\."));
        Pattern p = Pattern.compile(userIdRegular);
        Matcher m = p.matcher(userIdOrLocalPart);

        return m.matches() ? userIdOrLocalPart : join(new String[]{"@", userIdOrLocalPart,":", DOMAIN});

    }

    public String generateAccessToken() {
        return random(16, true, false);
    }
} public class RecaptchaInfo extends AuthenticationInfo {
    final static String RECAPTCHA_TYPE = "m.login.recaptcha";
    final static String CHALLENGE = "challenge";
    final static String RESPONSE = "response";

    public RecaptchaInfo() {
        setType(RECAPTCHA_TYPE);
    }

    @Override
    public boolean validateKeys(AuthenticationSubmission authentication) {
        return authentication.containsKey(CHALLENGE) && authentication.containsKey(RESPONSE);
    }
}
import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.swarmcom.jsynapse.domain.AccessToken;
import org.swarmcom.jsynapse.domain.Authentication.AuthenticationInfo;
import org.swarmcom.jsynapse.domain.Authentication.AuthenticationResult;
import org.swarmcom.jsynapse.domain.Authentication.AuthenticationSubmission;
import org.swarmcom.jsynapse.domain.User;
import org.swarmcom.jsynapse.service.accesstoken.AccessTokenService;
import org.swarmcom.jsynapse.service.exception.InvalidRequestException;
import org.swarmcom.jsynapse.service.authentication.AuthenticationProvider;
import org.swarmcom.jsynapse.service.user.UserService;
import org.swarmcom.jsynapse.service.user.UserUtils;
import javax.inject.Inject;
import java.util.Date;
import static org.swarmcom.jsynapse.service.authentication.recaptcha.RecaptchaInfo.*;
import static java.lang.String.format;
/*
 * (C) Copyright 2015 eZuce Inc.
 *
 * 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 org.swarmcom.jsynapse.service.authentication.recaptcha;





@Component(RECAPTCHA_TYPE)
public class RecaptchaProvider implements AuthenticationProvider {
    final static AuthenticationInfo flow = new RecaptchaInfo();
    private static final Logger LOGGER = LoggerFactory.getLogger(RecaptchaProvider.class);

    private final UserService userService;
    private final AccessTokenService accessTokenService;
    private final UserUtils userUtils;