com.thoughtworks.go.server.security.providers.FileAuthenticationProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.thoughtworks.go.server.security.providers.FileAuthenticationProvider.java

Source

/*************************GO-LICENSE-START*********************************
 * Copyright 2014 ThoughtWorks, 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.
 *************************GO-LICENSE-END***********************************/

package com.thoughtworks.go.server.security.providers;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import com.thoughtworks.go.server.security.AuthorityGranter;
import com.thoughtworks.go.server.security.userdetail.GoUserPrinciple;
import com.thoughtworks.go.server.service.GoConfigService;
import com.thoughtworks.go.server.service.SecurityService;
import com.thoughtworks.go.server.service.UserService;
import com.thoughtworks.go.util.StringUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.AuthenticationException;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.providers.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.userdetails.User;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.security.userdetails.memory.UserMap;
import org.springframework.security.userdetails.memory.UserMapEditor;

public class FileAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    private final GoConfigService goConfigService;
    private final AuthorityGranter authorityGranter;
    private final UserService userService;
    private final SecurityService securityService;

    @Autowired
    public FileAuthenticationProvider(GoConfigService goConfigService, AuthorityGranter authorityGranter,
            UserService userService, SecurityService securityService) {
        this.goConfigService = goConfigService;
        this.authorityGranter = authorityGranter;
        this.userService = userService;
        this.securityService = securityService;
    }

    protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        final String plainTextPassword = (String) authentication.getCredentials();
        if (!userDetails.getPassword().equals(StringUtil.sha1Digest(plainTextPassword.getBytes()))) {
            throw new BadCredentialsException(messages
                    .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credential"));
        }
    }

    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        final String passwordFilePath = goConfigService.security().passwordFileConfig().path();
        try {
            UserMap userMap = UserMapEditor.addUsersFromProperties(new UserMap(),
                    addDummyRoleToPropertiesIfRequired(
                            stripShaFromPasswordsIfRequired(loadPasswordFile(passwordFilePath))));
            final UserDetails details = userMap.getUser(username);
            return userStrippedOfAnyAuthoritiesSpecifiedInFile(username, details);
        } catch (IOException e) {
            throw new UsernameNotFoundException(
                    "Trying to authenticate user " + username + " but could not open file: " + passwordFilePath);
        }

    }

    private Properties loadPasswordFile(String passwordFilePath) throws IOException {
        final Properties properties = new Properties();
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(passwordFilePath);
            properties.load(inputStream);
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
        return properties;
    }

    private User userStrippedOfAnyAuthoritiesSpecifiedInFile(String username, UserDetails details) {
        com.thoughtworks.go.domain.User user = userService.findUserByName(details.getUsername());
        String displayName = username;
        if (user != null && !user.getDisplayName().isEmpty()) {
            displayName = user.getDisplayName();
        }
        return new GoUserPrinciple(details.getUsername(), displayName, details.getPassword(), details.isEnabled(),
                details.isAccountNonExpired(), details.isCredentialsNonExpired(), details.isAccountNonLocked(),
                authorityGranter.authorities(username));
    }

    private Properties addDummyRoleToPropertiesIfRequired(Properties properties) {
        for (Object key : properties.keySet()) {
            String value = properties.getProperty(String.valueOf(key));
            if (!value.contains(",")) {
                properties.setProperty(String.valueOf(key), value + ",ROLE_USER");
            }
        }
        return properties;
    }

    private Properties stripShaFromPasswordsIfRequired(Properties properties) {
        for (Object key : properties.keySet()) {
            String value = properties.getProperty(String.valueOf(key));
            if (value.startsWith("{SHA}")) {
                properties.setProperty(String.valueOf(key), value.substring(5));
            }
        }
        return properties;
    }

    @Override
    public boolean supports(Class authentication) {
        return isPasswordFileConfigured() && super.supports(authentication);
    }

    private boolean isPasswordFileConfigured() {
        return goConfigService.security().passwordFileConfig().isEnabled();
    }
}