The All-Important User Class

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Yo guys! You finally made it to the security course: you brave, brave souls. Whatever, these days, security isn't scary - it's super fun! You've got traditional login forms, Facebook authentication, GitHub authentication, and API authentication with JSON web tokens, just to name a few. When you're doing something with security these days, it's usually pretty darn fun. And we're going to learn enough so that you can implement whatever crazy, insane security system you want.

But, the only way to secure your new security skills it to feel secure in my recommendation that you code along with me. You guys know the drill: download the course code unzip it and look for the start/ directory. That'll have the same code that I have here. Open up the README file to find all the setup details. At the end, you'll open up a new tab and run:

./bin/console server:run

to start the built-in web server.

Authentication vs Authorization (Fight!)

Aquanauts assemble... to talk about security!

Security has two big parts. The first is authentication - this is all about who you are - and we'll cover it first. Authentication is the tough stuff, and there's a lot of variation - login forms, social media auth, API stuff - you get it.

The second big piece is authorization, and this doesn't care about who you are, just whether or not you have fins. I mean, whether or not you have permission to take an action. Authorization comes later.

What about FOSUserBundle?

Before swim there, let's talk about a super-famous bundle: FOSUserBundle. You might be wondering, should I use this? What does it do? Or, did I turn the oven off?

First, we will not use this bundle, but it is great and you did turn the oven off... probably.

It gives you a lot of free features that we will build by hand. But FOSUserBundle does not give you any special "security" system - it's much less interesting than that, in a good way! The bundle gives you just two things:

  1. A User entity in case you need to store users in the database
  2. A bunch of routes and controllers

for things like your login form, registration and reset password. Those are all things you can easily build yourself... but if you need them, why not use the bundle?

Anyways, we won't use it, and that'll be the best path to learn how the security system works. But when you finish, you might save yourself some time using FOSUserBundle.

Create that User Class

Now, back to authentication. Here's our first goal: create a login form where the user can sign in with their email and password. In this app, we'll load user info from the database.

No matter how your users will authenticate, the first step is always the same: create a User class.

In your Entity directory - create a new class called User. The only rule is that this must implement a UserInterface. Add that:

... lines 1 - 2
namespace AppBundle\Entity;
... lines 4 - 5
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
{
... lines 10 - 28
}

I'll use Command+N - or the "Code"->"Generate" menu - and select "Implement Methods". Select all the new methods:

... lines 1 - 2
namespace AppBundle\Entity;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
{
public function getUsername()
{
}
public function getRoles()
{
}
public function getPassword()
{
}
public function getSalt()
{
}
public function eraseCredentials()
{
}
}

Oh, and let's move getUsername() to the top: it makes more sense up there.

Is User an Entity?

Notice I did put my User class inside of the Entity directory because eventually we will store users in the database. But, that's not required: sometimes user details are stored somewhere else - like a central authentication server. In those cases, you will still have a User class, you just won't store it with Doctrine.

More on that as we go along.

Ok, we've got the empty user class: let's fill it in!

Leave a comment!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "knplabs/knp-markdown-bundle": "^1.4", // 1.4.2
        "doctrine/doctrine-migrations-bundle": "^1.1" // 1.1.1
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0", // v3.1.3
        "nelmio/alice": "^2.1", // 2.1.4
        "doctrine/doctrine-fixtures-bundle": "^2.3" // 2.3.0
    }
}