Skip to content

Instantly share code, notes, and snippets.

@amosfolz
Forked from archey347/login-suggestion.md
Last active May 21, 2019 01:46
Show Gist options
  • Select an option

  • Save amosfolz/3d244472ffb6ee7a950f18ecb604c743 to your computer and use it in GitHub Desktop.

Select an option

Save amosfolz/3d244472ffb6ee7a950f18ecb604c743 to your computer and use it in GitHub Desktop.
UserFrosting Login Feature Suggestion

UserFrosting Login Feature Suggestion

This plan outlines a possible method of integrating social login, 2 factor authentication, and also the option for a developer to introduce their own authentication methods through their own sprinkles.

For every authentication method, there will be an authenticator class, which will have standard methods depending on what type of authenticator it is (see below). Each authenticator will be enabled in the config file. This is also where any application credentials that are needed by the authenticator will also be stored.

The presence of it in the configuration will then allow UserFrosting to "register" the authenticator class in a sub container called authenticators. They have been set up in the config so that multiple instances of the same authenticator class can be used, such as if a person had two standard oath2 sites they wanted to use.

The different authenticator types will be split up into sub-containers again depending on what type it is.

Authenticator Types

  • Primary - Uses standard username/password form
  • External - Requires user input/redirect through another website
  • Secondary - Any 2nd Factor Authentication

Primary

This mode will use the standard username/password form. Each plugin will have a priority, so that the plugin with the highest priority will be tried first, and the one with the second highest will be tried second and so on. The priority will probably be set by the order in which they come in the config file.

This allows for other login sources to be used, such as LDAP.

This plugin will be based on the PrimaryAuthenticator class

External

This sort of plugin requires the user to login through another website or a popup, typically through OAuth or OpenID

This plugin will be based on the ExternalAuthenticator class

Possible options:

https://packagist.org/packages/simplesamlphp/simplesamlphp

https://github.com/Adldap2/Adldap2 | http://adldap2.github.io/Adldap2/

https://github.com/dapphp/radius

https://hybridauth.github.io/documentation.html

Secondary

This is any 2nd Factor authentication. If 2nd Factor authentication is required by an account, when a user logs in they can select any one of the methods that they have set up. They could include:

  • Time Based Code Generator
  • A list of 'Backup' codes
  • A text message with a code.
  • U2F token (if possible)

This plugin will be based on the SecondaryAuthenticator class

Possible options:

https://github.com/scheb/two-factor-bundle

https://github.com/paragonie/multi_factor

Authenticator Class

Each authenticator class will have standard methods, depending on what type it is.

The authenticator classes will also have to manage changing account details etc. It may be nescerary to have seperate account handlers as well, so that if a person wants to use their own oauth server, they can implement it with their own api. An avatar provider class may also have to be implemented with this. (Ref #620)

For the external authenticator class, a method will be needed to get a path for a twig template with a login button (e.g. a Login with Facebook button), and for the secondary authenticator then a method will be needed to render an additional login page.

A standard HybridAuthAuthenticator might be useful which can be extended for each provider supported by HybridAuth.

Configuration

The different plugins can be enabled or disabled by the configuration, along with any other additional options. As UF uses different configuration files for development and production, it would allow for a developer to more easily use "sandbox credentials" whilst developing.

Options

Config Name Type Description
slug String Name in the container and in the database
class_name String The full path to the class to use
options Array Any additional options needed by the specific authenticator

Format

The configuration will look something like this:

{
    "authenticators" : {
            "plugin_type" : [
                {
                    "__comment" : "The item defined first will have the highest priority"
                },
                {
                    "slug" : "slug_name",
                    "class_name" : "UserFrosting\\Sprinkle\\ExampleSprinkle\\Authenticators\\PluginType\\AuthenticatorClassName",
                    "options" : {
                        "option1" : "Additional Settings Go Here"
                    }
                }
            ]
        }
    }
}

Example

{
    "authenticators" : {
            "primary" : [
                {
                    "slug" : "database",
                    "class_name" : "DatabaseAuthenticator"
                },
                {
                    "slug" : "ldap",
                    "class_name" : "UserFrosting\\Sprinkle\\ExampleSprinkle\\Authenticator\\Primary\\LDAPAuthenticator",
                    "options" : {
                        "account_suffix" : "@example.com",
                        "domain_controllers" : [
                            "dc1.example.com",
                            "dc2.example.com"
                        ],
                        "admin_username" : "",
                        "admin_password" : ""
                    }
                }
            ],
            "external" : [
                {
                    "slug" : "github",
                    "class_name" : "UserFrosting\\Sprinkle\\ExampleSprinkle\\Authenticator\\External\\GithubAuthenticator",
                    "options" : {
                        "app_id" : "A App ID",
                        "app_secret" : "Some secret....."
                    }
                }
            ],
            "secondary" : [
                {
                    "slug" : "google_time_code",
                    "class_name" : "UserFrosting\\Sprinkle\\ExampleSprinkle\\Authenticator\\Secondary\\GoogleTimeCodeAuthenticator",
                    "options" : {
                        "salt" : "AKHD3425..."
                    }
                }
            ]
        }
    }
}

If there is no primary or external authentication configuration set, then it will use a "built-in" configuration for using the passwords in the database. It might be worth making the default uf authentication method mandatory after all of the other primary authenticators have been tried.

Database

Name Comment
auth_methods Contains all of the available authentication methods
account_auth_method Associates an account with a authentication method

auth_methods

Name Type Comments
id integer Auto Increment, Primary Key
slug String

The config will be used to generate all of the rows in the auth_method table, maybe through another bakery command which also runs on setup.

account_auth_method

Name Type Comments
id Int Auto Increment, Primary Key
account_id Int Links to accounts.id
auth_method_id Int Links to auth_methods.id
options TEXT Any credentials needed - In JSON format

Using JSON in a database is a bit crude - I don't know whether it would be worth to go the extra mile and do like a account_auth_method_options table instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment