Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
lib
unicaen
auth
Commits
f38c4ce0
Commit
f38c4ce0
authored
Jan 25, 2019
by
Bertrand Gauthier
Browse files
Merge branch 'local-auth'
parents
b5f31ecc
afb95057
Pipeline
#3392
failed with stages
in 2 minutes and 10 seconds
Changes
7
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
CHANGELOG.md
View file @
f38c4ce0
...
...
@@ -5,8 +5,15 @@
-
Authentification locale activable/désactivable dans la config.
-
Clé de config
`unicaen-auth`
>
`local`
>
`enabled`
.
-
F
onctionnalité "Mot de passe oublié" pour l'authentification locale.
-
Ajout de la f
onctionnalité "Mot de passe oublié" pour l'authentification locale.
-
Principe: un lien contenant un token est envoyé par mail à l'utilisateur.
-
NB: Le username de l'utilisateur doit être une adresse électronique.
-
NB: nécessité
d
de créer une nouvelle colonne dans la table des utilisateurs,
-
NB: nécessité de créer une nouvelle colonne dans la table des utilisateurs,
cf.
[
répertoire data
](
./data
)
.
## 1.3.1 - 25/01/2019
-
Fonctionnalité "Mot de passe oublié" :
-
Correction: l'utilisateur n'était pas recherché par son username!
-
Ajout d'un validateur sur le formulaire de saisie de l'adresse électronique.
-
Vérification que le compte utilisateur est bien local.
src/UnicaenAuth/Controller/AuthController.php
View file @
f38c4ce0
...
...
@@ -2,7 +2,7 @@
namespace
UnicaenAuth\Controller
;
use
Do
ctrine\ORM\NoResult
Exception
;
use
Do
main
Exception
;
use
UnicaenApp\Controller\Plugin\AppInfos
;
use
UnicaenApp\Controller\Plugin\Mail
;
use
UnicaenApp\Exception\RuntimeException
;
...
...
@@ -135,24 +135,42 @@ class AuthController extends AbstractActionController
$form
->
setData
(
$data
);
if
(
$form
->
isValid
())
{
$email
=
$data
[
'email'
];
$this
->
processPasswordResetRequest
(
$email
);
$view
->
setVariable
(
'email'
,
$email
);
$view
->
setTemplate
(
'unicaen-auth/auth/request-password-reset-success'
);
try
{
$this
->
processPasswordResetRequest
(
$email
);
$view
->
setVariable
(
'email'
,
$email
);
$view
->
setTemplate
(
'unicaen-auth/auth/request-password-reset-success'
);
}
catch
(
DomainException
$de
)
{
// affichage de l'erreur comme une erreur de validation
$form
->
get
(
'email'
)
->
setMessages
([
$de
->
getMessage
()]);
}
}
}
return
$view
;
}
/**
* @param string $email
*/
private
function
processPasswordResetRequest
(
$email
)
{
try
{
$token
=
$this
->
userService
->
updateUserPasswordResetToken
(
$email
);
}
catch
(
NoResultException
$nre
)
{
// aucun utilisateur trouvé tel que username = $email
// Recherche de l'utilisateur ayant pour *username* (login) l'email spécifié
$user
=
$this
->
userService
->
getUserMapper
()
->
findOneByUsername
(
$email
);
if
(
$user
===
null
)
{
// Aucun utilisateur trouvé ayant l'email spécifié :
// on ne fait rien mais on ne le signale pas sinon le formulaire permettrait
// de tester si des emails potentiellement valides existent dans la base.
return
;
}
if
(
!
$user
->
isLocal
())
{
// L'email spécifié appartient à un utilisateur non local : on signale l'impossibilité de changer le mdp.
throw
new
DomainException
(
"Le changement de mot de passe n'est pas possible pour cet utilisateur."
);
}
// génération/enregistrement d'un token
$token
=
$this
->
userService
->
updateUserPasswordResetToken
(
$user
);
// envoi du mail contenant le lien de changement de mdp
$app
=
$this
->
appInfos
()
->
getNom
();
...
...
src/UnicaenAuth/Entity/Db/AbstractUser.php
View file @
f38c4ce0
...
...
@@ -14,6 +14,9 @@ use Doctrine\ORM\Mapping as ORM;
*/
abstract
class
AbstractUser
implements
UserInterface
,
ProviderInterface
{
const
PASSWORD_LDAP
=
'ldap'
;
const
PASSWORD_SHIB
=
'shib'
;
/**
* @var int
* @ORM\Id
...
...
@@ -246,6 +249,22 @@ abstract class AbstractUser implements UserInterface, ProviderInterface
$this
->
roles
->
add
(
$role
);
}
/**
* Retourne true si cet utilisateur est local.
*
* Un utilisateur est local s'il ne résulte pas d'une authentification LDAP ou Shibboleth.
* Son mot de passe est chiffré dans la table des utilisateurs.
*
* @return bool
*/
public
function
isLocal
()
{
return
!
in_array
(
$this
->
getPassword
(),
[
AbstractUser
::
PASSWORD_LDAP
,
AbstractUser
::
PASSWORD_SHIB
,
]);
}
/**
*
* @return string
...
...
src/UnicaenAuth/Entity/Shibboleth/ShibUser.php
View file @
f38c4ce0
...
...
@@ -2,6 +2,7 @@
namespace
UnicaenAuth\Entity\Shibboleth
;
use
UnicaenAuth\Entity\Db\AbstractUser
;
use
ZfcUser\Entity\UserInterface
;
class
ShibUser
implements
UserInterface
...
...
@@ -200,7 +201,7 @@ class ShibUser implements UserInterface
*/
public
function
getPassword
()
{
return
'shib'
;
return
AbstractUser
::
PASSWORD_SHIB
;
}
/**
...
...
src/UnicaenAuth/Service/User.php
View file @
f38c4ce0
...
...
@@ -3,11 +3,11 @@
namespace
UnicaenAuth\Service
;
use
DateTime
;
use
Doctrine\ORM\NoResultException
;
use
Ramsey\Uuid\Uuid
;
use
UnicaenApp\Entity\Ldap\People
;
use
UnicaenApp\Exception\RuntimeException
;
use
UnicaenApp\Mapper\Ldap\People
as
LdapPeopleMapper
;
use
UnicaenAuth\Entity\Db\AbstractUser
;
use
UnicaenAuth\Entity\Shibboleth\ShibUser
;
use
UnicaenAuth\Event\UserAuthenticatedEvent
;
use
UnicaenAuth\Options\ModuleOptions
;
...
...
@@ -22,11 +22,11 @@ use Zend\Form\Form;
use
Zend\InputFilter\Input
;
use
Zend\ServiceManager\ServiceLocatorAwareInterface
;
use
Zend\ServiceManager\ServiceLocatorAwareTrait
;
use
Zend\Validator\EmailAddress
;
use
Zend\Validator\Identical
;
use
ZfcUser\Entity\UserInterface
;
use
ZfcUser\Options\AuthenticationOptionsInterface
;
use
ZfcUser\Options\ModuleOptions
as
ZfcUserModuleOptions
;
use
UnicaenAuth\Entity\Db\AbstractUser
;
/**
* Service traitant des utilisateurs locaux de l'application.
...
...
@@ -81,13 +81,13 @@ class User implements ServiceLocatorAwareInterface, EventManagerAwareInterface
case
$userData
instanceof
People
:
$username
=
$userData
->
getData
(
$this
->
getOptions
()
->
getLdapUsername
());
$email
=
$userData
->
getMail
();
$password
=
'ldap'
;
$password
=
AbstractUser
::
PASSWORD_LDAP
;
$state
=
in_array
(
'deactivated'
,
ldap_explode_dn
(
$userData
->
getDn
(),
1
))
?
0
:
1
;
break
;
case
$userData
instanceof
ShibUser
:
$username
=
$userData
->
getUsername
();
$email
=
$userData
->
getEmail
();
$password
=
'shib'
;
$password
=
AbstractUser
::
PASSWORD_SHIB
;
$state
=
1
;
break
;
default
:
...
...
@@ -260,7 +260,11 @@ class User implements ServiceLocatorAwareInterface, EventManagerAwareInterface
$form
->
add
((
new
Text
(
'email'
))
->
setLabel
(
"Adresse électronique :"
));
$form
->
add
((
new
Csrf
(
'csrf'
)));
$form
->
add
((
new
Submit
(
'submit'
))
->
setLabel
(
"Envoyer le lien"
));
$form
->
getInputFilter
()
->
add
((
new
Input
(
'email'
))
->
setRequired
(
true
));
$emailInput
=
new
Input
(
'email'
);
$emailInput
->
setRequired
(
true
);
$emailInput
->
getValidatorChain
()
->
attach
(
new
EmailAddress
());
$form
->
getInputFilter
()
->
add
(
$emailInput
);
return
$form
;
}
...
...
@@ -287,22 +291,13 @@ class User implements ServiceLocatorAwareInterface, EventManagerAwareInterface
}
/**
* Si l'utilisateur dont le username égale l'email spécifié est trouvé,
* génère puis enregistre le token permettant d'autoriser cet utilisateur à changer son mot de passe.
* Génère puis enregistre le token permettant d'autoriser un utilisateur à changer son mot de passe.
*
* @param str
ing $email Email de l'utilisateur qui doit être aussi son username
* @param
Ab
str
actUser $user Utilisateur concerné
* @return string|null Token généré
* @throws NoResultException Aucun utilisateur trouvé avec cet email
*/
public
function
updateUserPasswordResetToken
(
$email
)
public
function
updateUserPasswordResetToken
(
AbstractUser
$user
)
{
// Si l'email est inconnu, on ne fera rien mais on ne le signale pas sinon le formulaire permettrait
// de tester si des emails potentiellement valides existent dans la base.
$user
=
$this
->
getUserMapper
()
->
findByEmail
(
$email
);
/** @var User $user */
if
(
$user
===
null
)
{
throw
new
NoResultException
();
}
// Génération du token.
$token
=
$this
->
generatePasswordResetToken
();
...
...
@@ -344,8 +339,14 @@ class User implements ServiceLocatorAwareInterface, EventManagerAwareInterface
*/
public
function
generatePasswordResetToken
()
{
try
{
$uuid
=
Uuid
::
uuid4
();
}
catch
(
\
Exception
$e
)
{
throw
new
RuntimeException
(
"Erreur rencontrée lors de la génération du UUID."
,
null
,
$e
);
}
// NB: la date de fin de vie du token est concaténée à la fin.
$token
=
Uuid
::
uuid
4
()
->
toString
()
.
self
::
PASSWORD_RESET_TOKEN_SEP
.
date
(
'YmdHis'
,
time
()
+
3600
*
24
);
$token
=
$
uuid
->
toString
()
.
self
::
PASSWORD_RESET_TOKEN_SEP
.
date
(
'YmdHis'
,
time
()
+
3600
*
24
);
// durée de vie = 24h
return
$token
;
...
...
src/UnicaenAuth/Service/UserMapper.php
View file @
f38c4ce0
...
...
@@ -2,18 +2,32 @@
namespace
UnicaenAuth\Service
;
use
UnicaenAuth\Entity\Db\User
;
use
UnicaenAuth\Entity\Db\
Abstract
User
;
use
ZfcUserDoctrineORM\Mapper\User
as
ZfcUserDoctrineORMUserMapper
;
class
UserMapper
extends
ZfcUserDoctrineORMUserMapper
{
/**
* Recherche un utilisateur par son username (identifiant de connexion).
*
* @param string $username
* @return AbstractUser|null
*/
public
function
findOneByUsername
(
$username
)
{
/** @var AbstractUser $user */
$user
=
$this
->
em
->
getRepository
(
$this
->
options
->
getUserEntityClass
())
->
findOneBy
([
'username'
=>
$username
]);
return
$user
;
}
/**
* @param string $token
* @return User
* @return
Abstract
User
*/
public
function
findOneByPasswordResetToken
(
$token
)
{
/** @var User $user */
/** @var
Abstract
User $user */
$user
=
$this
->
em
->
getRepository
(
$this
->
options
->
getUserEntityClass
())
->
findOneBy
([
'passwordResetToken'
=>
$token
]);
return
$user
;
...
...
view/unicaen-auth/auth/request-password-reset-form.phtml
View file @
f38c4ce0
...
...
@@ -15,8 +15,8 @@ use Zend\Form\Form;
</h2>
<p
class=
"lead"
>
Un lien permettant d
e change
r votre
mot de passe
vous sera envoyé à l'adresse que vous renseignerez ci-dessous
.
<br>
<strong>
NB:
</strong>
Ce
tte adresse doit correspondre au compt
e que
v
ous utilis
ez pour vous connecter à l'application.
Cette page permet d'initier l
e change
ment du
mot de passe
associé à votre compte local de connexion à l'application
.
<br>
<strong>
NB:
</strong>
Ce
la n'est possibl
e que
p
ou
r le
s utilis
ateurs se connectant avec leur adresse électronique.
<br>
</p>
<div
class=
"col-sm-4"
>
...
...
@@ -30,6 +30,7 @@ use Zend\Form\Form;
echo
$this
->
formInput
(
$email
);
echo
$this
->
formElementErrors
(
$email
,
[
'class'
=>
'text-danger'
]);
?>
<span
class=
"help-block"
>
Un lien à cliquer vous sera envoyé à cette adresse électronique.
</span>
</p>
<?php
echo
$this
->
formInput
(
$form
->
get
(
'csrf'
));
?>
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment