{"id":18750672,"url":"https://github.com/webiny/security","last_synced_at":"2025-11-26T20:30:17.989Z","repository":{"id":20228575,"uuid":"23500434","full_name":"webiny/Security","owner":"webiny","description":"[READ-ONLY] The PHP security component is a layer that takes care of the authentication and authorization processes for you. (master at Webiny/Framework) ","archived":false,"fork":false,"pushed_at":"2017-11-26T21:25:20.000Z","size":124,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-12-28T22:53:42.349Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.webiny.com/","language":"PHP","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/webiny.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"Security.php","support":null}},"created_at":"2014-08-30T20:47:35.000Z","updated_at":"2023-05-21T17:38:04.000Z","dependencies_parsed_at":"2022-08-21T03:40:14.360Z","dependency_job_id":null,"html_url":"https://github.com/webiny/Security","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2FSecurity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2FSecurity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2FSecurity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2FSecurity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webiny","download_url":"https://codeload.github.com/webiny/Security/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239635853,"owners_count":19672244,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T17:12:44.855Z","updated_at":"2025-11-26T20:30:17.934Z","avatar_url":"https://github.com/webiny.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"Security Component\n==================\n\nThe security component is a layer that takes care of the authentication and authorization processes for you.\n\nInstall the component\n---------------------\nThe best way to install the component is using Composer.\n\n```bash\ncomposer require webiny/security\n```\nFor additional versions of the package, visit the [Packagist page](https://packagist.org/packages/webiny/security).\n\n# About\n\nBefore we go into details, is important that you are familiar with the terms of authorization, authentication and\naccess control, if you are not, please read the following articles:\n\n- http://www.cyberciti.biz/faq/authentication-vs-authorization/\n- http://stackoverflow.com/questions/6556522/authentication-versus-authorization\n\nIf you what to know more:\n\n- http://en.wikipedia.org/wiki/Authorization\n- http://en.wikipedia.org/wiki/Authentication\n- http://en.wikipedia.org/wiki/Access_control\n\n# Usage\n\nNOTE: There are 2 ways of accessing your firewalls.\n\nThe long way:\n```php\n$firewall = $this-\u003esecurity()-\u003efirewall('admin');\n```\n\nAnd the short way:\n```php\n$firewall = $this-\u003esecurity('admin');\n```\n\nThe usage of the component is fairly simple:\n\nFirst you process the user login:\n```php\nclass MyClass\n{\n    use SecurityTrait;\n\n    function loginUser()\n    {\n        $loginSuccessful = $this-\u003esecurity('admin')-\u003eprocessLogin();\n    }\n}\n```\n\nThen you can play around with the authorization methods:\n```php\nclass MyClass\n{\n    use SecurityTrait;\n\n    function myMethod(){\n        // get authenticated user\n        $user = $this-\u003esecurity('admin')-\u003egetUser();\n\n        // check if user has a role\n        if($user-\u003ehasRole('ROLE_EDITOR')) {\n            // user has role ROLE_EDITOR or any role with greater access level\n        }\n\n        // check if current user can access the current url\n        if($this-\u003esecurity('admin')-\u003eisUserAllowedAccess()){\n            // user can access the current url based on the defined access rules\n        }\n    }\n}\n```\n\nIf you wish to logout the user:\n```php\nclass MyClass\n{\n    use SecurityTrait;\n\n    function logoutUser()\n    {\n        $logoutSuccessful = $this-\u003esecurity('admin')-\u003eprocessLogout();\n    }\n}\n```\n\n# Example configuration\n\nThis is an example configuration.\nThe next few topics will describe every part of the configuration.\n\n```yaml\nSecurity:\n    UserProviders:\n        Memory:\n            john: {password: secret, roles: 'ROLE_USER'}\n            admin: {password: login123, roles: 'ROLE_SUPERADMIN'}\n    AuthenticationProviders:\n        OAuth2:\n            Params:\n                Server: FBAuth\n                Roles: [ROLE_USER]\n    Firewalls:\n        Admin:\n            RealmName: Administration\n            Anonymous: true\n            RememberMe: true\n            TokenKey: SecretKey\n            UserProviders: [Memory, OAuth2]\n            AuthenticationProviders: [Http, Form, OAuth2]\n```\n\n# Components\n\nThe security layer is actually a set of several components that work and communicate together. \nThe next few sections will go through the components and explain what they do.\n\n## Tokens (`Security.Tokens`)\n\nTokens are used to encrypt user data and save it into the session or cookie. Using tokens, once the user is authorized, we can do all future authorizations over the token, no need to use any authentication providers, check the database and things like that. Tokens save a lot of processing time.\n\nEvery token has two configuration parameters:\n- `Driver`: name of a registered `Crypt` service\n- `Params`: list of parameters that are being passed to the `Driver` constructor\n- `SecurityKey`: key that will be used to encrypt token data; key must a length of 2n (8, 16, 32, 64 characters)\n\nExample token definition:\n```yaml\nSecurity:\n    Tokens:\n        SomeTokenName:\n            Driver: '\\Webiny\\Component\\Security\\Token\\CryptDrivers\\Crypt\\Crypt'\n            SecurityKey: $3cR3tK3y # secret key that will be used to encrypt the token data\n    Firewalls:\n        Admin:\n            Token: SomeTokenName\n```\n\nThe built-in token driver is using the `Crypt` component, which is probably satisfying for the most cases.\nYou can also have multiple tokens defined, with different drivers or security key, but you can only use one token per firewall.\n\nBy default, you don't need to define a `Token`, an internal token is automatically set for you. In case of the default\ntoken, you just need to define the `TokenKey` under your firewall:\n\n```yaml\nSecurity:\n    Firewalls:\n        Admin:\n            TokenKey: SecretKey\n```\n\n\n## Encoders (`Security.Encoders`)\n\nEncoders are services that are responsible for two things, creating a password hash from the provided string and\nverifying if the submitted password matches the given hash. Encoders do the similar thing like tokens, but tokens do encryption of user data, which can be decrypted, while encoders create hashes, which is not a reversible process, so you cannot get the original string.\n\nThe encoder component comes with a default `Crypt` driver, that uses the built in `Crypt` component, for hashing and verifying passwords.\n\nThe driver requires that you have `Crypt` service defined. Just provide the name of the  service under `Params` and your encoder is ready. \n\nExample encoder configuration:\n\n```yaml\n# encoder configuration\nSecurity:\n    Encoders:\n        EncoderOne:\n            Driver: \\Webiny\\Component\\Security\\Encoder\\Drivers\\Crypt\n        EncoderTwo:\n            Driver: \\Webiny\\Component\\Security\\Encoder\\Drivers\\Plain\n    Firewalls:\n        Admin:\n            Encoder: EncoderOne\n```\n\nTo create a custom encoder driver, you need to create a class that implements\n`\\Webiny\\Component\\Security\\Encoder\\EncoderDriverInterface`.\n\nThe component also comes with a `Plain` driver, which doesn't encode passwords, it keeps them in their plain format.\nYou can also set `Encoder: false` under the `Firewall`. That will use the `Plain` driver.\n\nBy default you don't need to define an `Encoder`, an internal encoder is automatically defined for you. \n\n\n\n## User Providers (`Security.UserProviders`)\n\nUser providers are like a databases from where the `Security` component queries the users.\nEach provider consists of 2 parts, a user provider, and the user class itself.\nThe provider part is responsible for loading users based on submitted login credentials, while the user object is responsible for verifying the submitted credentials against the loaded object from the provider.\n\nThere are four built-in user providers:\n- `Memory` \n- `OAuth2` \n- `TwitterOAuth`\n- `Entity`\n\n\n\n### Memory provider\n\nThe `Memory` provider gives you the option to define users directly inside your configuration file, and it looks like this:\n\n```yaml\nSecurity:\n    UserProviders:\n        MyTestMemoryUsers:\n            john: {Password: secret, Roles: ROLE_USER}\n            admin: {Password: login, Roles: [ROLE_SUPERADMIN, ROLE_GOD]}\n        MyOtherMemoryUsers:\n            marco: {password: polo, roles: ROLE_ADMIN}\n    Firewall:\n        Admin:\n            UserProviders: [MyTestMemoryUsers, MyOtherMemoryUsers]\n```\n\nAs you see, you can have multiple memory providers defined. Which one you wish to use, depends on how you define your firewall. You can use both of them, but we'll see more about that later.\n\n**NOTE:**\nMake sure that you set `Encoder` to `false` on firewalls that are using `Memory` or some other provider that contains\npasswords in raw format, that is, where passwords are not encrypted. (NOTE: do not ever do that for production code).\n\n\n### OAuth2 provider\n\nThe OAuth2 provider depends on the `OAuth2` component and it must be wrapped together with the authentication provider,\ndescribed in the later topics. Basically, this provider gives you the option to do user authentication using any OAuth2 server, like Facebook, Google, LinkedIn, and many more.\n\nTo configure the OAuth2 user provider you just need to set the path to the built-in driver:\n\n```yaml\nSecurity:\n    UserProviders:\n        SomeOAuth2Provider:\n            Driver: '\\Webiny\\Component\\Security\\User\\Providers\\OAuth2\\OAuth2Provider'\n    Firewall:\n        Admin:\n            UserProviders: [SomeOAuth2Provider]\n```\n\n### TwitterOAuth provider\n\nUnfortunately Twitter doesn't support the version 2 of OAuth protocol, just version 1, so we created a special TwitterOAuth provider. Its configuration is very similar to the OAuth2 user provider.\n\n```yaml\nSecurity:\n    UserProviders:\n        MyTwitterOAuthProvider:\n            Driver: '\\Webiny\\Component\\Security\\User\\Providers\\TwitterOAuth\\TwitterOAuth'\n    Firewall:\n        UserProviders: [MyTwitterOAuthProvider]\n```\n\n### Entity provider\n\nThis provider uses the Entity component which is tied to your database. \n \n```yaml\nSecurity:\n    UserProviders:\n        MyFromDatabaseProvider:\n            Driver: '\\Webiny\\Component\\Security\\User\\Providers\\Entity\\Entity'\n            Params:\n                Entity: 'My\\App\\Entities\\User'\n                Username: username\n                Password: password\n                Role: ROLE_USER\n    Firewall:\n        UserProviders: [MyFromDatabaseProvider]\n```\n\n**Entity** parameter points your entity class.\n**Username** defines the field name in the collection that holds the username.\n**Password** same as the username, just points to the password field.\n**Role** points either to the collection field holding the users role, or will be used as the role name, if the field doesn't exist.\n\n### Custom user providers\n\nTo implement a custom user provider you need to create a class that implements\n`\\Webiny\\Component\\Security\\User\\UserProviderInterface`. And you need to create a user class that extends\n`\\Webiny\\Component\\Security\\User\\AbstractUser`. And that's it, all other details are described inside the interface and\nthe abstract class.\n\n### Combining multiple user providers\n\nEach firewall can use one or more user providers. You can combine them how it best fits your needs. We will discuss that in the later topics.\n\n### Authentication providers (`Security.AuthenticationProviders`)\n\nAuthentication providers are ways of authenticating users.\n\nThis is an example configuration for an authentication provider:\n\n```yaml\nSecurity:\n    AuthenticationProviders:\n        Http:\n            Driver: '\\Webiny\\Component\\Security\\Authentication\\Providers\\Http\\Http'\n        Facebook:\n            Driver: '\\Webiny\\Component\\Security\\Authentication\\Providers\\OAuth2\\OAuth2'\n            Params:\n                Server: Facebook # which OAuth2 server to use (defined under OAuth2 component)\n                Roles: [ROLE_USER] # which role to assign to user authenticated with this provider\n        TwitterOAuth:\n            Driver: \\Webiny\\Component\\Security\\Authentication\\Providers\\TwitterOAuth\\TwitterOAuth'\n            Params:\n                Server: ['MyTwitterApp'] # which twitter app to use (must be registered by TwitterOAuth component)\n                Roles: [ROLE_USER] # which role to assign to user authenticated with this provider\n    Firewall:\n        Admin:\n            AuthenticationProviders: [Http, Facebook, TwitterOAuth]\n```\n\nThe configuration must have two parameters, the `Driver` param that defines which class to use to process the authentication,\nand an optional `Params` that forwards the different parameters to the driver constructor.\n\nAdditional parameters might be required for some other auth providers.\n\nThere are also four built-in auth providers:\n\n#### Http auth provider\n\nThis is the basic Http authentication.\nDriver: `\\Webiny\\Component\\Security\\Authentication\\Providers\\Http\\Http`\n\n#### Form auth provider\n\nUse this provider when you have a HTML login form for authenticating your users.\nDriver: `\\Webiny\\Component\\Security\\Authentication\\Providers\\Form\\Form`.\n\nYour HTML form must have these fields:\n- `username`\n- `password`\n- `rememberme` (optional; default: \"\")\n\n#### OAuth2 auth provider\n\nThis provider uses the OAuth2 protocol and the `OAuth2` component. The supported OAuth2 servers are defined the by\nthe `OAuth2` component.\nDriver: `\\Webiny\\Component\\Security\\Authentication\\Providers\\OAuth2\\OAuth2`\n\nThis provider requires a bit more configuration, so here is an example:\n\n```yaml\nFacebook:\n    Driver: '\\Webiny\\Component\\Security\\Authentication\\Providers\\OAuth2\\OAuth2'\n    Params:\n        Server: Facebook # which OAuth2 server to use (must be defined under OAuth2 component configuration)\n        Roles: [ROLE_USER] # which role to assign to user authenticated with this provider\n```\n\nNotice the two attributes inside the params section, the `Server` attribute points to the defined OAuth2 configuration,\nwhile `Roles`param defines which roles will be assigned to users that are authenticated by this provider.\n\n#### TwitterOAuth auth provider\nThis auth provider is very similar to the OAuth2 auth provider, just this one is designed to work with Twitter OAuth server.\n\nHere is an example configuration:\n```yaml\nTwitterOAuth:\n    Driver: \\Webiny\\Component\\Security\\Authentication\\Providers\\TwitterOAuth\\TwitterOAuth'\n    Params:\n        Server: ['MyTwitterApp'] # which twitter app to use (must be registered by TwitterOAuth component)\n        Roles: [ROLE_USER] # which role to assign to user authenticated with this provider\n```\n\n## Firewall (`Security.Firewalls`)\n\nFirewall is the central component that controls the authentication layer.\n\nYou can have multiple sets of firewall. Each firewall consists of following parameters:\n- `RealmName`\n    - user readable name of the current firewall\n- `Anonymous`\n    - is anonymous access allowed behind this firewall or not\n- `RememberMe`\n    - do you want to remember the users credentials for a period of time or just the current session\n    - if you wish to use the 'Remember me' feature on the page, this must be set to `true`\n- `Encoder`\n    - if your passwords are hashed (and they should be), place the name of your `Encoder` here\n    - the encoder name must match the names under `Security.Encoders`\n- `Token`\n    - which token will the firewall use to encrypt user data\n- `UserProviders`\n    - these are the user providers that the firewall will use to ask for a user account\n    - you can define an array of user providers, and the firewall will ask them one-by-one\n- `AuthenticationProviders`\n    - unlike user providers, that just return a user for the given username, authentication providers do the checking of user credentials\n    - for example, authentication provider would ask the user to login over facebook, but the user provider, using facebook api, would retrieve the account\n- `AccessControl`\n    - set of urls and roles that are required to enter that area (you can find more information in the sections below)\n- `RoleHierarchy`\n    - defines the hierarchy of roles for the current firewall (you can find more information in the sections below)\n\n### Access control\n\nAccess control is the central part that handles the authorization.\nInside access control you define a set of rules, where each rule consist of a `Path` and a list of `Roles` that are required for accessing that path.\n\n```yaml\nAccessControl:\n    Rules:\n        - {Path: '/^\\/[a-zA-Z0-9-_]+\\/[a-zA-Z0-9-_]+\\/[a-zA-Z0-9]{13}$/', Roles: ROLE_ANONYMOUS}\n        - {Path: '/^\\/about/', Roles: [ROLE_USER,ROLE_EDITOR]}\n        - {Path: '/^\\/statistics/', Roles: ROLE_ANONYMOUS}\n    DecisionStrategy: affirmative\n```\n\nIf a rule is not matched, the built-in, `ROLE_ANONYMOUS`, will be returned as the required role to access that path.\n\n### Voters\n\nAccess control also has internal mechanism called `Voters`. These are like a jury that can either vote\n\n- `ACCESS ALLOWED`\n- `ACCESS_DENIED`\n- `ACCESS_ABSTAINED`\n\nThere are two built-in voters, the `AuthenticationVoter` that votes based on if user is authenticated or not, and there\nis a `RoleVoter` that votes based on if user has the necessary role to access the current area.\n\nThe logic behind voters is created so you can extend it and add your own voters. For example you can create a voter\nthat either allows or denies access based on users IP address, like a black-list filter.\n\nTo create a custom voter you need to create a class that implements `\\Webiny\\Component\\Security\\Authorization\\Voters\\VoterInterface`.\nAfter that, you need to create a service and tag it with `Security.Voter` tag.\n\n```yaml\nMyComponent:\n    Services:\n        MyVoter:\n            class: \\MyCustomLib\\MyCustomVoter\n            tags: [Security.Voter]\n```\n\n### Decision strategy\n\nDecision strategy is the property that defines how the system will make its ruling, either to allow or deny access,\nbased on the votes for the voters.\n\nThere are three different strategies that can be applied:\n- *unanimous* - all voters must vote `ACCESS_ALLOWED` to allow access\n- *affirmative* - only one `ACCESS_ALLOWED` vote is enough to allow access\n- *consensus* - majority wins (tie denies access)\n\n## Role hierarchy (`Security.RoleHierarchy`)\n\nThis component is mostly self-explanatory, it defines the list of available roles and their hierarchy.\n\nHere is an example:\n\n```yaml\nRoleHierarchy:\n    ROLE_USER: ROLE_EDITOR\n    ROLE_ADMIN: ROLE_USER\n```\n\n`ROLE_USER` will have access to all areas that require `ROLE_USER`, `ROLE_EDITOR` or `ROLE_ANONYMOUS`.\n`ROLE_ADMIN` will have access to all areas that require `ROLE_ADMIN`, `ROLE_USER`, `ROLE_EDITOR` or `ROLE_ANONYMOUS`.\n\n## Events\n\nThe component fires several events that you can subscribe to:\n\n- `wf.security.login_invalid` fired when user submits invalid login credentials\n- `wf.security.login_valid` fired when user submits valid login credentials\n- `wf.security.role_invalid` fired when authenticated user tries to enter an area that requires a higher role than he currently has\n- `wf.security.logout` fired when processLogout is called on a firewall\n- `wf.security.not_authenticated` fired when a user tries to access an area for which he doesn't have a proper authorization level (role)\n\nAll these events pass an instance of `\\Webiny\\Component\\Security\\SecurityEvent`.\n\nThere are also some, user provider specific, events:\n`OAuth2` user provider event:\n- `wf.security.user.oauth2` fired when user is authenticated over OAuth2 provider\n\n`TwitterOAuth` user provider event:\n- `wf.security.user.twitter` fired when user is authenticated over Twitter OAuth provider\n\nEach of those two events, returns a different class, for OAuth2 it's `Webiny\\Component\\Security\\User\\Providers\\OAuth2\\OAuth2Event` and for Twitter it's `Webiny\\Component\\Security\\User\\Providers\\TwitterOAuth`. Both classes have two methods, one returns an object, containing different user information we manged to get from the OAuth(2) server. The other method returns an instance of the OAuth class, either TwitterOAuth or OAuth2, giving you direct access to the API and the access key.\n\n\n## Using provider short codes\n\nIf you only need one instance of user or authentication provider, you can use short codes. With short codes you don't need\nto define the `Driver` parameter, and in cases of authentication provider, you don't need to define the auth provider under `Security.AuthenticationProviders`.\n\nFor example, this config can we written in a shorter version:\n\n```yaml\nSecurity:\n    UserProviders:\n        OAuth2:\n            Driver: '\\Webiny\\Component\\Security\\User\\Providers\\OAuth2\\OAuth2Provider'\n        TwitterOAuth:\n            Driver: '\\Webiny\\Component\\Security\\User\\Providers\\TwitterOAuth\\TwitterOAuth'\n        Memory:\n            john: {password: secret, roles: 'ROLE_USER'}\n            admin: {password: login123, roles: 'ROLE_SUPERADMIN'}\n        Entity:\n            Driver: '\\Webiny\\Component\\Security\\User\\Providers\\Entity\\Entity'\n            Params:\n                Entity: 'My\\App\\Entities\\User'\n                Username: username\n                Password: password\n                Role: ROLE_USER\n    AuthenticationProviders:\n        Http:\n            Driver: '\\Webiny\\Component\\Security\\Authentication\\Providers\\Http\\Http'\n        Form:\n            Driver: '\\Webiny\\Component\\Security\\Authentication\\Providers\\Form\\Form'\n        OAuth2:\n            Driver: '\\Webiny\\Component\\Security\\Authentication\\Providers\\OAuth2\\OAuth2'\n            Params:\n                Server: Facebook # which OAuth2 server to use (defined under OAuth2 component)\n                Roles: [ROLE_USER] # which role to assign to user authenticated with this provider\n        TwitterOAuth:\n            Driver: \\Webiny\\Component\\Security\\Authentication\\Providers\\TwitterOAuth\\TwitterOAuth'\n            Params:\n                Server: MyTwitterApp # which twitter app to use (must be registered by TwitterOAuth component)\n                Roles: [ROLE_USER] # which role to assign to user authenticated with this provider\n    Firewalls:\n        Admin:\n            RealmName: Administration\n            Anonymous: true\n            RememberMe: true\n            UserProviders: [OAuth2, TwitterOAuth, Memory, Entity]\n            AuthenticationProviders: [Http, Form, OAuth2, TwitterOAuth]\n```\n\nshort version:\n\n```yaml\nSecurity:\n    UserProviders:\n        Memory:\n            john: {password: secret, roles: 'ROLE_USER'}\n            admin: {password: login123, roles: 'ROLE_SUPERADMIN'}\n        Entity:\n            Params:\n                Entity: 'My\\App\\Entities\\User'\n                Username: username\n                Password: password\n                Role: ROLE_USER\n    AuthenticationProviders:\n        OAuth2:\n            Params:\n                Server: Facebook # which OAuth2 server to use (defined under OAuth2 component)\n                Roles: [ROLE_USER] # which role to assign to user authenticated with this provider\n        TwitterOAuth:\n            Params:\n                Server: MyTwitterApp # which twitter app to use (must be registered by TwitterOAuth component)\n                Roles: [ROLE_USER] # which role to assign to user authenticated with this provider\n    Firewalls:\n        Admin:\n            RealmName: Administration\n            Anonymous: true\n            RememberMe: true\n            UserProviders: [OAuth2, TwitterOAuth, Memory, Entity]\n            AuthenticationProviders: [Http, Form, OAuth2, TwitterOAuth]\n```\n\nThe key is that the name of the `UserProvider` or `AuthenticationProvider` matches the internal driver name. \nThis is valid only for the internal providers, for custom provider you always need to define the `Driver`.\n\n\nResources\n---------\n\nTo run unit tests, you need to use the following command:\n\n    $ cd path/to/Webiny/Component/Security/\n    $ composer.phar install\n    $ phpunit","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebiny%2Fsecurity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebiny%2Fsecurity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebiny%2Fsecurity/lists"}