AuthenticationController.java

/**
 * TFG 75.678 - TFG Desarrollo web 2020 e-Learning for Schools
 * Copyright (C) 2020  Eduardo Rodriguez Carro
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.uoc.tfg.sel.web;

import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.CurrentSecurityContext;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.uoc.tfg.sel.repository.model.User;
import org.uoc.tfg.sel.security.JwtUtil;
import org.uoc.tfg.sel.security.model.AuthenticationRequest;
import org.uoc.tfg.sel.security.model.AuthenticationResponse;
import org.uoc.tfg.sel.security.model.JWTToken;
import org.uoc.tfg.sel.security.model.UserDetailsExtended;
import org.uoc.tfg.sel.service.SessionService;

/**
 * Controlador de autenticacion
 * 
 * @author Eduardo Rodriguez Carro
 *
 */
@RestController
@CrossOrigin
@RequestMapping("/auth")
public class AuthenticationController {

	/**
	 * tiempo maximo de vida de la sesion
	 */
	@Value("${security.session.token.lifetime:31536000000}")
	private Long tokenLifeTime;
	
	/**
	 * Autenticador de Spring Security
	 */
	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private SessionService sessionService;
	
	/**
	 * Utilidades de JWT 
	 */
	@Autowired
	private JwtUtil jwtUtil;

	/**
	 * Endpoint de logout
	 * 
	 * @param uuid ide a retornar
	 * 
	 * @return retorna siempre estado OK
	 */
	@RequestMapping(value = "/logout", method = RequestMethod.POST)
	public ResponseEntity<Void> logout(@CurrentSecurityContext(expression = "authentication.principal") UserDetailsExtended userDetails) {
		if(userDetails != null) {
			sessionService.logout(userDetails.getSessionId());
		}
		return ResponseEntity.ok().build();
	}
	
	
	/**
	 * Endpoint de login
	 * 
	 * @param authenticationRequest
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public ResponseEntity<AuthenticationResponse> login(@RequestBody AuthenticationRequest authenticationRequest) throws Exception {
		
		// Autenticamos con el API del framework
		// En caso de error el proceso del API sale por error
		Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()));
		
		// Si hemos autenticado, obtenemos el nombre del usuario del objeto de usuario encapsulado en el UserDetails de Spring
		User user = null;
		UserDetailsExtended userAuthentication = null;
		if (authentication.getPrincipal() instanceof UserDetailsExtended) {
			userAuthentication = (UserDetailsExtended) authentication.getPrincipal();
			user = userAuthentication.getUser();
		} else {
			user = (User) authentication.getPrincipal();
		}
		
		// Borramos la password por seguridad
		user.setPassword(null);
		
		Map<String,Object> claims = new HashMap<>();
		
		String sessionId = sessionService.generateSession();
		
		if(userAuthentication !=null) {	
			userAuthentication.setSessionId(sessionId);
		}
		
		claims.put(JWTToken.SESSION_ID, sessionId);
		
		// Generamos el token JWT firmado
		String token = jwtUtil.generateToken(claims,user.getLogin(),tokenLifeTime);
		
		AuthenticationResponse response = new AuthenticationResponse();
		response.setUser(user);
		response.setToken(token);
		
		// Respondemos con el estado OK 
		return ResponseEntity.ok(response);
	}

}