integration hydra apps
This commit is contained in:
parent
21fb28a6f0
commit
c3328a1ba0
8
.env
8
.env
|
@ -118,7 +118,7 @@ SONDE_URL=
|
|||
# Mercure
|
||||
MERCURE_URL=https://127.0.0.1/.well-known/mercure
|
||||
MERCURE_PUBLIC_URL=https://127.0.0.1/.well-known/mercure
|
||||
MERCURE_JWT_SECRET="!ChangeMe!"
|
||||
MERCURE_JWT_SECRET="!changeme!changeme!changeme!changeme!changeme!changeme!"
|
||||
|
||||
# Minio
|
||||
MINIO_URL=http://127.0.0.1:9000
|
||||
|
@ -129,6 +129,12 @@ MINIO_ROOT=
|
|||
MINIO_PATH_STYLE=1
|
||||
MINIO_SECURE=0
|
||||
|
||||
# Hydra apps
|
||||
HYDRA_LOGINCHALLENGE="http://127.0.0.1:4445/oauth2/auth/requests/login?login_challenge="
|
||||
HYDRA_LOGINCHALLENGEACCEPT="http://127.0.0.1:4445/oauth2/auth/requests/login/accept?login_challenge="
|
||||
HYDRA_CONSENTCHALLENGE="http://127.0.0.1:4445/oauth2/auth/requests/consent?consent_challenge="
|
||||
HYDRA_CONSENTCHALLENGEACCEPT="http://127.0.0.1:4445/oauth2/auth/requests/consent/accept?consent_challenge="
|
||||
|
||||
# Lock
|
||||
LOCK_DSN="postgresql://symfony:ChangeMe@127.0.0.1:5432/app?serverVersion=13&charset=utf8"
|
||||
|
||||
|
|
|
@ -185,6 +185,10 @@ app_user_minio_document:
|
|||
controller: App\Controller\MinioController::document
|
||||
|
||||
#-- Access public
|
||||
app_minio_logo:
|
||||
path: /minio/logo
|
||||
controller: App\Controller\MinioController::logo
|
||||
|
||||
app_minio_image:
|
||||
path: /minio/image
|
||||
controller: App\Controller\MinioController::image
|
||||
|
@ -193,6 +197,28 @@ app_minio_document:
|
|||
path: /minio/document
|
||||
controller: App\Controller\MinioController::document
|
||||
|
||||
#== Hydra =======================================================================================================
|
||||
|
||||
app_hydra_loginsql:
|
||||
path: /hydra/loginsql
|
||||
controller: App\Controller\HydraController::loginsql
|
||||
|
||||
app_hydra_checkloginsql:
|
||||
path: /hydra/checkloginsql
|
||||
controller: App\Controller\HydraController::checkloginsql
|
||||
|
||||
app_hydra_loginldap:
|
||||
path: /hydra/loginldap
|
||||
controller: App\Controller\HydraController::loginldap
|
||||
|
||||
app_hydra_checkloginldap:
|
||||
path: /hydra/checkloginldap
|
||||
controller: App\Controller\HydraController::checkloginldap
|
||||
|
||||
app_hydra_consent:
|
||||
path: /hydra/consent
|
||||
controller: App\Controller\HydraController::consent
|
||||
|
||||
#== Ckeditor ====================================================================================================
|
||||
app_ckeditor_upload:
|
||||
path: /user/upload
|
||||
|
|
|
@ -100,6 +100,11 @@ parameters:
|
|||
minioPathstyle: '%env(resolve:MINIO_PATH_STYLE)%'
|
||||
minioSecure: '%env(resolve:MINIO_SECURE)%'
|
||||
|
||||
hydraLoginchallenge: '%env(resolve:HYDRA_LOGINCHALLENGE)%'
|
||||
hydraLoginchallengeaccept: '%env(resolve:HYDRA_LOGINCHALLENGEACCEPT)%'
|
||||
hydraConsentchallenge: '%env(resolve:HYDRA_CONSENTCHALLENGE)%'
|
||||
hydraConsentchallengeaccept: '%env(resolve:HYDRA_CONSENTCHALLENGEACCEPT)%'
|
||||
|
||||
sondeUse: '%env(resolve:SONDE_USE)%'
|
||||
sondeUrl: '%env(resolve:SONDE_URL)%'
|
||||
|
||||
|
|
|
@ -19,5 +19,44 @@ hydra:
|
|||
email_verified:
|
||||
- consent.session.id_token.email_verified
|
||||
|
||||
- id: ninesql
|
||||
title:
|
||||
fr: NINE SQL
|
||||
en: NINE SQL
|
||||
description:
|
||||
fr: Authentification via NINESQL
|
||||
en: Authentication by NINESQL
|
||||
icon_url: https://127.0.0.1:8000/minio/logo
|
||||
login_url: http://127.0.0.1:8000/hydra/loginsql
|
||||
consent_url: http://127.0.0.1:8000/hydra/consent
|
||||
logout_url: http://127.0.0.1:8000/hydra/logoutsql
|
||||
attributes_rewrite_rules:
|
||||
username:
|
||||
- consent.session.id_token.username
|
||||
email:
|
||||
- consent.session.id_token.email
|
||||
firstname:
|
||||
- consent.session.id_token.firstname
|
||||
lastname:
|
||||
- consent.session.id_token.lastname
|
||||
|
||||
|
||||
- id: nineldap
|
||||
title:
|
||||
fr: NINE LDAP
|
||||
en: NINE LDAP
|
||||
description:
|
||||
fr: Authentification via NINELDAP
|
||||
en: Authentication by NINELDAP
|
||||
icon_url: https://127.0.0.1:8000/minio/logo
|
||||
login_url: http://127.0.0.1:8000/hydra/loginldap
|
||||
consent_url: http://127.0.0.1:8000/hydra/consent
|
||||
logout_url: http://127.0.0.1:8000/hydra/logoutldap
|
||||
attributes_rewrite_rules:
|
||||
username:
|
||||
- consent.session.id_token.username
|
||||
email:
|
||||
- consent.session.id_token.email
|
||||
firstname:
|
||||
- consent.session.id_token.firstname
|
||||
lastname:
|
||||
- consent.session.id_token.lastname
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
body > section {
|
||||
background-color: rgba(214, 170, 214, 0.575);
|
||||
|
||||
}
|
||||
|
||||
input[type="radio"]:checked ~ .app-item {
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
"response_types": [
|
||||
"code"
|
||||
],
|
||||
"logo_uri": "https://upload.wikimedia.org/wikipedia/commons/e/e1/Password.svg",
|
||||
"logo_uri": "https://127.0.0.1:8000/minio/logo",
|
||||
"scope": "openid"
|
||||
}
|
|
@ -49,8 +49,8 @@ services:
|
|||
- "80"
|
||||
environment:
|
||||
SERVER_NAME: ':80'
|
||||
MERCURE_PUBLISHER_JWT_KEY: '!ChangeMe!'
|
||||
MERCURE_SUBSCRIBER_JWT_KEY: '!ChangeMe!'
|
||||
MERCURE_PUBLISHER_JWT_KEY: '!changeme!changeme!changeme!changeme!changeme!changeme!'
|
||||
MERCURE_SUBSCRIBER_JWT_KEY: '!changeme!changeme!changeme!changeme!changeme!changeme!'
|
||||
MERCURE_EXTRA_DIRECTIVES: |
|
||||
cors_origins https://127.0.0.1:8000
|
||||
# Comment the following line to disable the development mode
|
||||
|
@ -157,6 +157,7 @@ services:
|
|||
- ./containers/hydra/clients.d:/etc/hydra/clients.d
|
||||
ports:
|
||||
- 7080:4444
|
||||
- 4445:4445
|
||||
links:
|
||||
- postgresql
|
||||
depends_on:
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
use App\Service\ApiService;
|
||||
use App\Service\PasswordEncoder;
|
||||
use App\Service\LdapService;
|
||||
|
||||
use App\Form\LoginType;
|
||||
|
||||
|
||||
class HydraController extends AbstractController
|
||||
{
|
||||
|
||||
private $apiservice;
|
||||
private $passwordencoder;
|
||||
private $ldapservice;
|
||||
|
||||
public function __construct(ApiService $apiservice,LdapService $ldapservice,PasswordEncoder $passwordencoder)
|
||||
{
|
||||
$this->apiservice = $apiservice;
|
||||
$this->passwordencoder = $passwordencoder;
|
||||
$this->ldapservice = $ldapservice;
|
||||
}
|
||||
|
||||
public function loginsql(Request $request): Response
|
||||
{
|
||||
|
||||
$challenge = $request->query->get('login_challenge');
|
||||
|
||||
// S'il n'y a pas de challenge, on déclenche une bad request
|
||||
if (!$challenge) {
|
||||
throw new BadRequestException('pas de challenge');
|
||||
}
|
||||
|
||||
// On vérifie que la requête d'identification provient bien de hydra
|
||||
$response = $this->apiservice->run("GET",$this->getParameter('hydraLoginchallenge').$challenge,null);
|
||||
if(!$response)
|
||||
throw new BadRequestException('challenge invalide');
|
||||
|
||||
// si le challenge est validé par hydra, on le stocke en session pour l'utiliser par la suite et on redirige vers une route interne protégée qui va déclencher l'identification FranceConnect
|
||||
$request->getSession()->set('hydraChallenge', $challenge);
|
||||
|
||||
// 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/loginHYDRA.html.twig", [
|
||||
"useheader"=>false,
|
||||
"usemenu"=>false,
|
||||
"usesidebar"=>false,
|
||||
"form"=>$form->createView(),
|
||||
"mode"=>"SQL",
|
||||
]);
|
||||
}
|
||||
|
||||
public function checkloginsql(Request $request,ManagerRegistry $em) {
|
||||
$username=$request->get('login')["username"];
|
||||
$password=$request->get('login')["password"];
|
||||
|
||||
// user exist ?
|
||||
$user=$em->getRepository("App\Entity\User")->findOneBy(["username"=>$username]);
|
||||
if(!$user) return $this->redirect($this->generateUrl('app_hydra_loginsql',["login_challenge"=>$request->getSession()->get("hydraChallenge")]));
|
||||
|
||||
$islogin=$this->passwordencoder->verify($user->getPassword(),$password,$user->getSalt());
|
||||
if(!$islogin) return $this->redirect($this->generateUrl('app_hydra_loginsql',["login_challenge"=>$request->getSession()->get("hydraChallenge")]));
|
||||
|
||||
$response = $this->apiservice->run("PUT",$this->getParameter('hydraLoginchallengeaccept').$request->getSession()->get('hydraChallenge'),["subject"=>$user->getEmail(),"acr"=>"string"]);
|
||||
if(!$response||$response->code!="200")
|
||||
throw new BadRequestException('login accept invalide');
|
||||
|
||||
$datas=[
|
||||
"username"=>$user->getUsername(),
|
||||
"email"=>$user->getEmail(),
|
||||
"firstname"=>$user->getFirstname(),
|
||||
"lastname"=>$user->getLastname()
|
||||
];
|
||||
$request->getSession()->set("datas",$datas);
|
||||
|
||||
$redirect=$response->body->redirect_to;
|
||||
return $this->redirect($redirect, 301);
|
||||
|
||||
}
|
||||
|
||||
public function loginldap(Request $request): Response
|
||||
{
|
||||
|
||||
$challenge = $request->query->get('login_challenge');
|
||||
|
||||
// S'il n'y a pas de challenge, on déclenche une bad request
|
||||
if (!$challenge) {
|
||||
throw new BadRequestException('pas de challenge');
|
||||
}
|
||||
|
||||
// On vérifie que la requête d'identification provient bien de hydra
|
||||
$response = $this->apiservice->run("GET",$this->getParameter('hydraLoginchallenge').$challenge,null);
|
||||
if(!$response)
|
||||
throw new BadRequestException('challenge invalide');
|
||||
|
||||
// si le challenge est validé par hydra, on le stocke en session pour l'utiliser par la suite et on redirige vers une route interne protégée qui va déclencher l'identification FranceConnect
|
||||
$request->getSession()->set('hydraChallenge', $challenge);
|
||||
|
||||
// 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/loginHYDRA.html.twig", [
|
||||
"useheader"=>false,
|
||||
"usemenu"=>false,
|
||||
"usesidebar"=>false,
|
||||
"form"=>$form->createView(),
|
||||
"mode"=>"LDAP",
|
||||
]);
|
||||
}
|
||||
|
||||
public function checkloginldap(Request $request,ManagerRegistry $em) {
|
||||
$username=$request->get('login')["username"];
|
||||
$password=$request->get('login')["password"];
|
||||
|
||||
// L'utilisateur se co à l'annuaire ?
|
||||
$userldap=$this->ldapservice->userconnect($username,$password);
|
||||
if(!$userldap)
|
||||
return $this->redirect($this->generateUrl('app_hydra_loginldap',["login_challenge"=>$request->getSession()->get("hydraChallenge")]));
|
||||
|
||||
$userldap=$userldap[0];
|
||||
|
||||
// Init
|
||||
$email = "$username@nomail.fr";
|
||||
$lastname = $username;
|
||||
$firstname = " ";
|
||||
|
||||
// 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')];
|
||||
|
||||
$response = $this->apiservice->run("PUT",$this->getParameter('hydraLoginchallengeaccept').$request->getSession()->get('hydraChallenge'),["subject"=>$email,"acr"=>"string"]);
|
||||
if(!$response||$response->code!="200")
|
||||
throw new BadRequestException('login accept invalide');
|
||||
|
||||
$datas=[
|
||||
"username"=>$username,
|
||||
"email"=>$email,
|
||||
"firstname"=>$firstname,
|
||||
"lastname"=>$lastname
|
||||
];
|
||||
$request->getSession()->set("datas",$datas);
|
||||
|
||||
$redirect=$response->body->redirect_to;
|
||||
return $this->redirect($redirect, 301);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function consent(Request $request)
|
||||
{
|
||||
$challenge = $request->query->get('consent_challenge');
|
||||
if (!$challenge) {
|
||||
throw new BadRequestException("Le challenge n'est pas disponible");
|
||||
}
|
||||
|
||||
// On vérifie que la requête d'identification provient bien de hydra
|
||||
$response = $this->apiservice->run("GET",$this->getParameter('hydraConsentchallenge').$challenge,null);
|
||||
if(!$response)
|
||||
throw new BadRequestException('challenge invalide');
|
||||
|
||||
$response = $this->apiservice->run("PUT",$this->getParameter('hydraConsentchallengeaccept').$challenge,[
|
||||
'grant_scope' => ['openid', 'offline_access'],
|
||||
'session' => ['id_token' => $request->getSession()->get('datas')]
|
||||
]);
|
||||
|
||||
if(!$response)
|
||||
throw new BadRequestException('challenge not accept');
|
||||
|
||||
$redirect=$response->body->redirect_to;
|
||||
return $this->redirect($redirect, 301);
|
||||
}
|
||||
|
||||
}
|
|
@ -47,6 +47,11 @@ class MinioController extends AbstractController
|
|||
return new Response(json_encode($output));
|
||||
}
|
||||
|
||||
public function logo(Request $request): Response {
|
||||
|
||||
return $this->redirectToRoute("app_minio_image",["file"=>"uploads/logo/".$request->getSession()->get("logolight")]);
|
||||
}
|
||||
|
||||
public function image(Request $request): Response
|
||||
{
|
||||
$file=$request->query->get("file");
|
||||
|
|
|
@ -365,7 +365,7 @@ class SecurityController extends AbstractController
|
|||
$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&state=$state&post_logout_redirect_uri=$callback";
|
||||
$url.="?id_token_hint=$idtoken&scope=openid&post_logout_redirect_uri=$callback";
|
||||
return $this->redirect($url);
|
||||
|
||||
} else return $this->redirect($this->generateUrl("app_home"));
|
||||
|
|
|
@ -75,6 +75,15 @@ class ApiService
|
|||
}
|
||||
break;
|
||||
|
||||
case "PUT":
|
||||
try{
|
||||
$response = \Unirest\Request::put($url,$header,$query);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case "DELETE":
|
||||
try{
|
||||
$response = \Unirest\Request::delete($url,$header,$query);
|
||||
|
|
|
@ -25,7 +25,6 @@ class PasswordEncoder implements LegacyPasswordHasherInterface
|
|||
return false;
|
||||
}
|
||||
|
||||
var_dump($salt);
|
||||
return $this->hash($plainPassword,$salt) === $hashedPassword;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
{% extends "base.html.twig" %}
|
||||
|
||||
{% block body %}
|
||||
<div style="text-align:center">
|
||||
<img src="{{ path('app_minio_image',{file:"uploads/logo/"~app.session.get("logolight")}) }}" style="height:120px;margin-top:10px;margin-bottom:20px;">
|
||||
<h1 style="border:none">{{app.session.get('appname')}}</h1>
|
||||
{% if mode=="SQL" %}
|
||||
{% set route="app_hydra_checkloginsql" %}
|
||||
{% else %}
|
||||
{% set route="app_hydra_checkloginldap" %}
|
||||
{% endif %}
|
||||
|
||||
{{ form_start(form, {'action': path(route), 'method': 'POST'}) }}
|
||||
<div class="card homecard mb-3" style="width:400px; margin:auto; text-align: left;">
|
||||
<div class="card-body">
|
||||
{{ form_row(form.username) }}
|
||||
{{ form_row(form.password) }}
|
||||
{{ form_row(form.submit) }}
|
||||
</div>
|
||||
</div>
|
||||
{% if mode == "SQL"%}
|
||||
<a href="{{path("app_resetpwd01")}}" class="mt-3">Mot de passe oublié ?</a>
|
||||
{% endif %}
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block localscript %}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#login_username").focus();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue