ShibbolethUserDetailsService.java

/*
 * +====================================================================+
 * |         Copyright (C) 2015 Rochester Institute of Technology,      |
 * |            103 Lomb Memorial Drive, Rochester, NY - 14623          |
 * |                        All Rights Reserved.                        |
 * +====================================================================+
 *   FILENAME
 *    SsoUserDetailsService.java
 *
 *   AUTHOR
 *    @author Khanh Ho (kchisd at rit.edu)
 *
 * =====================================================================
 */

package edu.rit.coopeval.security.sso;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

import edu.rit.coopeval.dao.UserRepository;
import edu.rit.coopeval.model.User;
import edu.rit.coopeval.model.UserRole;
import edu.rit.coopeval.security.SecurityUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component("shibUserDetailsService")
public class ShibbolethUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepo;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepo.findFirstByUsername(username);

        // Because this is pre-authenticated, if the user does not exist just create a new one
        if (user == null) {
            user = new User();
            user.setUsername(username);
            // unguessable random password
            user.setPassword(passwordEncoder.encode(UUID.randomUUID().toString()));

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                .getRequest();
            user.setUid(request.getHeader("ritId"));
            user.setEmail(request.getHeader("mail"));
            user.setName(request.getHeader("displayName"));
            user.setFirstname(request.getHeader("givenName"));
            user.setLastname(request.getHeader("sn"));

            // add role according to RIT account type
            Set<UserRole> roles = new HashSet<>();
            if (StringUtils.hasText(request.getHeader("ritEduAccountType"))) {
                UserRole role = new UserRole(request.getHeader("ritEduAccountType"));
                role.setUser(user);
                roles.add(role);
            }

            user.setRoles(roles);
            user = userRepo.save(user);
        }

        // Map roles to GrantedAuthorities
        Set<GrantedAuthority> authorities;
        if (user.getRoles() != null) {
            authorities = user.getRoles().stream()
                              .map(UserRole::getRole)
                              .map(SimpleGrantedAuthority::new)
                              .collect(Collectors.toSet());
        } else {
            authorities = new HashSet<>();
        }

        return new SecurityUser(user, authorities);
    }
}