Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Guard dans la vraie vie

Guard dans la vraie vie

SymfonyLive Paris 2016

More Decks by jeremyFreeAgent (Jérémy Romey)

Other Decks in Programming

Transcript

  1. View Slide

  2. Guard

    dans la vraie vie
    SymfonyLive Paris 2016

    View Slide

  3. @jeremyFreeAgent
    Tony Danza @ .
    PHP Symfony
    Lean Startup
    Scrum
    ☀ From Marseille, lives in Paris ❤
    Restaurants
    Meet new people
    Je n’ai pas de chat mais j’ai un BB-8 — Il n’a ni Twitter ni Instagram
    T’es qui toi ?!

    View Slide

  4. View Slide

  5. Symfony Security Component - Guard
    symfony/security-guard

    ├── php >=5.5.9
    ├── symfony/security-core ~2.8|~3.0

    └── symfony/security-http ~2.8|~3.0

    View Slide

  6. Que fait Guard
    de plus ?

    View Slide

  7. Rien.

    View Slide

  8. View Slide

  9. Approche business

    View Slide

  10. Que veut-on ?
    Approche business

    View Slide

  11. Faciliter
    l’authentification
    Approche business

    View Slide

  12. Compliqué… (un peu)

    View Slide

  13. Beaucoup de
    classes
    Compliqué… (un peu)

    View Slide

  14. ListenerInterface
    AuthenticationProviderInterface
    SecurityFactoryInterface
    Compliqué… (un peu)

    View Slide

  15. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)

    View Slide

  16. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)

    View Slide

  17. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)

    View Slide

  18. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    UserProvider
    Récupération de
    l’utilisateur

    View Slide

  19. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    UserProvider
    Récupération de
    l’utilisateur

    View Slide

  20. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur

    View Slide

  21. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur

    View Slide

  22. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur

    View Slide

  23. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur

    View Slide

  24. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur
    Authentifié !

    View Slide

  25. Et Guard du coup ?!

    View Slide

  26. Une

    seule classe
    Et Guard du coup ?!

    View Slide

  27. GuardAuthenticatorInterface
    Et Guard du coup ?!

    View Slide

  28. interface
    GuardAuthenticatorInterface
    extends
    AuthenticationEntryPointInterface
    Et Guard du coup ?!

    View Slide

  29. Les classes qui
    restent comme
    avant
    Et Guard du coup ?!

    View Slide

  30. TokenInterface
    UserInterface
    UserProviderInterface
    Et Guard du coup ?!

    View Slide

  31. Concrètement…

    View Slide

  32. Une classe :
    toutes les étapes
    Concrètement…

    View Slide

  33. start()
    Response $response
    Besoin d’être authentifié ?
    Concrètement…

    View Slide

  34. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur
    Authentifié !

    View Slide

  35. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur
    Authentifié !
    1
    2
    3
    4

    View Slide

  36. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur
    Authentifié !
    1
    2
    3
    4

    View Slide

  37. getCredentials()
    $credentials
    Request $request
    Concrètement…
    1

    View Slide

  38. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur
    Authentifié !
    1
    2
    3
    4

    View Slide

  39. getUser()
    UserInterface $user
    $credentials
    Concrètement…
    2

    View Slide

  40. getUser()
    UserInterface $user
    $credentials
    Concrètement…

    ASTUCE
    Utiliser une
    UsernameNotFoundException
    et ne pas renvoyer null

    pour avoir plus d’info de debug.
    2

    View Slide

  41. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur
    Authentifié !
    1
    2
    3
    4

    View Slide

  42. checkCredentials()
    bool
    UserInterface $user $credentials

    Concrètement…
    3

    View Slide

  43. checkCredentials()
    bool
    UserInterface $user $credentials

    Concrètement…

    ASTUCE
    Utiliser une
    BadCredentialsException

    et ne pas renvoyer false

    pour avoir plus d’info de debug.
    3

    View Slide

  44. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur
    Authentifié !
    1
    2
    3
    4

    View Slide

  45. createAuthenticatedToken()
    TokenInterface $authenticatedToken
    UserInterface $user
    Concrètement…
    4

    View Slide

  46. createAuthenticatedToken()
    TokenInterface $authenticatedToken
    UserInterface $user
    Concrètement…
    4

    ASTUCE
    Il est possible d’étendre la classe
    AbstractGuardAuthenticator
    pour ne pas avoir implémenter

    cette méthode.

    View Slide

  47. SecurityEvents::INTERACTIVE_LOGIN
    Concrètement…
    4

    View Slide

  48. SecurityEvents::INTERACTIVE_LOGIN
    Concrètement…

    ASTUCE
    Déjà présent dans Symfony, on peut
    utiliser cet event pour : logger la date de
    connexion par exemple.
    4

    View Slide

  49. onAuthenticationSuccess()
    Response $response
    Request $request TokenInterface $token

    Concrètement…
    4

    View Slide

  50. Cookie de remember_me
    Concrètement…
    4

    View Slide

  51. Pourtant l’authentification c’est simple :
    Compliqué… (un peu)
    Credentials

    (username + password)
    User
    UserProvider
    Récupération de
    l’utilisateur
    PasswordEncoder
    Vérification du mot de
    passe de l’utilisateur
    Authentifié !
    1
    2
    3
    4

    View Slide

  52. namespace Symfony\Component\Security\Guard;
    interface GuardAuthenticatorInterface
    extends AuthenticationEntryPointInterface
    {
    function getCredentials();
    function getUser(, );
    function checkCredentials(, );
    function createAuthenticatedToken(, );
    function onAuthenticationFailure(, );
    function onAuthenticationSuccess(, , );
    function supportsRememberMe();
    }
    Concrètement…

    View Slide

  53. interface
    GuardAuthenticatorInterface
    extends
    AuthenticationEntryPointInterface
    Concrètement…

    View Slide

  54. namespace Symfony\Component\Security\Http\EntryPoint;
    interface AuthenticationEntryPointInterface
    {
    function start(, = null);
    }
    Concrètement…

    View Slide

  55. Un (tout petit)
    peu de config !
    Concrètement…

    View Slide

  56. #app/config/services.yml
    services:
    app.authenticator.form:
    class: Security\FormGuardAuthenticator
    Concrètement…

    View Slide

  57. #app/config/security.yml
    security:
    firewalls:
    main:
    pattern: ^/
    guard:

    authenticators:
    - app.authenticator.form
    Concrètement…

    View Slide

  58. #app/config/security.yml
    security:
    firewalls:
    main:
    pattern: ^/
    guard:

    authenticators:
    - app.authenticator.form
    Concrètement…

    View Slide

  59. #app/config/security.yml
    security:
    firewalls:
    main:
    pattern: ^/
    guard:

    authenticators:
    - app.authenticator.form
    - app.authenticator.sl_connect
    Concrètement…

    View Slide

  60. #app/config/security.yml
    security:
    firewalls:
    main:
    pattern: ^/
    guard:

    authenticators:
    - app.authenticator.form
    - app.authenticator.sl_connect
    - app.authenticator.facebook
    Concrètement…

    View Slide

  61. #app/config/security.yml
    security:
    firewalls:
    main:
    pattern: ^/
    guard:

    authenticators:
    - app.authenticator.form
    - app.authenticator.sl_connect
    - app.authenticator.facebook
    - app.authenticator.banana
    Concrètement…

    View Slide

  62. #app/config/security.yml
    security:
    firewalls:
    main:
    pattern: ^/
    guard:

    authenticators:
    - app.authenticator.form
    - app.authenticator.sl_connect
    - app.authenticator.facebook
    - app.authenticator.banana
    entry_point: app.authenticator.form
    Concrètement…

    View Slide

  63. #app/config/security.yml
    security:
    firewalls:
    main:
    pattern: ^/
    guard:

    authenticators:
    - app.authenticator.form
    - app.authenticator.sl_connect
    - app.authenticator.facebook
    - app.authenticator.banana
    entry_point: app.authenticator.form
    Concrètement…

    View Slide

  64. #app/config/security.yml
    security:
    firewalls:
    main:
    pattern: ^/
    guard:

    authenticators:
    - app.authenticator.form
    - app.authenticator.sl_connect
    - app.authenticator.facebook
    - app.authenticator.banana
    entry_point: app.authenticator.form
    Concrètement…

    AIDE
    Option entry_point permet de dire
    quel authenticator sera utilisé pour
    lancer la méthode start().

    View Slide

  65. Exemples

    View Slide

  66. Authentification
    via un token
    dans l’URL
    Exemples

    View Slide

  67. public function getCredentials(Request $request)
    {
    return $request->query->get('token', null);
    }
    Exemples

    View Slide

  68. public function getUser
    ($credentials, UserProviderInterface $userProvider)
    {
    return $userProvider->findByToken($credentials);
    }
    Exemples

    View Slide

  69. public function checkCredentials
    ($credentials, UserInterface $user)
    {
    return true;
    }
    Exemples

    View Slide

  70. OAuth avec

    SensioLabs
    Connect
    Exemples

    View Slide

  71. $ composer require sensiolabs/connect
    Exemples

    View Slide

  72. public function start
    (Request $request, AuthenticationException $exception = null)
    {
    $url = $this->client->getAuthorizationUri(
    'https://banana.com/connect/callback'
    );
    return new RedirectResponse($url);
    }
    Exemples

    View Slide

  73. public function getCredentials(Request $request)
    {
    if ('/connect/callback' != $request->getPathInfo()) {
    return;
    }
    return $this->client->requestAccessToken(
    'https://banana.com/connect/callback',
    $request->get('code')
    );
    }
    Exemples

    View Slide

  74. public function getUser
    ($credentials, UserProviderInterface $userProvider)
    {
    return $userProvider->findOrCreate($credentials);
    }
    Exemples

    View Slide

  75. public function checkCredentials($credentials, UserInterface $user)
    {
    return true;
    }
    Exemples

    View Slide

  76. Des trucs cools qu’on
    peut faire avec Guard

    View Slide

  77. Systèmes
    d’authentification
    différents par
    marque blanche
    Des trucs cools qu’on peut faire avec Guard

    View Slide

  78. Des trucs cools qu’on peut faire avec Guard
    1 application,
    3 marques blanches:
    banane.com

    pomme.com

    ananas.com

    View Slide

  79. banane.com
    Des trucs cools qu’on peut faire avec Guard
    Username:
    Password:
    LO G I N

    View Slide

  80. pomme.com
    Des trucs cools qu’on peut faire avec Guard
    Phone:
    Password:
    LO G I N

    View Slide

  81. ananas.com
    Des trucs cools qu’on peut faire avec Guard
    Username:
    Password:
    LO G I N
    Phone:

    View Slide

  82. Des trucs cools qu’on peut faire avec Guard
    3
    GuardAuthenticators

    View Slide

  83. Des trucs cools qu’on peut faire avec Guard
    banane.com
    Username:
    Password:
    LO G I N

    View Slide

  84. public function getCredentials(Request $request)
    {
    if ('banane.com' != $request->getHost()) {
    return;
    }
    return [
    'username' => $request->request->get('_username'),
    'password' => $request->request->get('_password'),
    ];
    }
    Des trucs cools qu’on peut faire avec Guard

    View Slide

  85. pomme.com
    Des trucs cools qu’on peut faire avec Guard
    Phone:
    Password:
    LO G I N

    View Slide

  86. public function getCredentials(Request $request)
    {
    if ('pomme.com' != $request->getHost()) {
    return;
    }
    return [
    'phone' => $request->request->get('_phone'),
    'password' => $request->request->get('_password'),
    ];
    }
    Des trucs cools qu’on peut faire avec Guard

    View Slide

  87. ananas.com
    Des trucs cools qu’on peut faire avec Guard
    Username:
    Password:
    LO G I N
    Phone:

    View Slide

  88. public function getCredentials(Request $request)
    {
    if ('ananas.com' != $request->getHost()) {
    return;
    }
    return [
    'username' => $request->request->get('_username'),
    'phone' => $request->request->get('_phone'),
    'password' => $request->request->get('_password'),
    ];
    }
    Des trucs cools qu’on peut faire avec Guard

    View Slide

  89. Modifier un
    utilisateur lors de
    tests fonctionnels
    Des trucs cools qu’on peut faire avec Guard

    View Slide

  90. $client = static::createClient([], [
    'PHP_AUTH_USER' => 'username',
    'PHP_AUTH_PW' => 'pa$$word',
    ]);
    # app/config/config_test.yml
    security:
    firewalls:
    your_firewall_name:
    http_basic: ~
    Des trucs cools qu’on peut faire avec Guard
    Vous connaissez cette technique…

    View Slide

  91. $client = static::createClient([], [
    'PHP_AUTH_USER' => 'username',
    'PHP_AUTH_PW' => 'pa$$word',
    ]);
    $client->request('/blog/mon-meilleur-article/edit');
    $this->assertSame(200, $client->getResponse()->getStatusCode());
    $client = static::createClient([], [
    'PHP_AUTH_USER' => 'username',
    'PHP_AUTH_PW' => 'pa$$word',
    'HTTP_X_AUTH_ID' => '2823a077-c587-4a43-b2d7-39b1238787bc',
    ]);
    $client->request('/blog/mon-meilleur-article/edit');
    $this->assertSame(403, $client->getResponse()->getStatusCode());
    Des trucs cools qu’on peut faire avec Guard

    View Slide

  92. $client = static::createClient([], [
    'PHP_AUTH_USER' => 'username',
    'PHP_AUTH_PW' => 'pa$$word',
    ]);
    $client->request('/admin');
    $this->assertSame(403, $client->getResponse()->getStatusCode());
    $client = static::createClient([], [
    'PHP_AUTH_USER' => 'username',
    'PHP_AUTH_PW' => 'pa$$word',
    'HTTP_X_AUTH_ROLES' => 'ROLE_ADMIN-ROLE_USER',
    ]);
    $client->request('/admin');
    $this->assertSame(200, $client->getResponse()->getStatusCode());
    Des trucs cools qu’on peut faire avec Guard

    View Slide

  93. Des trucs cools qu’on peut faire avec Guard
    public function getCredentials(Request $request)
    {
    if (!$request->headers->has('PHP_AUTH_USER')) {
    return;
    }
    return [
    'username' => $request->headers->get('PHP_AUTH_USER'),
    'password' => $request->headers->get('PHP_AUTH_PW'),
    'id' => $request->headers->get('X_AUTH_ID'),
    'roles' => explode(
    '-',
    $request->headers->get('X_AUTH_ROLES')
    ),
    ];
    }

    View Slide

  94. Des trucs cools qu’on peut faire avec Guard
    public function getUser
    ($credentials, UserProviderInterface $userProvider)
    {
    return $userProvider->load($credentials);
    }

    View Slide

  95. Des trucs cools qu’on peut faire avec Guard
    # app/config/config_test.yml
    services:
    app.security.authenticator.test.http_header:
    class: Security\HttpHeaderTestGuardAuthenticator
    security:
    firewalls:
    your_firewall_name:
    guard:
    authenticators:
    - 'app.security.authenticator.test.http_header'

    View Slide

  96. Migrer vers Guard

    View Slide

  97. Bah pourquoi ? ©
    Migrer vers Guard

    View Slide

  98. Facile
    à comprendre
    Migrer vers Guard

    View Slide

  99. Facile
    à ajouter
    Migrer vers Guard

    View Slide

  100. Facile
    à maintenir
    Migrer vers Guard

    View Slide

  101. Facile

    à tester
    Migrer vers Guard

    View Slide

  102. Moins de
    dépendances
    vers des bundles
    Migrer vers Guard

    View Slide

  103. Trop de
    puissance !
    Migrer vers Guard

    View Slide

  104. Guard

    c’est:
    simple et puissant
    c’est cool

    View Slide

  105. Guard

    c’est:
    simple et puissant
    c’est cool

    View Slide

  106. Guard

    c’est:
    simple et puissant
    c’est cool

    View Slide

  107. Merci <3

    View Slide

  108. Questions ?

    View Slide

  109. View Slide