SlideShare a Scribd company logo
1 of 51
Sécurisation de vos applications web
à l’aide du composant Security de Symfony
25 sept 2018
https://vria.eu
contact@vria.eu
https://twitter.com/RiaVlad
RIABCHENKO Vladyslav
5+ ans full stack web-développeur
Certifié Symfony
Architecte technique à Webnet
Symfony 3
1. Concepts de sécurité
2. Authentification artisanale
3. Firewall
4. Token anonyme
5. User provider
6. Authentication provider
7. HTTP Basic
8. Formulaire de connexion
9. Autorisation autour des rôles
Plan
Symfony 4
Authentification est un processus permettant à l’application de s’assurer que la requête
a été faite par un utilisateur légitime.
C’est une confirmation de son identité grâce à des identifiants.
Identification est une sélection d’utilisateur grâce à son identifiant.
Autorisation est une vérification des droits d’accès d’un utilisateur sur une ressource en
se basant sur une politique d’accès.
Auth simple 5
Authentifier chaque requête à l’application à l’aide d’un identifiant et d’un
mot de passe.Tâche 1
Front controller
Token
public/index.php reçoit toutes les requêtes client quelque soit le
path et les paramètres
HttpFoundation
Composant de Symfony qui fournit la couche orientée-objet pour
HTTP : Request, Response, Session, etc.
Conserve des données sur l’utilisateur :
• Objet d’utilisateur
• Username
• Credentials
• Roles
• Authentifié ou pas
SymfonyComponentSecurityCoreAuthenticationToken
6
Security listeners
Token Conserve des données sur l’utilisateur
+ getUser()
+ getUsername()
+ getCredentials()
+ isAuthenticated()
+ getRoles()
TokenInterface
+ getProviderKey()
UsernamePasswordToken
+ getSecret()
AnonymousToken
Listeners qui extraient les identifiants et les vérifient.
Ils créent ensuite un Token puis le stockent dans le Token storage.
Token storage Objet/service qui contient un Token
Auth simple
7Auth simple
// public/index.php
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage;
use SymfonyComponentHttpFoundationResponse;
$request = Request::createFromGlobals(); // HTTP request
$tokenStorage = new TokenStorage(); // Service that stores user token
// Call security listener on every request.
$securityListener = new AppSecuritySecurityListener($tokenStorage);
$securityListener->onRequest($request);
// Any code you can imagine to generate a response.
// You can deny access if no token were set.
$token = $tokenStorage->getToken();
$response = new Response(
'Request uri: '.$request->getRequestUri().'<br>'
.'Token: '.(is_object($token) ? get_class($token) : gettype($token)).'<br>'
.'Username: '.($token ? $token->getUsername(): 'NULL')
);
$response->send(); // Send response
8Auth simple
namespace AppSecurity;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken;
class SecurityListener
{
/** @var TokenStorageInterface */
private $tokenStorage;
public function onRequest(Request $request)
{
$user = $request->query->get('auth_user');
$password = $request->query->get('auth_pw');
if ($user === 'gordon' && $password === 'freeman') {
// Credentials are valid.
// Create a token with user object, credentials, provider key and roles
$token = new UsernamePasswordToken($user, $password, 'main', ['ROLE_USER']);
// Save it to token storage
$this->tokenStorage->setToken($token);
}
}
}
Firewall 9
Centraliser l’authentification dans un firewall afin de pouvoir utiliser
plusieurs systèmes d’authentification.Tâche 2
HttpKernel
Le composant de Symfony qui fournit un processus structuré pour
convertir Request en Response en utilisant EventDispatcher.
EventDispatcher
Le composant de Symfony qui permet aux composants de
communiquer entre eux à l’aide d’événements.
Request ResponseExecute controller
EXCEPTIONEvent Dispatcher
10Firewall
Le Front controller crée $kernel et lui demande de traiter la requête.
// public/index.php
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelHttpKernel;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage;
$request = Request::createFromGlobals(); // HTTP request.
$tokenStorage = new TokenStorage(); // Service that stores user token.
$dispatcher = new EventDispatcher();
// Controller creates a response to send to the user.
$controller = new AppController($request, $tokenStorage);
$controllerResolver = new AppControllerResolver([$controller, 'defaultAction']);
// Kernel is in charge of converting a Request into a Response by using the event dispatcher.
$kernel = new HttpKernel($dispatcher, $controllerResolver);
// We will add security listeners to dispatcher in few minutes.
$response = $kernel->handle($request); // Launch kernel and retrieve response.
$response->send(); // Send response.
11
Kernel demande à ControllerResolver de renvoyer le contrôleur en fonction de la
requête. C’est l’emplacement idéal pour la logique de Routing.
Firewall
namespace App;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelControllerControllerResolverInterface;
class ControllerResolver implements ControllerResolverInterface
{
/** @var callable */
private $default;
public function __construct(callable $default)
{
$this->default = $default;
}
public function getController(Request $request)
{
return $this->default;
}
}
12
La méthode Controller::defaultAction est un contrôleur qui sera exécuté par Kernel.
Firewall
namespace App;
class Controller
{
/** @var Request */
private $request;
/** @var TokenStorageInterface */
private $tokenStorage;
public function defaultAction()
{
$token = $this->tokenStorage->getToken();
return new Response(
'Request uri: '.$this->request->getRequestUri().'<br>'
.'Token: '.(is_object($token) ? get_class($token) : gettype($token)).'<br>'
.'Username: '.($token ? $token->getUsername(): 'NULL')
);
}
}
SymfonyComponentSecurityHttp
13
- map: array
+ getListeners(Request $request)
Firewall
- map: FirewallMap
+ onKernelRequest(GetResponseEvent $event)
FirewallMap
RequestMatcher
- path: string
=>
][
Le firewall est un listener de l’événement
REQUEST.
Il permet d’implémenter des stratégies
d’authentification en fonction de la
requête.
FirewallMap renvoie les listeners
configurés pour le requête spécifique.
ListenerInterface
+ handle(GetResponseEvent $event) , …
Firewall
14
RequestMatcher
- path = ^/lambda
- host = half-life.com
=>
][ BasicAuthenticationListener
Utiliser l’authentification HTTP basic pour toutes les requêtes qui commencent par
/lambda sur le serveur half-life.com :
Firewall
# config/packages/security.yaml
security:
firewalls:
half_life:
pattern: ^/lambda
host: half-life.com
http_basic:
realm: "Lambda Complex"
15
RequestMatcher
- path: ^/customer
=>
][ ContextListener
,
SimpleFormAuthenticationListener
Authentifier les requêtes qui commencent par /customer à l’aide d’un formulaire classique
Firewall
# config/packages/security.yaml
security:
firewalls:
half_life:
# ...
customer:
pattern: ^/customer
form_login:
check_path: /login_check
login_path: /login
16
RequestMatcher =>
][AnonymousAuthenticationListener
Authentifier toutes les autres requêtes comme anonymes
Firewall
# config/packages/security.yaml
security:
firewalls:
half_life:
# ...
customer:
# ...
public:
anonymous: true
17
Firewall attends l’événement REQUEST pour exécuter MainSecurityListener si le path de
la requête commence par /main.
Firewall
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewall;
// ...
// Create main security listener that handles authentication.
$securityListener = new AppSecurityMainSecurityListener($tokenStorage);
// Create firewall map and add main security listener under URLs starting with "/main".
$firewallMap = new FirewallMap();
$firewallMap->add(new RequestMatcher('^/main'), [$securityListener]);
// Create firewall and add it to dispatcher.
$firewall = new Firewall($firewallMap, $dispatcher);
$dispatcher->addSubscriber($firewall);
// ...
18
MainSecurityListener implémente désormais ListenerInterface.
Firewall
namespace AppSecurity;
use SymfonyComponentHttpKernelEventGetResponseEvent;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken;
use SymfonyComponentSecurityHttpFirewallListenerInterface;
class MainSecurityListener implements ListenerInterface
{
/** @var TokenStorageInterface */
private $tokenStorage;
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
$user = $request->query->get('auth_user');
$password = $request->query->get('auth_pw');
if ($user === 'gordon' && $password === 'freeman') {
$token = new UsernamePasswordToken($user, $password, 'main', ['ROLE_USER']);
$this->tokenStorage->setToken($token);
}
}
}
App
SymfonyComponentSecurityHttpFirewall
anon. 19
Permettre aux utilisateurs de s’authentifier comme des anonymes.Tâche 3
RequestMatcher
- path = ^/main =>
][
MainSecurityListener
AnonymousAuthenticationListener
# config/packages/security.yaml
security:
firewalls:
main:
# ...
anonymous: true
anon. 20
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewallAnonymousAuthenticationListener;
// ...
// Create a security listener that adds anonymous token if none is already present.
$anonListener = new AnonymousAuthenticationListener($tokenStorage, 'secret');
// Create firewall map and add main security listener under URLs starting with "/main".
$firewallMap = new FirewallMap();
$firewallMap->add(new RequestMatcher('^/main'), [$securityListener, $anonListener]);
// ...
Plusieurs security listeners peuvent s'enchaîner :
User provider 21
Abstraire le moyen de récupération des utilisateurs et déplacer cette logique
en dehors des security listeners.Tâche 4
SymfonyComponentSecurityCoreUser
UserProviderInterface
+ loadUserByUsername($username): UserInterface
+ refreshUser(UserInterface $user)
+ supportsClass($class)
Security Listener
- userProvider
+ loadUserByUsername($username):User
UserInterface
+ getUsername()
+ getRoles()
+ getPassword()
+ getSalt()
+ eraseCredentials()
+ isEnabled()
UserInMemoryUserProvider
22User provider
use SymfonyComponentHttpKernelEventGetResponseEvent;
use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken;
use SymfonyComponentSecurityCoreExceptionUsernameNotFoundException;
use SymfonyComponentSecurityCoreUserUserProviderInterface;
use SymfonyComponentSecurityHttpFirewallListenerInterface;
class MainSecurityListener implements ListenerInterface
{
/** @var UserProviderInterface */
private $userProvider;
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
$username = $request->query->get('auth_user');
$password = $request->query->get('auth_pw');
try {
$user = $this->userProvider->loadUserByUsername($username);
if ($user->getPassword() === $password) {
$token = new UsernamePasswordToken($user, $password, 'main', $user->getRoles());
$this->tokenStorage->setToken($token);
}
} catch (UsernameNotFoundException $e) { }
}
}
23User provider
Création d’un user provider pour main security listener.
// public/index.php
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewall;
use SymfonyComponentSecurityCoreUserInMemoryUserProvider;
// ...
// Create user provider that will be used by authentication listener.
$mainUserProvider = new InMemoryUserProvider([
'gordon' => ['password' => 'freeman', 'roles' => ['ROLE_USER']],
]);
// Create main security listener that handles authentication.
$mainSecurityListener = new AppSecurityMainSecurityListener($tokenStorage, $mainUserProvider);
// Create firewall map and add main security listener under URLs starting with "/main".
$firewallMap = new FirewallMap();
$firewallMap->add(new RequestMatcher('^/main'), [$mainSecurityListener, $anonListener]);
// ...
24User provider
# config/packages/security.yaml
security:
providers:
hl_characters:
memory:
users:
gordon:
password: freeman
roles: 'ROLE_USER'
g-man:
password: bureaucrat
roles: 'ROLE_EMPLOYER'
App
25Auth provider
Ajouter l’encodage du mot de passe, n’accepter que des utilisateurs activés.
Déplacer la logique d’authentification en dehors des security listeners.Tâche 5
- tokenStorage
- authenticationManager
SymfonyComponentSecurityCoreAuthentication
AuthenticationManagerInterface
+ authenticate(TokenInterface $token)
MainSecurityListener
̶ Être rappelé par Firewall pendant l’événement
REQUEST
̶ Extraire l’identifiant et le mot de passe
̶ Créer le token non authentifié
̶ Passer le token à l’authentification manager
̶ Mettre le token authentifié dans le token storage
̶ Récupérer l’utilisateur grâce à l’identifiant et à
l’aide de user provider
̶ Vérifier le mot de passe à l’aide de password
encoder
̶ Vérifier les autres paramètres
̶ Renvoyer le token authentifié
$token->setAuthenticated(true)
créer un nouveau token
SymfonyComponentSecurityCoreAuthentication
26Auth provider
Provider
DaoAuthenticationProvider
- userProvider
- encoderFactory
- userChecker
AuthenticationManagerInterface
+ authenticate(TokenInterface $token)
SymfonyComponentSecurityCoreUser
UserProviderInterface
+ loadUserByUsername($username)
+ refreshUser(UserInterface $user)
+ supportsClass($class)
+ loadUserByUsername($username):User
InMemoryUserProvider
SymfonyComponentSecurityCoreAuthentication
27Auth provider
Provider
DaoAuthenticationProvider
- userProvider
- encoderFactory
- userChecker
SymfonyComponentSecurityCoreEncoder
EncoderFactoryInterface
+ getEncoder($user): PasswordEncoderInterface
PasswordEncoderInterface
+ encodePassword($raw, $salt)
+ isPasswordValid($encoded, $raw, $salt)
- cost: int
BCryptPasswordEncoder
- encoders: array
EncoderFactory
SymfonyComponentSecurityCoreAuthentication
28Auth provider
Provider
DaoAuthenticationProvider
AuthenticationManagerInterface
+ authenticate(TokenInterface $token)
SymfonyComponentSecurityCoreUser
UserChecker
+ checkPreAuth(UserInterface $user)
+ checkPostAuth(UserInterface $user)
UserCheckerInterface
- userProvider
- encoderFactory
- userChecker
29Auth provider
use SymfonyComponentSecurityCoreAuthenticationAuthenticationManagerInterface;
class MainSecurityListener implements ListenerInterface
{
/** @var AuthenticationManagerInterface */
private $authenticationManager;
public function handle(GetResponseEvent $event)
{
// Extract credentials from request...
if ($username && $credentials) {
try {
// Token is not authenticated because no role is passed.
$token = new UsernamePasswordToken($username, $credentials, 'main');
// Try to authenticate the token.
// If there is an authentication error an AuthenticationException is thrown.
$token = $this->authenticationManager->authenticate($token);
// Add authenticated token to storage.
$this->tokenStorage->setToken($token);
} catch (AuthenticationException $e) { }
}
}
}
use SymfonyComponentSecurityCoreUserInMemoryUserProvider;
use SymfonyComponentSecurityCoreAuthenticationProviderDaoAuthenticationProvider;
use SymfonyComponentSecurityCoreEncoderEncoderFactory;
use SymfonyComponentSecurityCoreUserUser;
use SymfonyComponentSecurityCoreEncoderBCryptPasswordEncoder;
// Create user provider that will be used by authentication listener.
$mainUserProvider = new InMemoryUserProvider([
'gordon' => [
'password' => '$2y$10$50MJW4ov/LHLBdl6uYsxI.7MdWYoJ8K1MqBXfG677nOXbsSVVue6i',
'roles' => ['ROLE_USER'],
'enabled' => true,
],
]);
// Service that checks whether a user is non-locked, enabled, not expired, etc.
$mainUserChecker = new SymfonyComponentSecurityCoreUserUserChecker();
// A factory that specifies encoding algorithm to each user class.
$encoderFactory = new EncoderFactory([User::class => new BCryptPasswordEncoder(10)]);
// Create a provider to which security listener will delegate an authentication.
$mainAuthProvider = new DaoAuthenticationProvider(
$mainUserProvider, $mainUserChecker, 'main', $encoderFactory
);
// Create main security listener that handles authentication.
$mainSecurityListener = new AppSecurityMainSecurityListener($tokenStorage, $mainAuthProvider);
30Auth provider
31Auth provider
# config/packages/security.yaml
security:
providers:
in_memory:
memory: # returns SymfonyComponentSecurityCoreUserUser object
users:
gordon:
password: freeman
roles: 'ROLE_USER'
g-man:
password: bureaucrat
roles: 'ROLE_EMPLOYER'
encoders:
SymfonyComponentSecurityCoreUserUser:
algorithm: bcrypt
cost: 10
32HTTP basic auth
Mettre en place l’authentification HTTP, laisser passer seulement les
utilisateurs connectés.Tâche 6
SymfonyComponentSecurityHttpFirewall
- tokenStorage
- authenticationManager
BasicAuthenticationListener
- tokenStorage
- accessDecisionManager
AccessListener
RequestMatcher
- path: ^/main
=>
Extraire l’identifiant et le mot de
passe de l'en-tête Authorization.
Créer le token, l'authentifier, le
sauvegarder dans token storage.
Lancer une exception si les
credentials ne sont pas valides. Lancer une exception si le token
n’est pas présent ou s’il ne
respecte pas les règles d’accès.
33
SymfonyComponentSecurityHttpEntryPoint
+ start(Request $request, $authException): Response
AuthenticationEntryPointInterface
- realmName: string
BasicAuthenticationEntryPoint
Lors de l'exception d’authentification (accès anonyme ou identifiants non valides) il faut
aider l’utilisateur à (re-)commencer l’authentification.
SymfonyComponentSecurityHttpFirewall
- tokenStorage
- authenticationManager
- authenticationEntryPoint
BasicAuthenticationListener
EventDispatcher
- Kernel::EXCEPTION => [...]
- authenticationEntryPoint
ExceptionListener
HTTP basic auth
34HTTP basic auth
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpAccessMap;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewallBasicAuthenticationListener;
use SymfonyComponentSecurityHttpFirewallAccessListener;
use SymfonyComponentSecurityHttpEntryPointBasicAuthenticationEntryPoint;
use SymfonyComponentSecurityCoreAuthorizationAccessDecisionManager;
// ...
// Entry point helps user to authenticate.
$basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint('Black mesa');
// Create HTTP basic security listener that extracts credentials from headers (RFC 7617).
$mainSecurityListener = new BasicAuthenticationListener(
$tokenStorage, $mainAuthProvider, 'main', $basicAuthenticationEntryPoint
);
$accessDecisionManager = new AccessDecisionManager();
$accessMap = new AccessMap();
// Access listener will throw an exception when no token is already present.
$accessListener = new AccessListener(
$tokenStorage, $accessDecisionManager, $accessMap, $mainAuthProvider
);
// ...
35HTTP basic auth
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewallExceptionListener;
use SymfonyComponentSecurityCoreAuthenticationAuthenticationTrustResolver;
use SymfonyComponentSecurityCoreAuthenticationTokenAnonymousToken;
use SymfonyComponentSecurityCoreAuthenticationTokenRememberMeToken;
// ...
// ExceptionListener catches authentication exception and converts them to Response instance.
// In this case it invites user to enter its credentials by returning 401 response.
$authTrustResolver = new AuthenticationTrustResolver(AnonymousToken::class, RememberMeToken::class);
$mainExceptionListener = new ExceptionListener(
$tokenStorage, $authTrustResolver, $httpUtils, 'main', $basicAuthenticationEntryPoint
);
// Create firewall map and add main security listener under URLs starting with "/main".
$firewallMap = new FirewallMap();
$firewallMap->add(
new RequestMatcher('^/main’),
[$mainSecurityListener, $accessListener],
$mainExceptionListener
);
// ...
36HTTP basic auth
# config/packages/security.yaml
security:
firewalls:
half_life:
pattern: ^/lambda
host: half-life.com
http_basic:
realm: "Lambda Complex"
37Formulaire de connexion
Mettre en place l’authentification par le formulaire de connexion pour une
autre partie de site.Tâche 7
SymfonyComponentSecurityHttpFirewall
- tokenStorage
- userProviders
ContextListener
- tokenStorage
- accessDecisionManager
- options
- successHandler
- failureHandler
UsernamePasswordFormAuthenticationListener
RequestMatcher
- path: ^/front
=>
+ handle(GetResponseEvent $event)
+ onKernelResponse(FilterResponseEvent $event)
+ handle(GetResponseEvent $event)
Récupérer le token d’une session
lors de l’événement REQUEST.
Sauvegarder le token dans une
session lors de l’événement
RESPONSE.
Authentifier l’utilisateur
seulement quand le formulaire de
connexion est envoyé
(POST sur /front/login_check).
38Formulaire de connexion
Nouvelle action pour visualiser le formulaire de conexion : POST sur /front/login_check.
namespace App;
class Controller
{
public function loginFormAction()
{
return new Response(<<<END
<form action="/front/login_check" method="POST">
<input type="text" name="_username" placeholder="username">
<input type="password" name="_password" placeholder="password">
<input type="submit">
</form>
END
);
}
public function defaultAction()
{
$token = $this->tokenStorage->getToken();
$user = $token ? $token->getUser() : null;
// ...
}
}
39Formulaire de connexion
La nouvelle action sera appelée quand la requête est faite sur /font/login.
namespace App;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelControllerControllerResolverInterface;
class ControllerResolver implements ControllerResolverInterface
{
/** @var callable[] */
private $routes;
/** @var callable */
private $default;
public function getController(Request $request)
{
foreach ($this->routes as $pattern => $controller) {
if (preg_match($pattern, $request->getPathInfo())) {
return $controller;
}
}
return $this->default;
}
}
40Formulaire de connexion
La nouvelle action sera appelée quand la requête est faite sur /font/login.
// public/index.php
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentHttpKernelHttpKernel;
// ...
$dispatcher = new EventDispatcher();
// Controller creates a response to send to the user.
$controller = new AppController($request, $tokenStorage);
$controllerResolver = new AppControllerResolver(
['/^/front/login$/' => [$controller, 'loginFormAction']],
[$controller, 'defaultAction']
);
// Kernel is in charge of converting a Request into a Response by using the event dispatcher.
$kernel = new HttpKernel($dispatcher, $controllerResolver);
// ...
41Formulaire de connexion
Context security listener :
// public/index.php
use SymfonyComponentSecurityHttpFirewallContextListener;
// ...
// ContextListener retrieves previously authenticated token from the session during REQUEST event.
// It also saves token during RESPONSE event.
$contextListener = new ContextListener(
$tokenStorage, [$mainUserProvider], 'front', null, $dispatcher
);
// ...
42Formulaire de connexion
use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationSuccessHandler;
use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationFailureHandler;
use SymfonyComponentSecurityHttpFirewallUsernamePasswordFormAuthenticationListener;
use SymfonyComponentSecurityHttpSessionSessionAuthenticationStrategy;
$sessionAuthenticationStrategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
$successHandler = new DefaultAuthenticationSuccessHandler(
$httpUtils, ['default_target_path' => '/front/success’]
);
$failureHandler = new DefaultAuthenticationFailureHandler(
$kernel, $httpUtils, ['login_path' => '/front/login’]
);
// Listens for login form being send (POST to '/front/login_check').
// It extracts credentials, creates token, authenticates it and puts it to the token storage.
$formAuthListener = new UsernamePasswordFormAuthenticationListener(
$tokenStorage,
$frontAuthProvider, // The same authentication provider as for HTTP basic (except 'key'='front').
$sessionAuthenticationStrategy,
$httpUtils,
'front',
$successHandler, // Redirect user to '/front/success' if credentials are valid
$failureHandler, // Redirect user to '/front/login' if credentials are invalid
['check_path' => '/front/login_check', 'post_only' => true] // Act only on POST to '/front/login_check'
);
43Formulaire de connexion
Ajout de security listeners dans le Firewall :
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewall;
// ...
// Create firewall map
$firewallMap = new FirewallMap();
// Add basic http security listener under URLs starting with "/main".
$firewallMap->add(
new RequestMatcher('^/main'), [$mainSecurityListener, $accessListener], $mainExceptionListener
);
// Add login form security listeners under URLs starting with "/front".
$firewallMap->add(new RequestMatcher('^/front'), [$contextListener, $formAuthListener]);
// Create firewall and add it to dispatcher.
$firewall = new Firewall($firewallMap, $dispatcher);
$dispatcher->addSubscriber($firewall);
// ...
SymfonyComponentSecurityCoreAuthorization
44Formulaire de connexion
Vérifier les rôles d’utilisateurs avant de les autoriser à accéder
aux certains URLs.Tâche 8
- voters : VoterInterface[]
+ decide($token, $attributes, $object)
AuthorizationChecker
- tokenStorage
- accessDecisionManager
+ isGranted($attributes, $object)
AccessDecisionManager
Voter
+ vote($token, $subject, $attributes)
VoterInterface
RoleVoter AuthenticatedVoter
ROLE_*
IS_AUTHENTICATED_FULLY
IS_AUTHENTICATED_REMEMBERED
IS_AUTHENTICATED_ANONYMOUSLY
SymfonyComponentSecurityHttp
45Formulaire de connexion
AccessMap
+ add($requestMatcher, $attributes, $channel)
+ getPatterns(Request $request): array
- map: array
# config/security.yaml
security:
access_control:
- { path: ^/main, roles: ROLE_SCIENTIST }
- { path: ^/front/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/front, roles: ROLE_EMPLOYER }
// public/index.php
// Access map defines authorization rules, it maps request to attributes.
// It helps access listeners to determine the attributes the user must possess.
$accessMap = new AccessMap();
$accessMap->add(new RequestMatcher('^/main'), ['ROLE_SCIENTIST']);
$accessMap->add(new RequestMatcher('^/front/login$'), ['IS_AUTHENTICATED_ANONYMOUSLY']);
$accessMap->add(new RequestMatcher('^/front'), ['ROLE_EMPLOYER’]);
//...
Access map renvoi les attributs que l’utilisateur doit posséder :
46Formulaire de connexion
AccessListener
+ handle(GetResponseEvent $event)
- tokenStorage
- authManager
- accessDecisionManager
- map
Access map renvoi les attributs que l’utilisateur doit posséder :
SymfonyComponentSecurityHttp
AccessMapInterface
+ getPatterns(Request $request): array
SymfonyComponentSecurityCoreAuthorization
+ decide($token, $attributes, $object)
AccessDecisionManager
47Formulaire de connexion
// public/index.php
use SymfonyComponentSecurityCoreAuthorizationVoterAuthenticatedVoter;
use SymfonyComponentSecurityCoreAuthorizationVoterRoleVoter;
use SymfonyComponentSecurityCoreAuthorizationAccessDecisionManager;
// ...
// RoleVoter can determine if authenticated user has necessary roles
// like 'ROLE_SCIENTIST' or 'ROLE_EMPLOYER'.
$roleVoter = new RoleVoter();
// AuthenticatedVoter can determine if token is anonymous or fully authentified.
$authenticatedVoter = new AuthenticatedVoter($authTrustResolver);
// Access decision manager verifies authorisation of authentified token thanks to voters.
$accessDecisionManager = new AccessDecisionManager([$roleVoter, $authenticatedVoter]);
// ...
48Formulaire de connexion
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpAccessMap;
use SymfonyComponentSecurityCoreUserInMemoryUserProvider;
// Access map defines authorization rules, it maps request to attributes.
// It helps access listeners to determine the attributes the user must possess.
$accessMap = new AccessMap();
$accessMap->add(new RequestMatcher('^/main'), ['ROLE_SCIENTIST']);
$accessMap->add(new RequestMatcher('^/front/login$'), ['IS_AUTHENTICATED_ANONYMOUSLY']);
$accessMap->add(new RequestMatcher('^/front'), ['ROLE_EMPLOYER']);
// Create user provider that will be used by authentication listener.
$mainUserProvider = new InMemoryUserProvider([
'gordon' => [
'password' => '$2y$10$50MJW4ov/LHLBdl6uYsxI.7MdWYoJ8K1MqBXfG677nOXbsSVVue6i',
'roles' => ['ROLE_SCIENTIST'],
],
'g-man' => [
'password' => '$2y$10$.23HMg6E0qsMXYcscJyJBOVFzSC31aWY8wd3CHJeO86dRljos0zie',
'roles' => ['ROLE_EMPLOYER'],
],
]);
// ...
49Formulaire de connexion
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallAccessListener;
// ...
// Access listener will throw an exception when no token is already present.
$mainAccessListener = new AccessListener(
$tokenStorage, $accessDecisionManager, $accessMap, $mainAuthProvider
);
// Add basic http security listener under URLs starting with "/main".
$firewallMap->add(
new RequestMatcher('^/main’),
[$mainSecurityListener, $mainAccessListener],
$mainExceptionListener
);
// ...
50Formulaire de connexion
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallAccessListener;
// ...
// Access listener will throw an exception when no token is already present.
$frontAccessListener = new AccessListener(
$tokenStorage, $accessDecisionManager, $accessMap, $frontAuthProvider
);
// Add login form security listeners under URLs starting with "/front".
$firewallMap->add(
new RequestMatcher('^/front’),
[$contextListener, $formAuthListener, $frontAnonListener, $frontAccessListener],
$frontExceptionListener
);
// ...
Merci pour votre attention
Le code de cette présentation :
https://github.com/vria/symfony-security-component-use

More Related Content

What's hot

Networking in Java with NIO and Netty
Networking in Java with NIO and NettyNetworking in Java with NIO and Netty
Networking in Java with NIO and NettyConstantine Slisenka
 
Java Threads and Concurrency
Java Threads and ConcurrencyJava Threads and Concurrency
Java Threads and ConcurrencySunil OS
 
Redux Saga - Under the hood
Redux Saga - Under the hoodRedux Saga - Under the hood
Redux Saga - Under the hoodWaqqas Jabbar
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.jsjacekbecela
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to CeleryIdan Gazit
 
Vert.x for Microservices Architecture
Vert.x for Microservices ArchitectureVert.x for Microservices Architecture
Vert.x for Microservices ArchitectureIdan Fridman
 
Spring security oauth2
Spring security oauth2Spring security oauth2
Spring security oauth2axykim00
 
gestion Comptes Bancaire SpringBoot-Exemple.pdf
gestion Comptes Bancaire SpringBoot-Exemple.pdfgestion Comptes Bancaire SpringBoot-Exemple.pdf
gestion Comptes Bancaire SpringBoot-Exemple.pdfMohamedHassoun11
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React AlicanteIgnacio Martín
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
Symfony on steroids
: Vue.js, Mercure, Panther
Symfony on steroids
: Vue.js, Mercure, PantherSymfony on steroids
: Vue.js, Mercure, Panther
Symfony on steroids
: Vue.js, Mercure, PantherLes-Tilleuls.coop
 
Asynchronous JavaScript Programming
Asynchronous JavaScript ProgrammingAsynchronous JavaScript Programming
Asynchronous JavaScript ProgrammingHaim Michael
 

What's hot (20)

Le guide d'administration d'un site sous joomla3
Le guide d'administration d'un site sous joomla3Le guide d'administration d'un site sous joomla3
Le guide d'administration d'un site sous joomla3
 
Networking in Java with NIO and Netty
Networking in Java with NIO and NettyNetworking in Java with NIO and Netty
Networking in Java with NIO and Netty
 
jdbc document
jdbc documentjdbc document
jdbc document
 
Java Threads and Concurrency
Java Threads and ConcurrencyJava Threads and Concurrency
Java Threads and Concurrency
 
Introduction à Laravel
Introduction à LaravelIntroduction à Laravel
Introduction à Laravel
 
Json Web Token - JWT
Json Web Token - JWTJson Web Token - JWT
Json Web Token - JWT
 
Redux Saga - Under the hood
Redux Saga - Under the hoodRedux Saga - Under the hood
Redux Saga - Under the hood
 
Introduction à ASP.NET
Introduction à ASP.NETIntroduction à ASP.NET
Introduction à ASP.NET
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
 
JUnit 4
JUnit 4JUnit 4
JUnit 4
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to Celery
 
react-slides.pptx
react-slides.pptxreact-slides.pptx
react-slides.pptx
 
Vert.x for Microservices Architecture
Vert.x for Microservices ArchitectureVert.x for Microservices Architecture
Vert.x for Microservices Architecture
 
Spring security oauth2
Spring security oauth2Spring security oauth2
Spring security oauth2
 
gestion Comptes Bancaire SpringBoot-Exemple.pdf
gestion Comptes Bancaire SpringBoot-Exemple.pdfgestion Comptes Bancaire SpringBoot-Exemple.pdf
gestion Comptes Bancaire SpringBoot-Exemple.pdf
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Symfony on steroids
: Vue.js, Mercure, Panther
Symfony on steroids
: Vue.js, Mercure, PantherSymfony on steroids
: Vue.js, Mercure, Panther
Symfony on steroids
: Vue.js, Mercure, Panther
 
Asynchronous JavaScript Programming
Asynchronous JavaScript ProgrammingAsynchronous JavaScript Programming
Asynchronous JavaScript Programming
 
Apache tomcat
Apache tomcatApache tomcat
Apache tomcat
 

Similar to Securing Web Apps with Symfony Security Component"TITLE"Symfony Security: Authentication, Authorization and Firewalls" TITLE"Build Secure Symfony Apps Using Authentication and Authorization"TITLE"Symfony Security Best Practices for Web Applications"TITLE"Symfony Security Component Tutorial: Authentication and Firewalls

Sécurisation de vos applications web à l’aide du composant Security de Symfony
Sécurisation de vos applications web à l’aide du composant Security de SymfonySécurisation de vos applications web à l’aide du composant Security de Symfony
Sécurisation de vos applications web à l’aide du composant Security de SymfonyVladyslav Riabchenko
 
JWT - Sécurisez vos APIs
JWT - Sécurisez vos APIsJWT - Sécurisez vos APIs
JWT - Sécurisez vos APIsAndré Tapia
 
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menace
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menaceDEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menace
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menaceFelipe Prado
 
Implementing application security using the .net framework
Implementing application security using the .net frameworkImplementing application security using the .net framework
Implementing application security using the .net frameworkLalit Kale
 
OAuth 2.0 and Library
OAuth 2.0 and LibraryOAuth 2.0 and Library
OAuth 2.0 and LibraryKenji Otsuka
 
How to Build an Indivo X Personal Health App
How to Build an Indivo X Personal Health AppHow to Build an Indivo X Personal Health App
How to Build an Indivo X Personal Health AppBen Adida
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
CIS 2012 - Going Mobile with PingFederate and OAuth 2
CIS 2012 - Going Mobile with PingFederate and OAuth 2CIS 2012 - Going Mobile with PingFederate and OAuth 2
CIS 2012 - Going Mobile with PingFederate and OAuth 2scotttomilson
 
Java Web Programming [9/9] : Web Application Security
Java Web Programming [9/9] : Web Application SecurityJava Web Programming [9/9] : Web Application Security
Java Web Programming [9/9] : Web Application SecurityIMC Institute
 
Building a Microgateway in Ballerina_KubeCon 2108
Building a Microgateway in Ballerina_KubeCon 2108Building a Microgateway in Ballerina_KubeCon 2108
Building a Microgateway in Ballerina_KubeCon 2108Ballerina
 
Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)danwrong
 
Spring Framework - Spring Security
Spring Framework - Spring SecuritySpring Framework - Spring Security
Spring Framework - Spring SecurityDzmitry Naskou
 
How to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAMHow to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAMProvectus
 
WP Passkey: Passwordless Authentication on WordPress
WP Passkey: Passwordless Authentication on WordPressWP Passkey: Passwordless Authentication on WordPress
WP Passkey: Passwordless Authentication on WordPressWordPress
 
Securing your Pulsar Cluster with Vault_Chris Kellogg
Securing your Pulsar Cluster with Vault_Chris KelloggSecuring your Pulsar Cluster with Vault_Chris Kellogg
Securing your Pulsar Cluster with Vault_Chris KelloggStreamNative
 
OAuth2 on Ericsson Labs
OAuth2 on Ericsson LabsOAuth2 on Ericsson Labs
OAuth2 on Ericsson LabsEricsson Labs
 
Client certificate validation in windows 8
Client certificate validation in windows 8Client certificate validation in windows 8
Client certificate validation in windows 8Ashish Agrawal
 
Security In .Net Framework
Security In .Net FrameworkSecurity In .Net Framework
Security In .Net FrameworkRamakanta Behera
 

Similar to Securing Web Apps with Symfony Security Component"TITLE"Symfony Security: Authentication, Authorization and Firewalls" TITLE"Build Secure Symfony Apps Using Authentication and Authorization"TITLE"Symfony Security Best Practices for Web Applications"TITLE"Symfony Security Component Tutorial: Authentication and Firewalls (20)

Sécurisation de vos applications web à l’aide du composant Security de Symfony
Sécurisation de vos applications web à l’aide du composant Security de SymfonySécurisation de vos applications web à l’aide du composant Security de Symfony
Sécurisation de vos applications web à l’aide du composant Security de Symfony
 
JWT - Sécurisez vos APIs
JWT - Sécurisez vos APIsJWT - Sécurisez vos APIs
JWT - Sécurisez vos APIs
 
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menace
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menaceDEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menace
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menace
 
Implementing application security using the .net framework
Implementing application security using the .net frameworkImplementing application security using the .net framework
Implementing application security using the .net framework
 
OAuth 2.0 and Library
OAuth 2.0 and LibraryOAuth 2.0 and Library
OAuth 2.0 and Library
 
How to Build an Indivo X Personal Health App
How to Build an Indivo X Personal Health AppHow to Build an Indivo X Personal Health App
How to Build an Indivo X Personal Health App
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
CIS 2012 - Going Mobile with PingFederate and OAuth 2
CIS 2012 - Going Mobile with PingFederate and OAuth 2CIS 2012 - Going Mobile with PingFederate and OAuth 2
CIS 2012 - Going Mobile with PingFederate and OAuth 2
 
Java Web Programming [9/9] : Web Application Security
Java Web Programming [9/9] : Web Application SecurityJava Web Programming [9/9] : Web Application Security
Java Web Programming [9/9] : Web Application Security
 
Building a Microgateway in Ballerina_KubeCon 2108
Building a Microgateway in Ballerina_KubeCon 2108Building a Microgateway in Ballerina_KubeCon 2108
Building a Microgateway in Ballerina_KubeCon 2108
 
Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
 
Spring Framework - Spring Security
Spring Framework - Spring SecuritySpring Framework - Spring Security
Spring Framework - Spring Security
 
How to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAMHow to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAM
 
WP Passkey: Passwordless Authentication on WordPress
WP Passkey: Passwordless Authentication on WordPressWP Passkey: Passwordless Authentication on WordPress
WP Passkey: Passwordless Authentication on WordPress
 
Securing your Pulsar Cluster with Vault_Chris Kellogg
Securing your Pulsar Cluster with Vault_Chris KelloggSecuring your Pulsar Cluster with Vault_Chris Kellogg
Securing your Pulsar Cluster with Vault_Chris Kellogg
 
OAuth2 on Ericsson Labs
OAuth2 on Ericsson LabsOAuth2 on Ericsson Labs
OAuth2 on Ericsson Labs
 
TLDR - OAuth
TLDR - OAuthTLDR - OAuth
TLDR - OAuth
 
Client certificate validation in windows 8
Client certificate validation in windows 8Client certificate validation in windows 8
Client certificate validation in windows 8
 
State management
State managementState management
State management
 
Security In .Net Framework
Security In .Net FrameworkSecurity In .Net Framework
Security In .Net Framework
 

More from Vladyslav Riabchenko

Modèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratiqueModèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratiqueVladyslav Riabchenko
 
SOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsSOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsVladyslav Riabchenko
 
SOLID: the core principles of success of the Symfony web framework and of you...
SOLID: the core principles of success of the Symfony web framework and of you...SOLID: the core principles of success of the Symfony web framework and of you...
SOLID: the core principles of success of the Symfony web framework and of you...Vladyslav Riabchenko
 
Versionning sémantique et Composer
Versionning sémantique et ComposerVersionning sémantique et Composer
Versionning sémantique et ComposerVladyslav Riabchenko
 
Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Vladyslav Riabchenko
 
Les patrons de conception du composant Form
Les patrons de conception du composant FormLes patrons de conception du composant Form
Les patrons de conception du composant FormVladyslav Riabchenko
 

More from Vladyslav Riabchenko (7)

Modèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratiqueModèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratique
 
SOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsSOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applications
 
SOLID: the core principles of success of the Symfony web framework and of you...
SOLID: the core principles of success of the Symfony web framework and of you...SOLID: the core principles of success of the Symfony web framework and of you...
SOLID: the core principles of success of the Symfony web framework and of you...
 
Git
GitGit
Git
 
Versionning sémantique et Composer
Versionning sémantique et ComposerVersionning sémantique et Composer
Versionning sémantique et Composer
 
Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3
 
Les patrons de conception du composant Form
Les patrons de conception du composant FormLes patrons de conception du composant Form
Les patrons de conception du composant Form
 

Recently uploaded

Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningVitsRangannavar
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 

Recently uploaded (20)

Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learning
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 

Securing Web Apps with Symfony Security Component"TITLE"Symfony Security: Authentication, Authorization and Firewalls" TITLE"Build Secure Symfony Apps Using Authentication and Authorization"TITLE"Symfony Security Best Practices for Web Applications"TITLE"Symfony Security Component Tutorial: Authentication and Firewalls

  • 1. Sécurisation de vos applications web à l’aide du composant Security de Symfony 25 sept 2018
  • 2. https://vria.eu contact@vria.eu https://twitter.com/RiaVlad RIABCHENKO Vladyslav 5+ ans full stack web-développeur Certifié Symfony Architecte technique à Webnet
  • 3. Symfony 3 1. Concepts de sécurité 2. Authentification artisanale 3. Firewall 4. Token anonyme 5. User provider 6. Authentication provider 7. HTTP Basic 8. Formulaire de connexion 9. Autorisation autour des rôles Plan
  • 4. Symfony 4 Authentification est un processus permettant à l’application de s’assurer que la requête a été faite par un utilisateur légitime. C’est une confirmation de son identité grâce à des identifiants. Identification est une sélection d’utilisateur grâce à son identifiant. Autorisation est une vérification des droits d’accès d’un utilisateur sur une ressource en se basant sur une politique d’accès.
  • 5. Auth simple 5 Authentifier chaque requête à l’application à l’aide d’un identifiant et d’un mot de passe.Tâche 1 Front controller Token public/index.php reçoit toutes les requêtes client quelque soit le path et les paramètres HttpFoundation Composant de Symfony qui fournit la couche orientée-objet pour HTTP : Request, Response, Session, etc. Conserve des données sur l’utilisateur : • Objet d’utilisateur • Username • Credentials • Roles • Authentifié ou pas
  • 6. SymfonyComponentSecurityCoreAuthenticationToken 6 Security listeners Token Conserve des données sur l’utilisateur + getUser() + getUsername() + getCredentials() + isAuthenticated() + getRoles() TokenInterface + getProviderKey() UsernamePasswordToken + getSecret() AnonymousToken Listeners qui extraient les identifiants et les vérifient. Ils créent ensuite un Token puis le stockent dans le Token storage. Token storage Objet/service qui contient un Token Auth simple
  • 7. 7Auth simple // public/index.php use SymfonyComponentHttpFoundationRequest; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage; use SymfonyComponentHttpFoundationResponse; $request = Request::createFromGlobals(); // HTTP request $tokenStorage = new TokenStorage(); // Service that stores user token // Call security listener on every request. $securityListener = new AppSecuritySecurityListener($tokenStorage); $securityListener->onRequest($request); // Any code you can imagine to generate a response. // You can deny access if no token were set. $token = $tokenStorage->getToken(); $response = new Response( 'Request uri: '.$request->getRequestUri().'<br>' .'Token: '.(is_object($token) ? get_class($token) : gettype($token)).'<br>' .'Username: '.($token ? $token->getUsername(): 'NULL') ); $response->send(); // Send response
  • 8. 8Auth simple namespace AppSecurity; use SymfonyComponentHttpFoundationRequest; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface; use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken; class SecurityListener { /** @var TokenStorageInterface */ private $tokenStorage; public function onRequest(Request $request) { $user = $request->query->get('auth_user'); $password = $request->query->get('auth_pw'); if ($user === 'gordon' && $password === 'freeman') { // Credentials are valid. // Create a token with user object, credentials, provider key and roles $token = new UsernamePasswordToken($user, $password, 'main', ['ROLE_USER']); // Save it to token storage $this->tokenStorage->setToken($token); } } }
  • 9. Firewall 9 Centraliser l’authentification dans un firewall afin de pouvoir utiliser plusieurs systèmes d’authentification.Tâche 2 HttpKernel Le composant de Symfony qui fournit un processus structuré pour convertir Request en Response en utilisant EventDispatcher. EventDispatcher Le composant de Symfony qui permet aux composants de communiquer entre eux à l’aide d’événements. Request ResponseExecute controller EXCEPTIONEvent Dispatcher
  • 10. 10Firewall Le Front controller crée $kernel et lui demande de traiter la requête. // public/index.php use SymfonyComponentEventDispatcherEventDispatcher; use SymfonyComponentHttpFoundationRequest; use SymfonyComponentHttpKernelHttpKernel; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage; $request = Request::createFromGlobals(); // HTTP request. $tokenStorage = new TokenStorage(); // Service that stores user token. $dispatcher = new EventDispatcher(); // Controller creates a response to send to the user. $controller = new AppController($request, $tokenStorage); $controllerResolver = new AppControllerResolver([$controller, 'defaultAction']); // Kernel is in charge of converting a Request into a Response by using the event dispatcher. $kernel = new HttpKernel($dispatcher, $controllerResolver); // We will add security listeners to dispatcher in few minutes. $response = $kernel->handle($request); // Launch kernel and retrieve response. $response->send(); // Send response.
  • 11. 11 Kernel demande à ControllerResolver de renvoyer le contrôleur en fonction de la requête. C’est l’emplacement idéal pour la logique de Routing. Firewall namespace App; use SymfonyComponentHttpFoundationRequest; use SymfonyComponentHttpKernelControllerControllerResolverInterface; class ControllerResolver implements ControllerResolverInterface { /** @var callable */ private $default; public function __construct(callable $default) { $this->default = $default; } public function getController(Request $request) { return $this->default; } }
  • 12. 12 La méthode Controller::defaultAction est un contrôleur qui sera exécuté par Kernel. Firewall namespace App; class Controller { /** @var Request */ private $request; /** @var TokenStorageInterface */ private $tokenStorage; public function defaultAction() { $token = $this->tokenStorage->getToken(); return new Response( 'Request uri: '.$this->request->getRequestUri().'<br>' .'Token: '.(is_object($token) ? get_class($token) : gettype($token)).'<br>' .'Username: '.($token ? $token->getUsername(): 'NULL') ); } }
  • 13. SymfonyComponentSecurityHttp 13 - map: array + getListeners(Request $request) Firewall - map: FirewallMap + onKernelRequest(GetResponseEvent $event) FirewallMap RequestMatcher - path: string => ][ Le firewall est un listener de l’événement REQUEST. Il permet d’implémenter des stratégies d’authentification en fonction de la requête. FirewallMap renvoie les listeners configurés pour le requête spécifique. ListenerInterface + handle(GetResponseEvent $event) , … Firewall
  • 14. 14 RequestMatcher - path = ^/lambda - host = half-life.com => ][ BasicAuthenticationListener Utiliser l’authentification HTTP basic pour toutes les requêtes qui commencent par /lambda sur le serveur half-life.com : Firewall # config/packages/security.yaml security: firewalls: half_life: pattern: ^/lambda host: half-life.com http_basic: realm: "Lambda Complex"
  • 15. 15 RequestMatcher - path: ^/customer => ][ ContextListener , SimpleFormAuthenticationListener Authentifier les requêtes qui commencent par /customer à l’aide d’un formulaire classique Firewall # config/packages/security.yaml security: firewalls: half_life: # ... customer: pattern: ^/customer form_login: check_path: /login_check login_path: /login
  • 16. 16 RequestMatcher => ][AnonymousAuthenticationListener Authentifier toutes les autres requêtes comme anonymes Firewall # config/packages/security.yaml security: firewalls: half_life: # ... customer: # ... public: anonymous: true
  • 17. 17 Firewall attends l’événement REQUEST pour exécuter MainSecurityListener si le path de la requête commence par /main. Firewall // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewall; // ... // Create main security listener that handles authentication. $securityListener = new AppSecurityMainSecurityListener($tokenStorage); // Create firewall map and add main security listener under URLs starting with "/main". $firewallMap = new FirewallMap(); $firewallMap->add(new RequestMatcher('^/main'), [$securityListener]); // Create firewall and add it to dispatcher. $firewall = new Firewall($firewallMap, $dispatcher); $dispatcher->addSubscriber($firewall); // ...
  • 18. 18 MainSecurityListener implémente désormais ListenerInterface. Firewall namespace AppSecurity; use SymfonyComponentHttpKernelEventGetResponseEvent; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface; use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken; use SymfonyComponentSecurityHttpFirewallListenerInterface; class MainSecurityListener implements ListenerInterface { /** @var TokenStorageInterface */ private $tokenStorage; public function handle(GetResponseEvent $event) { $request = $event->getRequest(); $user = $request->query->get('auth_user'); $password = $request->query->get('auth_pw'); if ($user === 'gordon' && $password === 'freeman') { $token = new UsernamePasswordToken($user, $password, 'main', ['ROLE_USER']); $this->tokenStorage->setToken($token); } } }
  • 19. App SymfonyComponentSecurityHttpFirewall anon. 19 Permettre aux utilisateurs de s’authentifier comme des anonymes.Tâche 3 RequestMatcher - path = ^/main => ][ MainSecurityListener AnonymousAuthenticationListener # config/packages/security.yaml security: firewalls: main: # ... anonymous: true
  • 20. anon. 20 // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewallAnonymousAuthenticationListener; // ... // Create a security listener that adds anonymous token if none is already present. $anonListener = new AnonymousAuthenticationListener($tokenStorage, 'secret'); // Create firewall map and add main security listener under URLs starting with "/main". $firewallMap = new FirewallMap(); $firewallMap->add(new RequestMatcher('^/main'), [$securityListener, $anonListener]); // ... Plusieurs security listeners peuvent s'enchaîner :
  • 21. User provider 21 Abstraire le moyen de récupération des utilisateurs et déplacer cette logique en dehors des security listeners.Tâche 4 SymfonyComponentSecurityCoreUser UserProviderInterface + loadUserByUsername($username): UserInterface + refreshUser(UserInterface $user) + supportsClass($class) Security Listener - userProvider + loadUserByUsername($username):User UserInterface + getUsername() + getRoles() + getPassword() + getSalt() + eraseCredentials() + isEnabled() UserInMemoryUserProvider
  • 22. 22User provider use SymfonyComponentHttpKernelEventGetResponseEvent; use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken; use SymfonyComponentSecurityCoreExceptionUsernameNotFoundException; use SymfonyComponentSecurityCoreUserUserProviderInterface; use SymfonyComponentSecurityHttpFirewallListenerInterface; class MainSecurityListener implements ListenerInterface { /** @var UserProviderInterface */ private $userProvider; public function handle(GetResponseEvent $event) { $request = $event->getRequest(); $username = $request->query->get('auth_user'); $password = $request->query->get('auth_pw'); try { $user = $this->userProvider->loadUserByUsername($username); if ($user->getPassword() === $password) { $token = new UsernamePasswordToken($user, $password, 'main', $user->getRoles()); $this->tokenStorage->setToken($token); } } catch (UsernameNotFoundException $e) { } } }
  • 23. 23User provider Création d’un user provider pour main security listener. // public/index.php use SymfonyComponentEventDispatcherEventDispatcher; use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewall; use SymfonyComponentSecurityCoreUserInMemoryUserProvider; // ... // Create user provider that will be used by authentication listener. $mainUserProvider = new InMemoryUserProvider([ 'gordon' => ['password' => 'freeman', 'roles' => ['ROLE_USER']], ]); // Create main security listener that handles authentication. $mainSecurityListener = new AppSecurityMainSecurityListener($tokenStorage, $mainUserProvider); // Create firewall map and add main security listener under URLs starting with "/main". $firewallMap = new FirewallMap(); $firewallMap->add(new RequestMatcher('^/main'), [$mainSecurityListener, $anonListener]); // ...
  • 24. 24User provider # config/packages/security.yaml security: providers: hl_characters: memory: users: gordon: password: freeman roles: 'ROLE_USER' g-man: password: bureaucrat roles: 'ROLE_EMPLOYER'
  • 25. App 25Auth provider Ajouter l’encodage du mot de passe, n’accepter que des utilisateurs activés. Déplacer la logique d’authentification en dehors des security listeners.Tâche 5 - tokenStorage - authenticationManager SymfonyComponentSecurityCoreAuthentication AuthenticationManagerInterface + authenticate(TokenInterface $token) MainSecurityListener ̶ Être rappelé par Firewall pendant l’événement REQUEST ̶ Extraire l’identifiant et le mot de passe ̶ Créer le token non authentifié ̶ Passer le token à l’authentification manager ̶ Mettre le token authentifié dans le token storage ̶ Récupérer l’utilisateur grâce à l’identifiant et à l’aide de user provider ̶ Vérifier le mot de passe à l’aide de password encoder ̶ Vérifier les autres paramètres ̶ Renvoyer le token authentifié $token->setAuthenticated(true) créer un nouveau token
  • 26. SymfonyComponentSecurityCoreAuthentication 26Auth provider Provider DaoAuthenticationProvider - userProvider - encoderFactory - userChecker AuthenticationManagerInterface + authenticate(TokenInterface $token) SymfonyComponentSecurityCoreUser UserProviderInterface + loadUserByUsername($username) + refreshUser(UserInterface $user) + supportsClass($class) + loadUserByUsername($username):User InMemoryUserProvider
  • 27. SymfonyComponentSecurityCoreAuthentication 27Auth provider Provider DaoAuthenticationProvider - userProvider - encoderFactory - userChecker SymfonyComponentSecurityCoreEncoder EncoderFactoryInterface + getEncoder($user): PasswordEncoderInterface PasswordEncoderInterface + encodePassword($raw, $salt) + isPasswordValid($encoded, $raw, $salt) - cost: int BCryptPasswordEncoder - encoders: array EncoderFactory
  • 28. SymfonyComponentSecurityCoreAuthentication 28Auth provider Provider DaoAuthenticationProvider AuthenticationManagerInterface + authenticate(TokenInterface $token) SymfonyComponentSecurityCoreUser UserChecker + checkPreAuth(UserInterface $user) + checkPostAuth(UserInterface $user) UserCheckerInterface - userProvider - encoderFactory - userChecker
  • 29. 29Auth provider use SymfonyComponentSecurityCoreAuthenticationAuthenticationManagerInterface; class MainSecurityListener implements ListenerInterface { /** @var AuthenticationManagerInterface */ private $authenticationManager; public function handle(GetResponseEvent $event) { // Extract credentials from request... if ($username && $credentials) { try { // Token is not authenticated because no role is passed. $token = new UsernamePasswordToken($username, $credentials, 'main'); // Try to authenticate the token. // If there is an authentication error an AuthenticationException is thrown. $token = $this->authenticationManager->authenticate($token); // Add authenticated token to storage. $this->tokenStorage->setToken($token); } catch (AuthenticationException $e) { } } } }
  • 30. use SymfonyComponentSecurityCoreUserInMemoryUserProvider; use SymfonyComponentSecurityCoreAuthenticationProviderDaoAuthenticationProvider; use SymfonyComponentSecurityCoreEncoderEncoderFactory; use SymfonyComponentSecurityCoreUserUser; use SymfonyComponentSecurityCoreEncoderBCryptPasswordEncoder; // Create user provider that will be used by authentication listener. $mainUserProvider = new InMemoryUserProvider([ 'gordon' => [ 'password' => '$2y$10$50MJW4ov/LHLBdl6uYsxI.7MdWYoJ8K1MqBXfG677nOXbsSVVue6i', 'roles' => ['ROLE_USER'], 'enabled' => true, ], ]); // Service that checks whether a user is non-locked, enabled, not expired, etc. $mainUserChecker = new SymfonyComponentSecurityCoreUserUserChecker(); // A factory that specifies encoding algorithm to each user class. $encoderFactory = new EncoderFactory([User::class => new BCryptPasswordEncoder(10)]); // Create a provider to which security listener will delegate an authentication. $mainAuthProvider = new DaoAuthenticationProvider( $mainUserProvider, $mainUserChecker, 'main', $encoderFactory ); // Create main security listener that handles authentication. $mainSecurityListener = new AppSecurityMainSecurityListener($tokenStorage, $mainAuthProvider); 30Auth provider
  • 31. 31Auth provider # config/packages/security.yaml security: providers: in_memory: memory: # returns SymfonyComponentSecurityCoreUserUser object users: gordon: password: freeman roles: 'ROLE_USER' g-man: password: bureaucrat roles: 'ROLE_EMPLOYER' encoders: SymfonyComponentSecurityCoreUserUser: algorithm: bcrypt cost: 10
  • 32. 32HTTP basic auth Mettre en place l’authentification HTTP, laisser passer seulement les utilisateurs connectés.Tâche 6 SymfonyComponentSecurityHttpFirewall - tokenStorage - authenticationManager BasicAuthenticationListener - tokenStorage - accessDecisionManager AccessListener RequestMatcher - path: ^/main => Extraire l’identifiant et le mot de passe de l'en-tête Authorization. Créer le token, l'authentifier, le sauvegarder dans token storage. Lancer une exception si les credentials ne sont pas valides. Lancer une exception si le token n’est pas présent ou s’il ne respecte pas les règles d’accès.
  • 33. 33 SymfonyComponentSecurityHttpEntryPoint + start(Request $request, $authException): Response AuthenticationEntryPointInterface - realmName: string BasicAuthenticationEntryPoint Lors de l'exception d’authentification (accès anonyme ou identifiants non valides) il faut aider l’utilisateur à (re-)commencer l’authentification. SymfonyComponentSecurityHttpFirewall - tokenStorage - authenticationManager - authenticationEntryPoint BasicAuthenticationListener EventDispatcher - Kernel::EXCEPTION => [...] - authenticationEntryPoint ExceptionListener HTTP basic auth
  • 34. 34HTTP basic auth // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpAccessMap; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewallBasicAuthenticationListener; use SymfonyComponentSecurityHttpFirewallAccessListener; use SymfonyComponentSecurityHttpEntryPointBasicAuthenticationEntryPoint; use SymfonyComponentSecurityCoreAuthorizationAccessDecisionManager; // ... // Entry point helps user to authenticate. $basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint('Black mesa'); // Create HTTP basic security listener that extracts credentials from headers (RFC 7617). $mainSecurityListener = new BasicAuthenticationListener( $tokenStorage, $mainAuthProvider, 'main', $basicAuthenticationEntryPoint ); $accessDecisionManager = new AccessDecisionManager(); $accessMap = new AccessMap(); // Access listener will throw an exception when no token is already present. $accessListener = new AccessListener( $tokenStorage, $accessDecisionManager, $accessMap, $mainAuthProvider ); // ...
  • 35. 35HTTP basic auth // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewallExceptionListener; use SymfonyComponentSecurityCoreAuthenticationAuthenticationTrustResolver; use SymfonyComponentSecurityCoreAuthenticationTokenAnonymousToken; use SymfonyComponentSecurityCoreAuthenticationTokenRememberMeToken; // ... // ExceptionListener catches authentication exception and converts them to Response instance. // In this case it invites user to enter its credentials by returning 401 response. $authTrustResolver = new AuthenticationTrustResolver(AnonymousToken::class, RememberMeToken::class); $mainExceptionListener = new ExceptionListener( $tokenStorage, $authTrustResolver, $httpUtils, 'main', $basicAuthenticationEntryPoint ); // Create firewall map and add main security listener under URLs starting with "/main". $firewallMap = new FirewallMap(); $firewallMap->add( new RequestMatcher('^/main’), [$mainSecurityListener, $accessListener], $mainExceptionListener ); // ...
  • 36. 36HTTP basic auth # config/packages/security.yaml security: firewalls: half_life: pattern: ^/lambda host: half-life.com http_basic: realm: "Lambda Complex"
  • 37. 37Formulaire de connexion Mettre en place l’authentification par le formulaire de connexion pour une autre partie de site.Tâche 7 SymfonyComponentSecurityHttpFirewall - tokenStorage - userProviders ContextListener - tokenStorage - accessDecisionManager - options - successHandler - failureHandler UsernamePasswordFormAuthenticationListener RequestMatcher - path: ^/front => + handle(GetResponseEvent $event) + onKernelResponse(FilterResponseEvent $event) + handle(GetResponseEvent $event) Récupérer le token d’une session lors de l’événement REQUEST. Sauvegarder le token dans une session lors de l’événement RESPONSE. Authentifier l’utilisateur seulement quand le formulaire de connexion est envoyé (POST sur /front/login_check).
  • 38. 38Formulaire de connexion Nouvelle action pour visualiser le formulaire de conexion : POST sur /front/login_check. namespace App; class Controller { public function loginFormAction() { return new Response(<<<END <form action="/front/login_check" method="POST"> <input type="text" name="_username" placeholder="username"> <input type="password" name="_password" placeholder="password"> <input type="submit"> </form> END ); } public function defaultAction() { $token = $this->tokenStorage->getToken(); $user = $token ? $token->getUser() : null; // ... } }
  • 39. 39Formulaire de connexion La nouvelle action sera appelée quand la requête est faite sur /font/login. namespace App; use SymfonyComponentHttpFoundationRequest; use SymfonyComponentHttpKernelControllerControllerResolverInterface; class ControllerResolver implements ControllerResolverInterface { /** @var callable[] */ private $routes; /** @var callable */ private $default; public function getController(Request $request) { foreach ($this->routes as $pattern => $controller) { if (preg_match($pattern, $request->getPathInfo())) { return $controller; } } return $this->default; } }
  • 40. 40Formulaire de connexion La nouvelle action sera appelée quand la requête est faite sur /font/login. // public/index.php use SymfonyComponentEventDispatcherEventDispatcher; use SymfonyComponentHttpKernelHttpKernel; // ... $dispatcher = new EventDispatcher(); // Controller creates a response to send to the user. $controller = new AppController($request, $tokenStorage); $controllerResolver = new AppControllerResolver( ['/^/front/login$/' => [$controller, 'loginFormAction']], [$controller, 'defaultAction'] ); // Kernel is in charge of converting a Request into a Response by using the event dispatcher. $kernel = new HttpKernel($dispatcher, $controllerResolver); // ...
  • 41. 41Formulaire de connexion Context security listener : // public/index.php use SymfonyComponentSecurityHttpFirewallContextListener; // ... // ContextListener retrieves previously authenticated token from the session during REQUEST event. // It also saves token during RESPONSE event. $contextListener = new ContextListener( $tokenStorage, [$mainUserProvider], 'front', null, $dispatcher ); // ...
  • 42. 42Formulaire de connexion use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationSuccessHandler; use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationFailureHandler; use SymfonyComponentSecurityHttpFirewallUsernamePasswordFormAuthenticationListener; use SymfonyComponentSecurityHttpSessionSessionAuthenticationStrategy; $sessionAuthenticationStrategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE); $successHandler = new DefaultAuthenticationSuccessHandler( $httpUtils, ['default_target_path' => '/front/success’] ); $failureHandler = new DefaultAuthenticationFailureHandler( $kernel, $httpUtils, ['login_path' => '/front/login’] ); // Listens for login form being send (POST to '/front/login_check'). // It extracts credentials, creates token, authenticates it and puts it to the token storage. $formAuthListener = new UsernamePasswordFormAuthenticationListener( $tokenStorage, $frontAuthProvider, // The same authentication provider as for HTTP basic (except 'key'='front'). $sessionAuthenticationStrategy, $httpUtils, 'front', $successHandler, // Redirect user to '/front/success' if credentials are valid $failureHandler, // Redirect user to '/front/login' if credentials are invalid ['check_path' => '/front/login_check', 'post_only' => true] // Act only on POST to '/front/login_check' );
  • 43. 43Formulaire de connexion Ajout de security listeners dans le Firewall : // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewall; // ... // Create firewall map $firewallMap = new FirewallMap(); // Add basic http security listener under URLs starting with "/main". $firewallMap->add( new RequestMatcher('^/main'), [$mainSecurityListener, $accessListener], $mainExceptionListener ); // Add login form security listeners under URLs starting with "/front". $firewallMap->add(new RequestMatcher('^/front'), [$contextListener, $formAuthListener]); // Create firewall and add it to dispatcher. $firewall = new Firewall($firewallMap, $dispatcher); $dispatcher->addSubscriber($firewall); // ...
  • 44. SymfonyComponentSecurityCoreAuthorization 44Formulaire de connexion Vérifier les rôles d’utilisateurs avant de les autoriser à accéder aux certains URLs.Tâche 8 - voters : VoterInterface[] + decide($token, $attributes, $object) AuthorizationChecker - tokenStorage - accessDecisionManager + isGranted($attributes, $object) AccessDecisionManager Voter + vote($token, $subject, $attributes) VoterInterface RoleVoter AuthenticatedVoter ROLE_* IS_AUTHENTICATED_FULLY IS_AUTHENTICATED_REMEMBERED IS_AUTHENTICATED_ANONYMOUSLY
  • 45. SymfonyComponentSecurityHttp 45Formulaire de connexion AccessMap + add($requestMatcher, $attributes, $channel) + getPatterns(Request $request): array - map: array # config/security.yaml security: access_control: - { path: ^/main, roles: ROLE_SCIENTIST } - { path: ^/front/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/front, roles: ROLE_EMPLOYER } // public/index.php // Access map defines authorization rules, it maps request to attributes. // It helps access listeners to determine the attributes the user must possess. $accessMap = new AccessMap(); $accessMap->add(new RequestMatcher('^/main'), ['ROLE_SCIENTIST']); $accessMap->add(new RequestMatcher('^/front/login$'), ['IS_AUTHENTICATED_ANONYMOUSLY']); $accessMap->add(new RequestMatcher('^/front'), ['ROLE_EMPLOYER’]); //... Access map renvoi les attributs que l’utilisateur doit posséder :
  • 46. 46Formulaire de connexion AccessListener + handle(GetResponseEvent $event) - tokenStorage - authManager - accessDecisionManager - map Access map renvoi les attributs que l’utilisateur doit posséder : SymfonyComponentSecurityHttp AccessMapInterface + getPatterns(Request $request): array SymfonyComponentSecurityCoreAuthorization + decide($token, $attributes, $object) AccessDecisionManager
  • 47. 47Formulaire de connexion // public/index.php use SymfonyComponentSecurityCoreAuthorizationVoterAuthenticatedVoter; use SymfonyComponentSecurityCoreAuthorizationVoterRoleVoter; use SymfonyComponentSecurityCoreAuthorizationAccessDecisionManager; // ... // RoleVoter can determine if authenticated user has necessary roles // like 'ROLE_SCIENTIST' or 'ROLE_EMPLOYER'. $roleVoter = new RoleVoter(); // AuthenticatedVoter can determine if token is anonymous or fully authentified. $authenticatedVoter = new AuthenticatedVoter($authTrustResolver); // Access decision manager verifies authorisation of authentified token thanks to voters. $accessDecisionManager = new AccessDecisionManager([$roleVoter, $authenticatedVoter]); // ...
  • 48. 48Formulaire de connexion // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpAccessMap; use SymfonyComponentSecurityCoreUserInMemoryUserProvider; // Access map defines authorization rules, it maps request to attributes. // It helps access listeners to determine the attributes the user must possess. $accessMap = new AccessMap(); $accessMap->add(new RequestMatcher('^/main'), ['ROLE_SCIENTIST']); $accessMap->add(new RequestMatcher('^/front/login$'), ['IS_AUTHENTICATED_ANONYMOUSLY']); $accessMap->add(new RequestMatcher('^/front'), ['ROLE_EMPLOYER']); // Create user provider that will be used by authentication listener. $mainUserProvider = new InMemoryUserProvider([ 'gordon' => [ 'password' => '$2y$10$50MJW4ov/LHLBdl6uYsxI.7MdWYoJ8K1MqBXfG677nOXbsSVVue6i', 'roles' => ['ROLE_SCIENTIST'], ], 'g-man' => [ 'password' => '$2y$10$.23HMg6E0qsMXYcscJyJBOVFzSC31aWY8wd3CHJeO86dRljos0zie', 'roles' => ['ROLE_EMPLOYER'], ], ]); // ...
  • 49. 49Formulaire de connexion // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallAccessListener; // ... // Access listener will throw an exception when no token is already present. $mainAccessListener = new AccessListener( $tokenStorage, $accessDecisionManager, $accessMap, $mainAuthProvider ); // Add basic http security listener under URLs starting with "/main". $firewallMap->add( new RequestMatcher('^/main’), [$mainSecurityListener, $mainAccessListener], $mainExceptionListener ); // ...
  • 50. 50Formulaire de connexion // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallAccessListener; // ... // Access listener will throw an exception when no token is already present. $frontAccessListener = new AccessListener( $tokenStorage, $accessDecisionManager, $accessMap, $frontAuthProvider ); // Add login form security listeners under URLs starting with "/front". $firewallMap->add( new RequestMatcher('^/front’), [$contextListener, $formAuthListener, $frontAnonListener, $frontAccessListener], $frontExceptionListener ); // ...
  • 51. Merci pour votre attention Le code de cette présentation : https://github.com/vria/symfony-security-component-use