{"action":"closed","number":14673,"pull_request":{"url":"https://api.github.com/repos/symfony/symfony/pulls/14673","id":35594385,"html_url":"https://github.com/symfony/symfony/pull/14673","diff_url":"https://github.com/symfony/symfony/pull/14673.diff","patch_url":"https://github.com/symfony/symfony/pull/14673.patch","issue_url":"https://api.github.com/repos/symfony/symfony/issues/14673","number":14673,"state":"closed","locked":false,"title":"New Guard Authentication System (e.g. putting the joy back into security)","user":{"login":"weaverryan","id":121003,"avatar_url":"https://avatars.githubusercontent.com/u/121003?v=3","gravatar_id":"","url":"https://api.github.com/users/weaverryan","html_url":"https://github.com/weaverryan","followers_url":"https://api.github.com/users/weaverryan/followers","following_url":"https://api.github.com/users/weaverryan/following{/other_user}","gists_url":"https://api.github.com/users/weaverryan/gists{/gist_id}","starred_url":"https://api.github.com/users/weaverryan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weaverryan/subscriptions","organizations_url":"https://api.github.com/users/weaverryan/orgs","repos_url":"https://api.github.com/users/weaverryan/repos","events_url":"https://api.github.com/users/weaverryan/events{/privacy}","received_events_url":"https://api.github.com/users/weaverryan/received_events","type":"User","site_admin":false},"body":"| Q             | A\r\n| ------------- | ---\r\n| Bug fix?      | no\r\n| New feature?  | yes\r\n| BC breaks?    | no\r\n| Deprecations? | no\r\n| Tests pass?   | yes\r\n| Fixed tickets | at least partially: #14300, #11158, #11451, #10035, #10463, #8606, probably more\r\n| License       | MIT\r\n| Doc PR        | symfony/symfony-docs#5265\r\n\r\nHi guys!\r\n\r\nThough it got much easier in 2.4 with `pre_auth`, authentication is a pain in Symfony. This introduces a new authentication provider called guard, with one goal in mind: put everything you need for *any* authentication system into one spot. \r\n\r\n### How it works\r\n\r\nWith guard, you can perform custom authentication just by implementing the [GuardAuthenticatorInterface](https://github.com/weaverryan/symfony/blob/guard/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php) and registering it as a service. It has methods for every part of a custom authentication flow I can think of.\r\n\r\nFor a working example, see https://github.com/weaverryan/symfony-demo/tree/guard-auth. This uses 2 authenticators simultaneously, creating a system that handles [form login](https://github.com/weaverryan/symfony-demo/blob/guard-auth/src/AppBundle/Security/FormLoginAuthenticator.php) and [api token auth](https://github.com/weaverryan/symfony-demo/blob/guard-auth/src/AppBundle/Security/TokenAuthenticator.php) with a respectable amount of code. The [security.yml](https://github.com/weaverryan/symfony-demo/blob/guard-auth/app/config/security.yml) is also quite simple.\r\n\r\nThis also supports \"manual login\" without jumping through hoops: https://github.com/weaverryan/symfony-demo/blob/guard-auth/src/AppBundle/Controller/SecurityController.php#L45\r\n\r\nI've also tested with \"remember me\" and \"switch user\" - no problems with either.\r\n\r\nI hope you like it :).\r\n\r\n### What's Needed\r\n\r\n1) **Other Use-Cases?**: Please think about the code and try it. What use-cases are we *not* covering? I want Guard to be simple, but cover the 99.9% use-cases.\r\n\r\n2) **Remember me** functionality cannot be triggered via manual login. That's true now, and it's not fixed, and it's tricky.\r\n\r\n### Deprecations?\r\n\r\nThis is a new feature, so no deprecations. But, creating a login form with a guard authenticator is a whole heck of a lot easier to understand than `form_login` or even `simple_form`. In a perfect world, we'd either deprecate those or make them use \"guard\" internally so that we have just **one** way of performing authentication.\r\n\r\nThanks!\r\n","created_at":"2015-05-17T22:12:45Z","updated_at":"2015-09-24T07:21:21Z","closed_at":"2015-09-24T07:21:21Z","merged_at":"2015-09-24T07:21:21Z","merge_commit_sha":"dd0cebf3a102bf19f99c034eb70681770618229a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/symfony/symfony/pulls/14673/commits","review_comments_url":"https://api.github.com/repos/symfony/symfony/pulls/14673/comments","review_comment_url":"https://api.github.com/repos/symfony/symfony/pulls/comments{/number}","comments_url":"https://api.github.com/repos/symfony/symfony/issues/14673/comments","statuses_url":"https://api.github.com/repos/symfony/symfony/statuses/a01ed35cfcbc97aed0fadcbbd0ae61fd92a4cacc","head":{"label":"weaverryan:guard","ref":"guard","sha":"a01ed35cfcbc97aed0fadcbbd0ae61fd92a4cacc","user":{"login":"weaverryan","id":121003,"avatar_url":"https://avatars.githubusercontent.com/u/121003?v=3","gravatar_id":"","url":"https://api.github.com/users/weaverryan","html_url":"https://github.com/weaverryan","followers_url":"https://api.github.com/users/weaverryan/followers","following_url":"https://api.github.com/users/weaverryan/following{/other_user}","gists_url":"https://api.github.com/users/weaverryan/gists{/gist_id}","starred_url":"https://api.github.com/users/weaverryan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weaverryan/subscriptions","organizations_url":"https://api.github.com/users/weaverryan/orgs","repos_url":"https://api.github.com/users/weaverryan/repos","events_url":"https://api.github.com/users/weaverryan/events{/privacy}","received_events_url":"https://api.github.com/users/weaverryan/received_events","type":"User","site_admin":false},"repo":{"id":21151556,"name":"symfony","full_name":"weaverryan/symfony","owner":{"login":"weaverryan","id":121003,"avatar_url":"https://avatars.githubusercontent.com/u/121003?v=3","gravatar_id":"","url":"https://api.github.com/users/weaverryan","html_url":"https://github.com/weaverryan","followers_url":"https://api.github.com/users/weaverryan/followers","following_url":"https://api.github.com/users/weaverryan/following{/other_user}","gists_url":"https://api.github.com/users/weaverryan/gists{/gist_id}","starred_url":"https://api.github.com/users/weaverryan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weaverryan/subscriptions","organizations_url":"https://api.github.com/users/weaverryan/orgs","repos_url":"https://api.github.com/users/weaverryan/repos","events_url":"https://api.github.com/users/weaverryan/events{/privacy}","received_events_url":"https://api.github.com/users/weaverryan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/weaverryan/symfony","description":"The Symfony PHP framework","fork":true,"url":"https://api.github.com/repos/weaverryan/symfony","forks_url":"https://api.github.com/repos/weaverryan/symfony/forks","keys_url":"https://api.github.com/repos/weaverryan/symfony/keys{/key_id}","collaborators_url":"https://api.github.com/repos/weaverryan/symfony/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/weaverryan/symfony/teams","hooks_url":"https://api.github.com/repos/weaverryan/symfony/hooks","issue_events_url":"https://api.github.com/repos/weaverryan/symfony/issues/events{/number}","events_url":"https://api.github.com/repos/weaverryan/symfony/events","assignees_url":"https://api.github.com/repos/weaverryan/symfony/assignees{/user}","branches_url":"https://api.github.com/repos/weaverryan/symfony/branches{/branch}","tags_url":"https://api.github.com/repos/weaverryan/symfony/tags","blobs_url":"https://api.github.com/repos/weaverryan/symfony/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/weaverryan/symfony/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/weaverryan/symfony/git/refs{/sha}","trees_url":"https://api.github.com/repos/weaverryan/symfony/git/trees{/sha}","statuses_url":"https://api.github.com/repos/weaverryan/symfony/statuses/{sha}","languages_url":"https://api.github.com/repos/weaverryan/symfony/languages","stargazers_url":"https://api.github.com/repos/weaverryan/symfony/stargazers","contributors_url":"https://api.github.com/repos/weaverryan/symfony/contributors","subscribers_url":"https://api.github.com/repos/weaverryan/symfony/subscribers","subscription_url":"https://api.github.com/repos/weaverryan/symfony/subscription","commits_url":"https://api.github.com/repos/weaverryan/symfony/commits{/sha}","git_commits_url":"https://api.github.com/repos/weaverryan/symfony/git/commits{/sha}","comments_url":"https://api.github.com/repos/weaverryan/symfony/comments{/number}","issue_comment_url":"https://api.github.com/repos/weaverryan/symfony/issues/comments{/number}","contents_url":"https://api.github.com/repos/weaverryan/symfony/contents/{+path}","compare_url":"https://api.github.com/repos/weaverryan/symfony/compare/{base}...{head}","merges_url":"https://api.github.com/repos/weaverryan/symfony/merges","archive_url":"https://api.github.com/repos/weaverryan/symfony/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/weaverryan/symfony/downloads","issues_url":"https://api.github.com/repos/weaverryan/symfony/issues{/number}","pulls_url":"https://api.github.com/repos/weaverryan/symfony/pulls{/number}","milestones_url":"https://api.github.com/repos/weaverryan/symfony/milestones{/number}","notifications_url":"https://api.github.com/repos/weaverryan/symfony/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/weaverryan/symfony/labels{/name}","releases_url":"https://api.github.com/repos/weaverryan/symfony/releases{/id}","created_at":"2014-06-24T04:00:07Z","updated_at":"2015-06-28T12:37:42Z","pushed_at":"2015-09-24T02:42:37Z","git_url":"git://github.com/weaverryan/symfony.git","ssh_url":"git@github.com:weaverryan/symfony.git","clone_url":"https://github.com/weaverryan/symfony.git","svn_url":"https://github.com/weaverryan/symfony","homepage":"symfony.com","size":60594,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":true,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":4,"forks":0,"open_issues":4,"watchers":0,"default_branch":"master"}},"base":{"label":"symfony:2.8","ref":"2.8","sha":"b1e0bd76c431659dca7e83bbe0b1c867478682eb","user":{"login":"symfony","id":143937,"avatar_url":"https://avatars.githubusercontent.com/u/143937?v=3","gravatar_id":"","url":"https://api.github.com/users/symfony","html_url":"https://github.com/symfony","followers_url":"https://api.github.com/users/symfony/followers","following_url":"https://api.github.com/users/symfony/following{/other_user}","gists_url":"https://api.github.com/users/symfony/gists{/gist_id}","starred_url":"https://api.github.com/users/symfony/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/symfony/subscriptions","organizations_url":"https://api.github.com/users/symfony/orgs","repos_url":"https://api.github.com/users/symfony/repos","events_url":"https://api.github.com/users/symfony/events{/privacy}","received_events_url":"https://api.github.com/users/symfony/received_events","type":"Organization","site_admin":false},"repo":{"id":458058,"name":"symfony","full_name":"symfony/symfony","owner":{"login":"symfony","id":143937,"avatar_url":"https://avatars.githubusercontent.com/u/143937?v=3","gravatar_id":"","url":"https://api.github.com/users/symfony","html_url":"https://github.com/symfony","followers_url":"https://api.github.com/users/symfony/followers","following_url":"https://api.github.com/users/symfony/following{/other_user}","gists_url":"https://api.github.com/users/symfony/gists{/gist_id}","starred_url":"https://api.github.com/users/symfony/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/symfony/subscriptions","organizations_url":"https://api.github.com/users/symfony/orgs","repos_url":"https://api.github.com/users/symfony/repos","events_url":"https://api.github.com/users/symfony/events{/privacy}","received_events_url":"https://api.github.com/users/symfony/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/symfony/symfony","description":"The Symfony PHP framework","fork":false,"url":"https://api.github.com/repos/symfony/symfony","forks_url":"https://api.github.com/repos/symfony/symfony/forks","keys_url":"https://api.github.com/repos/symfony/symfony/keys{/key_id}","collaborators_url":"https://api.github.com/repos/symfony/symfony/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/symfony/symfony/teams","hooks_url":"https://api.github.com/repos/symfony/symfony/hooks","issue_events_url":"https://api.github.com/repos/symfony/symfony/issues/events{/number}","events_url":"https://api.github.com/repos/symfony/symfony/events","assignees_url":"https://api.github.com/repos/symfony/symfony/assignees{/user}","branches_url":"https://api.github.com/repos/symfony/symfony/branches{/branch}","tags_url":"https://api.github.com/repos/symfony/symfony/tags","blobs_url":"https://api.github.com/repos/symfony/symfony/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/symfony/symfony/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/symfony/symfony/git/refs{/sha}","trees_url":"https://api.github.com/repos/symfony/symfony/git/trees{/sha}","statuses_url":"https://api.github.com/repos/symfony/symfony/statuses/{sha}","languages_url":"https://api.github.com/repos/symfony/symfony/languages","stargazers_url":"https://api.github.com/repos/symfony/symfony/stargazers","contributors_url":"https://api.github.com/repos/symfony/symfony/contributors","subscribers_url":"https://api.github.com/repos/symfony/symfony/subscribers","subscription_url":"https://api.github.com/repos/symfony/symfony/subscription","commits_url":"https://api.github.com/repos/symfony/symfony/commits{/sha}","git_commits_url":"https://api.github.com/repos/symfony/symfony/git/commits{/sha}","comments_url":"https://api.github.com/repos/symfony/symfony/comments{/number}","issue_comment_url":"https://api.github.com/repos/symfony/symfony/issues/comments{/number}","contents_url":"https://api.github.com/repos/symfony/symfony/contents/{+path}","compare_url":"https://api.github.com/repos/symfony/symfony/compare/{base}...{head}","merges_url":"https://api.github.com/repos/symfony/symfony/merges","archive_url":"https://api.github.com/repos/symfony/symfony/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/symfony/symfony/downloads","issues_url":"https://api.github.com/repos/symfony/symfony/issues{/number}","pulls_url":"https://api.github.com/repos/symfony/symfony/pulls{/number}","milestones_url":"https://api.github.com/repos/symfony/symfony/milestones{/number}","notifications_url":"https://api.github.com/repos/symfony/symfony/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/symfony/symfony/labels{/name}","releases_url":"https://api.github.com/repos/symfony/symfony/releases{/id}","created_at":"2010-01-04T14:21:21Z","updated_at":"2015-09-24T06:44:15Z","pushed_at":"2015-09-24T07:21:20Z","git_url":"git://github.com/symfony/symfony.git","ssh_url":"git@github.com:symfony/symfony.git","clone_url":"https://github.com/symfony/symfony.git","svn_url":"https://github.com/symfony/symfony","homepage":"symfony.com","size":248370,"stargazers_count":10824,"watchers_count":10824,"language":"PHP","has_issues":true,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":4268,"mirror_url":null,"open_issues_count":936,"forks":4268,"open_issues":936,"watchers":10824,"default_branch":"2.8"}},"_links":{"self":{"href":"https://api.github.com/repos/symfony/symfony/pulls/14673"},"html":{"href":"https://github.com/symfony/symfony/pull/14673"},"issue":{"href":"https://api.github.com/repos/symfony/symfony/issues/14673"},"comments":{"href":"https://api.github.com/repos/symfony/symfony/issues/14673/comments"},"review_comments":{"href":"https://api.github.com/repos/symfony/symfony/pulls/14673/comments"},"review_comment":{"href":"https://api.github.com/repos/symfony/symfony/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/symfony/symfony/pulls/14673/commits"},"statuses":{"href":"https://api.github.com/repos/symfony/symfony/statuses/a01ed35cfcbc97aed0fadcbbd0ae61fd92a4cacc"}},"merged":true,"mergeable":null,"mergeable_state":"unknown","merged_by":{"login":"fabpot","id":47313,"avatar_url":"https://avatars.githubusercontent.com/u/47313?v=3","gravatar_id":"","url":"https://api.github.com/users/fabpot","html_url":"https://github.com/fabpot","followers_url":"https://api.github.com/users/fabpot/followers","following_url":"https://api.github.com/users/fabpot/following{/other_user}","gists_url":"https://api.github.com/users/fabpot/gists{/gist_id}","starred_url":"https://api.github.com/users/fabpot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fabpot/subscriptions","organizations_url":"https://api.github.com/users/fabpot/orgs","repos_url":"https://api.github.com/users/fabpot/repos","events_url":"https://api.github.com/users/fabpot/events{/privacy}","received_events_url":"https://api.github.com/users/fabpot/received_events","type":"User","site_admin":false},"comments":18,"review_comments":32,"commits":24,"additions":1932,"deletions":3,"changed_files":25}}