Skip to content

[Pre-Draft][WIP] Started rewriting Security component docs #5463

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 229 additions & 0 deletions components/security/core/authentication.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
.. index::
single: Security, Core Authentication

Security Core: Authentication
=============================

As you've :ref:`already learned <components-security-terminology>`, the first
step in the Security system is authentication, answering the question: **Who
are you?**

Authentication Manager
----------------------

This question is answered by an
:class:`authentication manager <Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationManagerInterface>`.
This class recieves a token containing the information available about the
visitor of your application. Based on this information, it tries to determine
the visitor and returns an authenticated token. If it can't authenticate the
user, an
:class:`Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException`
is thrown. This exception can the be transformed into a redirect to the login
form, for example.

Using the authentication manager, authenticating a user becomes very simple (no
worries, you'll fill the missing variables within a couple of minutes)::

use Symfony\Component\Security\Core\Exception\AuthenticationException;

try {
$authenticatedToken = $authManager->authenticate($unauthenticatedToken);
} catch (AuthenticationException $e) {
// ... authentication failed, do something
}

The Security component comes with one very flexible authentication manager, the
:class:`Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationProviderManager`.
This uses authentication providers to authenticate a token.

.. _component-security-core-authentication-providers:

Authentication Providers
~~~~~~~~~~~~~~~~~~~~~~~~

One ``AuthenticationProviderManager`` can have multiple
:class:`authentication providers <Symfony\\Component\\Security\\Core\\Authentication\\Provider\\AuthenticationProviderInterface>`.
Using the ``supports()`` method, providers determines if they can authenticate
the passed token.

The most simple authentication provider is the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph needs some additional explanation about how can this auth provider possibly exist. Why do we need to authenticate anonymous users?

``AnonymousAuthenticationProvider``. This providers "authenticates" an
``AnonymousToken``. Anonymous users are guests, they aren't registered for the
application, but they are still authenticated.

.. code-block:: php

// ...
use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
use Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;

$anonToken = new AnonymousToken('a_custom_key', 'Guest'.uniqid());

// 'a_custom_key' has to match the 1st argument of AnonymousToken.
$anonymousAuthProvider = new AnonymousAuthenticationProvider('a_custom_key');

$authManager = new AuthenticationProviderManager(array(
$anonymousAuthProvider,
));

try {
$authenticatedToken = $authManager->authenticate($unauthenticatedToken);
} catch (AuthenticationException $e) {
// ... authentication failed, do something
}

// user is authenticated as a guest

In this example, each requests to the application will result in an
authenticated anonymous token with different names starting with ``Guest``.

The DaoAuthenticationProvider (Data Access Object)
..................................................

This authentication provider is one of the most common authentication
providers. It'll authenticate an ``UsernamePasswordToken``, retrieve the user,
check the password and then return an authenticated ``UsernamePasswordToken``
containing the user object. That's quite a lot, the following paragraphs each
explain one of these steps.

The first step is to retrieve the user. The dao provider does this with the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dao -> DAO

help of a
:class:`user provider <Symfony\\Component\\Security\\Core\\User\\UserProviderInterface>`.
This can provide users from a database for example. The most basic user
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can provide users from a database ... --> It can fetch users from a database ...

provider is the ``InMemoryUserProvider``, which provides users from an array::

use Symfony\Component\Security\Core\User\InMemoryUserProvider;

$userProvider = new InMemoryUserProvider(array(
'wouter' => array('password' => 'pa$$'),
));

After the user is retrieved, the dao provider checks if the password from the
token and the user provided by the user provider (based on its username) are
the same. It does this with the help of a
:class:`password encoder <Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface>`.
This encodes the password in the token in the same way as the password was
encoded during registration and then compares the two. As the password was
saved in plain text (for demostration purposes), you're going to need the
``PlaintextPasswordEncoder``.

In order to be able to authenticate different types of users, using different
encoding strategies, you'll pass an ``EncoderFactory`` instance. This factory
is configured with the correct encoder for the correct user type.

.. code-block:: php

use Symfony\Component\Security\Core\Encoder\EncoderFactory;
use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;

$encoderFactory = new EncoderFactory(array(
// this is the FQCN to the user object used by the in memory user provider
'Symfony\Component\Security\Core\User\User' => new PlaintextPasswordEncoder(),
));

Now the user is retrieved and matched against the submitted password, the dao
provider has to do some final checks. For instance, if the user is not banned
or if the account is not expired. Such checks are done by
:class:`user checkers <Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface>`::

use Symfony\Component\Security\Core\User\UserChecker;

$userChecker = new UserChecker();

Everything is now set-up and ready to be combined into the dao authentication
provider!

.. code-block::

use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider;
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\UserChecker;

$userProvider = new InMemoryUserProvider(array(
'wouter' => array('password' => 'pa$$'),
));

$encoderFactory = new EncoderFactory(array(
// this is the FQCN to the user object used by the in memory user provider
'Symfony\Component\Security\Core\User\User' => new PlaintextPasswordEncoder(),
));

$userChecker = new UserChecker();

$daoAuthProvider = new DaoAuthenticationProvider(
$userProvider,
$userChecker,
'default', // used to group multiple providers
$encoderFactory
);

You can now inject the dao authentication provider in your authentication
manager::

// ...
$anonymousAuthProvider = new AnonymousAuthenticationProvider('a_custom_key');

$authManager = new AuthenticationProviderManager(array(
$daoAuthProvider,
$anonymousAuthProvider,
));

Now, you can test this out. As both the dao and anonymous authentication
providers are configured, you can now authenticate an anonymous user as well as
a real member::

// ...
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

$token = new UsernamePasswordToken(
'wouter', // username
'pa$$', // password
'default' // provider key (used to determine which providers are targetted)
);

try {
$authenticatedToken = $authManager->authenticate($token);
} catch (AuthenticationException $e) {
// ... bummer, user submitted a wrong username/password or has not been registered
}

// ... user is authenticated and a real member!

Other Authentication Providers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is that readers expect these three auth providers to be explained in detail as the previous ones.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that'll make this article a bit long. It already has enough stuff to make your head spin if you're new to it.

However, I will talk about them in more detail on other locations of the component docs and add a reference to it here. For instance, RememberMe becomes very nice when using the HTTP component and SimpleAuthenticationProvider and UserAuthenticationProvider should be documented in some "advanced extending" article in the future.

..............................

The component contains some other authentication providers:

:class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\RememberMeAuthenticationProvider`
This can authenticate a
:class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken`,
which can be used to be automatically logged in again after the current
session expired.

:class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\SimpleAuthenticationProvider`
This authentication provider provides a simple way to customize the
authentication process. You use this provider to implement a custom way to
authenticate.

:class:`Symfony\\Component\\Security\\Core\\Authentication\\Provider\\UserAuthenticationProvider` (abstract)
This is a base class for authentication providers dealing with the
``UsernamePasswordToken`` (like the dao provider).

Wrapping Up
-----------

This chapter, you've implemented a very simple authentication part of the
Security system. As you've probably seen a lot of new stuff, this is a good
moment to recap what you've learned:

#. Authentication is done by an *authentication manager*
#. The authentication manager uses *authentication provider* to transform and
*unauthenticated token* into an authenticated one.
#. The *dao authentication provider* is commonly used. It's behaviour can be
customized by implementing custom *user providers*, *user checkers* and
*password encoders*.
#. Other authentication providers are the *anonymous*, *rembember me* and
*simple* providers.
7 changes: 7 additions & 0 deletions components/security/core/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Security Core
=============

.. toctree::
:maxdepth: 2

authentication
6 changes: 2 additions & 4 deletions components/security/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@ Security
:maxdepth: 2

introduction
firewall
authentication
authorization
secure_tools
core/index
secure_tools
97 changes: 87 additions & 10 deletions components/security/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
The Security Component
======================

The Security component provides a complete security system for your web
application. It ships with facilities for authenticating using HTTP basic
or digest authentication, interactive form login or X.509 certificate
login, but also allows you to implement your own authentication strategies.
Furthermore, the component provides ways to authorize authenticated users
based on their roles, and it contains an advanced ACL system.

The Security component provides a complete security system for your
application. It's flexible enough to solve the most basic security needs
(form login or HTTP basic/digest), but also to serve as a complex security
system (X.509 certificate or custom authentication systems). Furthermore,
the component provides ways to authorize authenticated users based on their
roles or using an advanced ACL system.

Installation
------------
Expand All @@ -21,12 +22,88 @@ You can install the component in 2 different ways:

.. include:: /components/require_autoload.rst.inc

Sections
.. _components-security-terminology:

Security Terminology
--------------------

Security is a quite complex task and has some terminology that you won't often
find in other type of programming libraries. That's why it's good to make sure
you know some of the terms used in the Security component before starting to
dive into it.

**Authentication**
This is the first of the two phases in the Security component. During this
phase, the security tries to answer one question: **Who are you?** The
answer to this question might be retrieved from a session or from a token,
to name some examples.

**Authorization**
This is the second phase and it tries to answer another question: **Are you
allowed to access this?** The security system knows who you are and what
you are allowed to do, now it has to decide if you fit the requirements for
the requested action. E.g. do you have admin rights, when trying to access
the admin dashboard.

**Token**
The token is the central object in the Security system. It contains all
information that the security system has to know. For instance, if you
login, it contains the submitted username and password. After you've logged
in, it contains your rights.

**Roles**
This is another naming for rights. It tells your "role" in the application
(e.g. user, admin or moderator, etc.).

Usage
-----

Now you know some terms, you already have a very global overview of the flow in
the Security component (be aware that this code is *not* working in the current
state)::

// The authentication manager answers *Who are you?*
$authenticationManager = ...;

// Keeps track of the token during the lifetime of the token
$tokenStorage = ...;

// The authenticator transforms an unauthenticated token into an
// authenticated one
$authenticatedToken = $authenticationManager->authenticate(new Token(...));

$tokenStorage->setToken($authenticatedToken);

// The authorization checker is the access point of the Authorization phase
$authorizationChecker = ...;

// This code checks if admin is your role in the application
if (!$authorizationChecker->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}

// ... show something secret, all Security checks are done!

The Security component itself consists of a couple of sub-components, with Core
and Http being the two big ones. Besides this, it contains a sub-components for
CSRF protection and ACL (Access Control Lists) systems.

The Security Core component contains the actual Security system, decoupled from
possible access points (e.g. web request). This means it's usable in every
application (e.g. a CLI application or a web application).

The Security Http component is a wrapper around the Core component, providing
integration into "HTTP-land" using the
:doc:`HttpFoundation component </components/http_foundation/introduction>`.

In the next chapters, you'll learn more about these 2 sub-components.

Chapters
--------

* :doc:`/components/security/firewall`
* :doc:`/components/security/authentication`
* :doc:`/components/security/authorization`
* :doc:`/components/security/core/authentication`
* :doc:`/components/security/core/authorization`
* :doc:`/components/security/http`
* :doc:`/components/security/secure_tools`

.. _Packagist: https://packagist.org/packages/symfony/security