nineskeletor/src/Controller/SecurityController.php

525 lines
21 KiB
PHP
Executable File

<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Ramsey\Uuid\Uuid;
use App\Entity\User;
use App\Entity\Niveau01;
use App\Entity\Group;
use App\Form\LoginType;
use App\Service\LdapService;
use App\Service\ApiService;
class SecurityController extends AbstractController
{
private $appKernel;
private $tokenstorage;
private $ldapservice;
private $apiservice;
public function __construct(KernelInterface $appKernel, TokenStorageInterface $tokenstorage, LdapService $ldapservice, ApiService $apiservice)
{
$this->appKernel = $appKernel;
$this->tokenstorage = $tokenstorage;
$this->ldapservice = $ldapservice;
$this->apiservice = $apiservice;
}
public function noperm(Request $request)
{
return $this->render('Home/noperm.html.twig',[
"useheader"=>true,
"usemenu"=>false,
]);
}
public function login(Request $request, AuthenticationUtils $authenticationUtils,ManagerRegistry $em)
{
switch($this->getParameter("appAuth")) {
case "SQL":
return $this->loginSQL($request,$authenticationUtils,$em);
break;
case "CAS":
return $this->loginCAS($request,$authenticationUtils,$em);
break;
case "LDAP":
return $this->loginLDAP($request,$authenticationUtils,$em);
break;
case "OPENID":
return $this->loginOPENID($request,$authenticationUtils,$em);
break;
}
}
public function loginSQL(Request $request, AuthenticationUtils $authenticationUtils,ManagerRegistry $em)
{
return $this->render('Home/loginSQL.html.twig', array(
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),
));
}
public function loginCAS(Request $request, AuthenticationUtils $authenticationUtils,ManagerRegistry $em)
{
// Récupération de la cible de navigation
$redirect = $request->getSession()->get("_security.main.target_path");
// Masteridentity
$appMasteridentity=$this->getParameter("appMasteridentity");
// Init Client CAS
$alias=$this->getParameter('appAlias');
\phpCAS::setDebug($this->appKernel->getProjectDir()."/var/log/cas.log");
\phpCAS::client(CAS_VERSION_2_0, $this->getParameter('casHost'), intval($this->getParameter('casPort')), is_null($this->getParameter('casPath')) ? '' : $this->getParameter('casPath'), false);
\phpCAS::setNoCasServerValidation();
// Authentification
\phpCAS::forceAuthentication();
// Récupération UID
$username = \phpCAS::getUser();
// Récupération Attribut
$attributes = \phpCAS::getAttributes();
// Init
$email = "$username@nomail.fr";
$lastname = $username;
$firstname = " ";
$avatar="noavatar.png";
// Rechercher l'utilisateur
if(isset($attributes[$this->getParameter('casUsername')]))
$username = $attributes[$this->getParameter('casUsername')];
if(isset($attributes[$this->getParameter('casEmail')]))
$email = $attributes[$this->getParameter('casEmail')];
if(isset($attributes[$this->getParameter('casLastname')]))
$lastname = $attributes[$this->getParameter('casLastname')];
if(isset($attributes[$this->getParameter('casFirstname')]))
$firstname = $attributes[$this->getParameter('casFirstname')];
if(isset($attributes[$this->getParameter('casAvatar')]))
$avatar = $attributes[$this->getParameter('casAvatar')];
// Rechercher l'utilisateur
$user = $em->getRepository('App\Entity\User')->findOneBy(array("username"=>$username));
if (!$user) {
if(!$this->getParameter("casAutosubmit")) return $this->redirect($this->generateUrl('app_noperm'));
$this->submitSSONiveau01($attributes,$em);
$this->submitSSOGroup($attributes,$em);
$niveau01=$em->getRepository('App\Entity\Niveau01')->calculateSSONiveau01($attributes);
$user=$this->submituser($username,$firstname,$lastname,$email,$avatar,$niveau01,$em);
$user=$em->getRepository('App\Entity\Group')->calculateSSOGroup($user,$attributes);
}
elseif($this->getParameter("casAutoupdate")) {
$this->submitSSONiveau01($attributes,$em);
$this->submitSSOGroup($attributes,$em);
$this->updateuser($user,$firstname,$lastname,$email,$avatar,$em);
$user=$em->getRepository('App\Entity\Group')->calculateSSOGroup($user,$attributes);
}
// Autoconnexion
return $this->autoconnexion($user,$redirect,$request);
}
public function loginLDAP(Request $request, AuthenticationUtils $authenticationUtils,ManagerRegistry $em)
{
// Création du formulaire
$form = $this->createForm(LoginType::class);
// Récupération des data du formulaire
$form->handleRequest($request);
// Affichage du formulaire
return $this->render("Home/loginLDAP.html.twig", [
"useheader"=>false,
"usemenu"=>false,
"usesidebar"=>false,
"form"=>$form->createView(),
]);
}
public function loginldapcheck(Request $request, AuthenticationUtils $authenticationUtils,ManagerRegistry $em)
{
$username=$request->get('login')["username"];
$password=$request->get('login')["password"];
// Récupération de la cible de navigation
$redirect = $request->getSession()->get("_security.main.target_path");
// L'utilisateur se co à l'annuaire
$userldap=$this->ldapservice->userconnect($username,$password);
if($userldap) {
$userldap=$userldap[0];
// Init
$email = "$username@nomail.fr";
$lastname = $username;
$firstname = " ";
$avatar="noavatar.png";
// Rechercher l'utilisateur
if(isset($userldap[$this->getParameter('ldapFirstname')]))
$firstname = $userldap[$this->getParameter('ldapFirstname')];
if(isset($userldap[$this->getParameter('ldapLastname')]))
$lastname = $userldap[$this->getParameter('ldapLastname')];
if(isset($userldap[$this->getParameter('ldapEmail')]))
$email = $userldap[$this->getParameter('ldapEmail')];
if(isset($userldap[$this->getParameter('ldapAvatar')]))
$avatar = $userldap[$this->getParameter('ldapAvatar')];
$user = $em->getRepository('App\Entity\User')->findOneBy(array("username"=>$username));
if (!$user) {
if(!$this->getParameter("ldapAutosubmit")) return $this->redirect($this->generateUrl('app_noperm'));
$niveau01=$em->getRepository('App\Entity\Niveau01')->calculateLDAPNiveau01($username);
$user=$this->submituser($username,$firstname,$lastname,$email,$avatar,$niveau01,$em);
}
elseif($this->getParameter("ldapAutoupdate")) {
$this->updateuser($user,$firstname,$lastname,$email,$avatar,$em);
}
// Autoconnexion
return $this->autoconnexion($user,$redirect,$request);
}
return $this->redirect($this->generateUrl('app_login'));
}
public function loginOPENID(Request $request, AuthenticationUtils $authenticationUtils,ManagerRegistry $em)
{
$state=Uuid::uuid4();
$request->getSession()->set("oauthState",$state);
$callback=$this->generateUrl('app_loginopenidcallback', array(), UrlGeneratorInterface::ABSOLUTE_URL);
$url=$this->getParameter("oauthLoginurl")."?client_id=".$this->getParameter("oauthClientid")."&redirect_uri=".$callback."&response_type=code&state=".$state."&scope=openid";
return $this->redirect($url);
}
public function loginopenidcallback(Request $request, AuthenticationUtils $authenticationUtils,ManagerRegistry $em)
{
// Récupération de la cible de navigation
$redirect = $request->getSession()->get("_security.main.target_path");
// Masteridentity
$appMasteridentity=$this->getParameter("appMasteridentity");
$callback=$this->generateUrl('app_loginopenidcallback', array(), UrlGeneratorInterface::ABSOLUTE_URL);
$apiurl = $this->getParameter("oauthTokenurl");
$query= [
"grant_type" => "authorization_code",
"code" => $request->get("code"),
"redirect_uri" => $callback,
"client_id" => $this->getParameter("oauthClientid"),
"client_secret" => $this->getParameter("oauthClientsecret"),
];
$response=$this->apiservice->run("POST",$apiurl,$query,null,"form");
if(!$response||$response->code!="200") die("pb openid 01");
$accesstoken=$response->body->access_token;
$accesstokentype=$response->body->token_type;
$îdtoken=$response->body->id_token;
$request->getSession()->set("oauthAccesstoken",$accesstoken);
$request->getSession()->set("oauthIdtoken",$îdtoken);
$apiurl = $this->getParameter("oauthUserinfo");
$response=$this->apiservice->run("GET",$apiurl,null,["Authorization"=>$accesstokentype." ".$accesstoken]);
if(!$response||$response->code!="200") die("pb openid 02");
$attributes=json_decode(json_encode($response->body), true);
// Username
$username="";
if(isset($attributes[$this->getParameter('oauthUsername')]))
$username = $attributes[$this->getParameter('oauthUsername')];
// Valeur par défaut
$email = "$username@nomail.fr";
$lastname = $username;
$firstname = " ";
$avatar="noavatar.png";
// Récupérer les attributs associés
if(isset($attributes[$this->getParameter('oauthEmail')]))
$email = $attributes[$this->getParameter('oauthEmail')];
if(isset($attributes[$this->getParameter('oauthLastname')]))
$lastname = $attributes[$this->getParameter('oauthLastname')];
if(isset($attributes[$this->getParameter('oauthFirstname')]))
$firstname = $attributes[$this->getParameter('oauthFirstname')];
if(isset($attributes[$this->getParameter('oauthAvatar')]))
$avatar = $attributes[$this->getParameter('oauthAvatar')];
// Rechercher l'utilisateur
$user = $em->getRepository('App\Entity\User')->findOneBy(array("username"=>$username));
if (!$user) {
if(!$this->getParameter("oauthAutosubmit")) return $this->redirect($this->generateUrl('app_noperm'));
$this->submitSSONiveau01($attributes,$em);
$this->submitSSOGroup($attributes,$em);
$niveau01=$em->getRepository('App\Entity\Niveau01')->calculateSSONiveau01($attributes);
$user=$this->submituser($username,$firstname,$lastname,$email,$avatar,$niveau01,$em);
}
elseif($this->getParameter("oauthAutoupdate")) {
$this->submitSSONiveau01($attributes,$em);
$this->submitSSOGroup($attributes,$em);
$this->updateuser($user,$firstname,$lastname,$email,$avatar,$em);
$user=$em->getRepository('App\Entity\Group')->calculateSSOGroup($user,$attributes);
}
// Autoconnexion
return $this->autoconnexion($user,$redirect,$request);
}
public function logout(Request $request) {
$auth_mode=$this->getParameter("appAuth");
switch($auth_mode) {
case "SQL":
return $this->logoutSQL($request);
break;
case "CAS":
return $this->logoutCAS($request);
break;
case "LDAP":
return $this->logoutLDAP($request);
break;
case "OPENID":
return $this->logoutOPENID($request);
break;
}
}
public function logoutSQL(Request $request) {
$this->tokenstorage->setToken(null);
$request->getSession()->invalidate();
return $this->redirect($this->generateUrl("app_home"));
}
public function logoutCAS(Request $request) {
$this->tokenstorage->setToken(null);
$request->getSession()->invalidate();
// Init Client CAS
$alias=$this->getParameter('appAlias');
\phpCAS::setDebug($this->appKernel->getProjectDir()."/var/log/cas.log");
\phpCAS::client(CAS_VERSION_2_0, $this->getParameter('casHost'), intval($this->getParameter('casPort')), is_null($this->getParameter('casPath')) ? '' : $this->getParameter('casPath'), false);
\phpCAS::setNoCasServerValidation();
// Logout
$url=$this->generateUrl('app_home', array(), UrlGeneratorInterface::ABSOLUTE_URL);
\phpCAS::logout(array("service"=>$url));
return true;
}
public function logoutLDAP(Request $request) {
$this->tokenstorage->setToken(null);
$request->getSession()->invalidate();
return $this->redirect($this->generateUrl("app_home"));
}
public function logoutOPENID(Request $request) {
$accesstoken=$request->getSession()->get("oauthAccesstoken");
$idtoken=$request->getSession()->get("oauthIdtoken");
$state=$request->getSession()->get("oauthState");
$this->tokenstorage->setToken(null);
$request->getSession()->invalidate();
$url=$this->getParameter("oauthLogouturl");
if($url) {
$callback=($request->isSecure()?"https://":"http://").str_replace("//","/",$this->getParameter("appWeburl").$this->getParameter("appAlias").$this->generateUrl('app_home'));
$callback=substr($callback, 0, -1);
$url.="?id_token_hint=$idtoken&scope=openid&post_logout_redirect_uri=$callback";
return $this->redirect($url);
} else return $this->redirect($this->generateUrl("app_home"));
}
// Génération automatique des niveau01 provenant de l'attribut casniveau01
private function submitSSONiveau01($attributes,ManagerRegistry $em) {
$attrNiveau01=($this->getParameter("appAuth")=="CAS"?$this->getParameter('casNiveau01'):$this->getParameter('oauthNiveau01'));
if(!$attrNiveau01)
return null;
// Si l'utilisateur possège l'attribut niveau01 dans ses attributs
if(array_key_exists($attrNiveau01,$attributes)) {
if(!is_array($attributes[$attrNiveau01])) {
$attributes[$attrNiveau01]=[$attributes[$attrNiveau01]];
}
foreach($attributes[$attrNiveau01] as $ssoniveau01) {
$basedn=$this->getParameter('ldapBasedn');
$name=$ssoniveau01;
if($basedn!="") {
// Si présence du basedn dans le nom du groupe = nous sommes en présence d'un DN = on récupere donc comme nom que son cn
if(stripos($name,$basedn)!==false) {
$tbname=explode(",",$name);
$tbname=explode("=",$tbname[0]);
$name=$tbname[1];
}
}
// Recherche du groupe
$niveau01=$em->getRepository("App\Entity\Niveau01")->findOneBy(["label"=>$name]);
if(!$niveau01) {
$niveau01=new Niveau01();
$niveau01->setLabel($name);
$niveau01->setApikey(Uuid::uuid4());
}
$niveau01->setAttributes('{"'.$attrNiveau01.'":"'.$ssoniveau01.'"}');
$em->getManager()->persist($niveau01);
$em->getManager()->flush();
}
}
}
// Génération automatique des groupes provenant de l'attribut casgroup ou oauthgroup
private function submitSSOGroup($attributes,ManagerRegistry $em) {
$attrGroup=($this->getParameter("appAuth")=="CAS"?$this->getParameter('casGroup'):$this->getParameter('oauthGroup'));
if(!$attrGroup)
return null;
// Si l'utilisateur possège l'attribut groupe dans ses attributs
if(array_key_exists($attrGroup,$attributes)) {
if(!is_array($attributes[$attrGroup])) {
$attributes[$attrGroup]=[$attributes[$attrGroup]];
}
foreach($attributes[$attrGroup] as $ssogroup) {
$basedn=$this->getParameter('ldapBasedn');
$name=$ssogroup;
if($basedn!="") {
// Si présence du basedn dans le nom du groupe = nous sommes en présence d'un DN = on récupere donc comme nom que son cn
if(stripos($name,$basedn)!==false) {
$tbname=explode(",",$name);
$tbname=explode("=",$tbname[0]);
$name=$tbname[1];
}
}
// Recherche du groupe
$group=$em->getRepository("App\Entity\Group")->findOneBy(["label"=>$name]);
if(!$group) {
$group=new Group();
$group->setLabel($name);
$group->setIsopen(false);
$group->setIsworkgroup(false);
$group->setApikey(Uuid::uuid4());
}
$group->setAttributes('{"'.$attrGroup.'":"'.$ssogroup.'"}');
$em->getManager()->persist($group);
$em->getManager()->flush();
}
}
}
private function submituser($username,$firstname,$lastname,$email,$avatar,$niveau01,$em) {
if(empty($email)) $email = $username."@nomail.com";
if(empty($avatar)) $avatar = "noavatar.png";
if(empty($firstname)) $firstname = " ";
if(empty($lastname)) $lastname = $username;
$uuid=Uuid::uuid4();
$password=$this->getParameter("appAuth")."PWD-".$username."-".$uuid;
// Si aucun niveau01 on prend par défaut le niveau system
if(!$niveau01) $niveau01=$em->getRepository('App\Entity\Niveau01')->find(-1);
// Autogénération du user vu qu'il a pu se connecter
$user = new User();
$user->setUsername($username);
$user->setEmail($email);
$user->setLastname($lastname);
$user->setFirstname($firstname);
$user->setApikey(Uuid::uuid4());
$user->setPassword($password);
$user->setNiveau01($niveau01);
$user->setAvatar($avatar);
$user->setIsvisible(true);
$user->setRole("ROLE_USER");
if(in_array($username,$this->getParameter("appAdmins")))
$user->setRole("ROLE_ADMIN");
$em->getManager()->persist($user);
$em->getManager()->flush();
return $user;
}
private function updateuser($user,$firstname,$lastname,$email,$avatar,$em) {
if($avatar=="noavatar.png") $avatar=$user->getAvatar();
if(!empty($lastname)) $user->setLastname($lastname);
if(!empty($firstname)) $user->setFirstname($firstname);
if(!empty($email)) $user->setEmail($email);
if(!empty($avatar)) $user->setAvatar($avatar);
if(in_array($user->getUsername(),$this->getParameter("appAdmins")))
$user->setRole("ROLE_ADMIN");
$em->getManager()->flush();
}
private function autoconnexion($user,$redirect,Request $request)
{
// Récupérer le token de l'utilisateur
$token = new UsernamePasswordToken($user, "main", $user->getRoles());
$this->tokenstorage->setToken($token);
$request->getSession()->set('_security_main', serialize($token));
// Simuler l'evenement de connexion
$event = new InteractiveLoginEvent($request, $token);
$dispatcher = new EventDispatcher();
$dispatcher->dispatch($event);
// Redirection
if($redirect)
return $this->redirect($redirect);
else
return $this->redirect($this->generateUrl('app_home'));
}
}