Adldap2 / Adldap2-Laravel

LDAP Authentication & Management for Laravel
MIT License
911 stars 184 forks source link

SQLSTATE[42S22] Column Not Found: 1054 Unknown column 'email' in 'field list' #567

Closed shawnbyday closed 6 years ago

shawnbyday commented 6 years ago

Description:

Currently trying to get my configuration correct for ActiveDirectory. I've followed the "from scratch" section in my current project and I'm currently on the error:

"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'email' in 'field list' (SQL: insert into users (email, name, username, password, updated_at, created_at) values (removed@removed.removed, Shawn Miller, , removed, 2018-07-23 16:42:57, 2018-07-23 16:42:57))

I also receive this same error when running: php artisan adldap:import user.name

For some reason even though it is using my sAMAccountName to find and authenticate me as indicated here:

[2018-07-23 16:40:07] local.INFO: User 'Shawn Miller' is being imported.  
[2018-07-23 16:40:07] local.INFO: User 'Shawn Miller' is being synchronized.  
[2018-07-23 16:40:07] local.INFO: User 'Shawn Miller' has been successfully synchronized.  
[2018-07-23 16:40:07] local.ERROR: Unable to import user Shawn Miller. SQLSTATE[42S22]: Column not found: 1054 Unknown column 'email' in 'field list' (SQL: insert into `users` (`email`, `name`, `username`, `password`, `updated_at`, `created_at`) values (removed@removed.removed, Shawn Miller, ,removed, 2018-07-23 16:40:07, 2018-07-23 16:40:07))  
[2018-07-23 16:42:57] local.INFO: User 'Shawn Miller' has been successfully found for authentication.  
[2018-07-23 16:42:57] local.INFO: User 'Shawn Miller' is being imported.  
[2018-07-23 16:42:57] local.INFO: User 'Shawn Miller' is being synchronized.  
[2018-07-23 16:42:57] local.INFO: User 'Shawn Miller' has been successfully synchronized.  
[2018-07-23 16:42:57] local.INFO: User 'Shawn Miller' is authenticating with username: 'Shawn Miller'  
[2018-07-23 16:42:57] local.INFO: User 'Shawn Miller' has successfully passed LDAP authentication.  
[2018-07-23 16:42:57] local.ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'email' in 'field list' (SQL: insert into `users` (`email`, `name`, `username`, `password`, `updated_at`, `created_at`) values (removed@removed.removed, Shawn Miller, , removed, 2018-07-23 16:42:57, 2018-07-23 16:42:57)) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'email' in 'field list' (SQL: insert into `users` (`email`, `name`, `username`, `password`, `updated_at`, `created_at`) values (removed@removed.removed, Shawn Miller, , removed, 2018-07-23 16:42:57, 2018-07-23 16:42:57)) at /home/shawn/Documents/Sites/firefly/vendor/laravel/framework/src/Illuminate/Database/Connection.php:664, PDOException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'email' in 'field list' at /home/shawn/Documents/Sites/firefly/vendor/laravel/framework/src/Illuminate/Database/Connection.php:452)
[stacktrace]

it is trying to insert a blank username into the database. It feels like Laravel is still trying to insert into the database the way it wants so I'm not sure if this is a Laravel issue I'm trying to solve or a Adldap2 issue or an AD issue or a me issue. It feels like Laravel is still trying to use e-mail as the username and more or less ignoring my username configs. Maybe I'm just missing something important?

adldap.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Connections
    |--------------------------------------------------------------------------
    |
    | This array stores the connections that are added to Adldap. You can add
    | as many connections as you like.
    |
    | The key is the name of the connection you wish to use and the value is
    | an array of configuration settings.
    |
    */

    'connections' => [

        'default' => [

            /*
            |--------------------------------------------------------------------------
            | Auto Connect
            |--------------------------------------------------------------------------
            |
            | If auto connect is true, Adldap will try to automatically connect to
            | your LDAP server in your configuration. This allows you to assume
            | connectivity rather than having to connect manually
            | in your application.
            |
            | If this is set to false, you **must** connect manually before running
            | LDAP operations.
            |
            */

            'auto_connect' => env('ADLDAP_AUTO_CONNECT', true),

            /*
            |--------------------------------------------------------------------------
            | Connection
            |--------------------------------------------------------------------------
            |
            | The connection class to use to run raw LDAP operations on.
            |
            | Custom connection classes must implement:
            |
            |  Adldap\Connections\ConnectionInterface
            |
            */

            'connection' => Adldap\Connections\Ldap::class,

            /*
            |--------------------------------------------------------------------------
            | Schema
            |--------------------------------------------------------------------------
            |
            | The schema class to use for retrieving attributes and generating models.
            |
            | You can also set this option to `null` to use the default schema class.
            |
            | For OpenLDAP, you must use the schema:
            |
            |   Adldap\Schemas\OpenLDAP::class
            |
            | For FreeIPA, you must use the schema:
            |
            |   Adldap\Schemas\FreeIPA::class
            |
            | Custom schema classes must implement Adldap\Schemas\SchemaInterface
            |
            */

            'schema' => Adldap\Schemas\ActiveDirectory::class,

            /*
            |--------------------------------------------------------------------------
            | Connection Settings
            |--------------------------------------------------------------------------
            |
            | This connection settings array is directly passed into the Adldap constructor.
            |
            | Feel free to add or remove settings you don't need.
            |
            */

            'connection_settings' => [

                /*
                |--------------------------------------------------------------------------
                | Account Prefix
                |--------------------------------------------------------------------------
                |
                | The account prefix option is the prefix of your user accounts in LDAP directory.
                |
                | This string is prepended to authenticating users usernames.
                |
                */

                'account_prefix' => env('ADLDAP_ACCOUNT_PREFIX', ''),

                /*
                |--------------------------------------------------------------------------
                | Account Suffix
                |--------------------------------------------------------------------------
                |
                | The account suffix option is the suffix of your user accounts in your LDAP directory.
                |
                | This string is appended to authenticating users usernames.
                |
                */

                'account_suffix' => env('ADLDAP_ACCOUNT_SUFFIX', ''),

                /*
                |--------------------------------------------------------------------------
                | Domain Controllers
                |--------------------------------------------------------------------------
                |
                | The domain controllers option is an array of servers located on your
                | network that serve Active Directory. You can insert as many servers or
                | as little as you'd like depending on your forest (with the
                | minimum of one of course).
                |
                | These can be IP addresses of your server(s), or the host name.
                |
                */

                'domain_controllers' => explode(' ', env('ADLDAP_CONTROLLERS', 'removed')),

                /*
                |--------------------------------------------------------------------------
                | Port
                |--------------------------------------------------------------------------
                |
                | The port option is used for authenticating and binding to your LDAP server.
                |
                */

                'port' => env('ADLDAP_PORT', 389),

                /*
                |--------------------------------------------------------------------------
                | Timeout
                |--------------------------------------------------------------------------
                |
                | The timeout option allows you to configure the amount of time in
                | seconds that your application waits until a response
                | is received from your LDAP server.
                |
                */

                'timeout' => env('ADLDAP_TIMEOUT', 5),

                /*
                |--------------------------------------------------------------------------
                | Base Distinguished Name
                |--------------------------------------------------------------------------
                |
                | The base distinguished name is the base distinguished name you'd
                | like to perform query operations on. An example base DN would be:
                |
                |        dc=corp,dc=acme,dc=org
                |
                | A correct base DN is required for any query results to be returned.
                |
                */

                'base_dn' => env('ADLDAP_BASEDN', 'DC=removed,DC=removed'),

                /*
                |--------------------------------------------------------------------------
                | Administrator Account Suffix / Prefix
                |--------------------------------------------------------------------------
                |
                | This option allows you to set a different account prefix and suffix
                | for your configured administrator account upon binding.
                |
                | If left empty or set to `null`, your `account_prefix` and
                | `account_suffix` options above will be used.
                |
                */

                'admin_account_prefix' => env('ADLDAP_ADMIN_ACCOUNT_PREFIX', ''),
                'admin_account_suffix' => env('ADLDAP_ADMIN_ACCOUNT_SUFFIX', ''),

                /*
                |--------------------------------------------------------------------------
                | Administrator Username & Password
                |--------------------------------------------------------------------------
                |
                | When connecting to your LDAP server, a username and password is required
                | to be able to query and run operations on your server(s). You can
                | use any user account that has these permissions. This account
                | does not need to be a domain administrator unless you
                | require changing and resetting user passwords.
                |
                */

                'admin_username' => env('ADLDAP_ADMIN_USERNAME', 'DN=removed'),
                'admin_password' => env('ADLDAP_ADMIN_PASSWORD', 'removed'),

                /*
                |--------------------------------------------------------------------------
                | Follow Referrals
                |--------------------------------------------------------------------------
                |
                | The follow referrals option is a boolean to tell active directory
                | to follow a referral to another server on your network if the
                | server queried knows the information your asking for exists,
                | but does not yet contain a copy of it locally.
                |
                | This option is defaulted to false.
                |
                */

                'follow_referrals' => false,

                /*
                |--------------------------------------------------------------------------
                | SSL & TLS
                |--------------------------------------------------------------------------
                |
                | If you need to be able to change user passwords on your server, then an
                | SSL or TLS connection is required. All other operations are allowed
                | on unsecured protocols.
                | 
                | One of these options are definitely recommended if you 
                | have the ability to connect to your server securely.
                |
                */

                'use_ssl' => env('ADLDAP_USE_SSL', false),
                'use_tls' => env('ADLDAP_USE_TLS', false),

            ],

        ],

    ],

];

adldap_auth.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Connection
    |--------------------------------------------------------------------------
    |
    | The LDAP connection to use for laravel authentication.
    |
    | You must specify connections in your `config/adldap.php` configuration file.
    |
    | This must be a string.
    |
    */

    'connection' => env('ADLDAP_CONNECTION', 'default'),

    /*
    |--------------------------------------------------------------------------
    | Provider
    |--------------------------------------------------------------------------
    |
    | The LDAP authentication provider to use depending
    | if you require database synchronization.
    |
    | For synchronizing LDAP users to your local applications database, use the provider:
    |
    | Adldap\Laravel\Auth\DatabaseUserProvider::class
    |
    | Otherwise, if you just require LDAP authentication, use the provider:
    |
    | Adldap\Laravel\Auth\NoDatabaseUserProvider::class
    |
    */

    'provider' => Adldap\Laravel\Auth\DatabaseUserProvider::class,

    /*
    |--------------------------------------------------------------------------
    | Rules
    |--------------------------------------------------------------------------
    |
    | Rules allow you to control user authentication requests depending on scenarios.
    |
    | You can create your own rules and insert them here.
    |
    | All rules must extend from the following class:
    |
    |   Adldap\Laravel\Validation\Rules\Rule
    |
    */

    'rules' => [

        // Denys deleted users from authenticating.

        Adldap\Laravel\Validation\Rules\DenyTrashed::class,

        // Allows only manually imported users to authenticate.

        // Adldap\Laravel\Validation\Rules\OnlyImported::class,

    ],

    /*
    |--------------------------------------------------------------------------
    | Scopes
    |--------------------------------------------------------------------------
    |
    | Scopes allow you to restrict the LDAP query that locates
    | users upon import and authentication.
    |
    | All scopes must implement the following interface:
    |
    |   Adldap\Laravel\Scopes\ScopeInterface
    |
    */

    'scopes' => [

        // Only allows users with a user principal name to authenticate.
        // Remove this if you're using OpenLDAP.
        Adldap\Laravel\Scopes\UpnScope::class,

        // Only allows users with a uid to authenticate.
        // Uncomment if you're using OpenLDAP.
        // Adldap\Laravel\Scopes\UidScope::class,

    ],

    'usernames' => [

        /*
        |--------------------------------------------------------------------------
        | LDAP
        |--------------------------------------------------------------------------
        |
        | Discover:
        |
        |   The discover value is the users attribute you would
        |   like to locate LDAP users by in your directory.
        |
        |   For example, using the default configuration below, if you're
        |   authenticating users with an email address, your LDAP server
        |   will be queried for a user with the a `userprincipalname`
        |   equal to the entered email address.
        |
        | Authenticate:
        |
        |   The authenticate value is the users attribute you would
        |   like to use to bind to your LDAP server.
        |
        |   For example, when a user is located by the above 'discover'
        |   attribute, the users attribute you specify below will
        |   be used as the username to bind to your LDAP server.
        |
        */

        'ldap' => [

            'discover' => 'sAMAccountName',

            'authenticate' => 'cn',

        ],

        /*
        |--------------------------------------------------------------------------
        | Eloquent
        |--------------------------------------------------------------------------
        |
        | The value you enter is the database column name used for locating
        | the local database record of the authenticating user.
        |
        | If you're using a `username` column instead, change this to `username`.
        |
        | This option is only applicable to the DatabaseUserProvider.
        |
        */

        'eloquent' => 'username',

        /*
        |--------------------------------------------------------------------------
        | Windows Authentication Middleware (SSO)
        |--------------------------------------------------------------------------
        |
        | Discover:
        |
        |   The 'discover' value is the users attribute you would
        |   like to locate LDAP users by in your directory.
        |
        |   For example, if 'samaccountname' is the value, then your LDAP server is
        |   queried for a user with the 'samaccountname' equal to the value of
        |   $_SERVER['AUTH_USER'].
        |
        |   If a user is found, they are imported (if using the DatabaseUserProvider)
        |   into your local database, then logged in.
        |
        | Key:
        |
        |    The 'key' value represents the 'key' of the $_SERVER
        |    array to pull the users account name from.
        |
        |    For example, $_SERVER['AUTH_USER'].
        |
        */

        'windows' => [

            'discover' => 'sAMAccountName',

            'key' => 'AUTH_USER',

        ],

    ],

    'passwords' => [

        /*
        |--------------------------------------------------------------------------
        | Password Sync
        |--------------------------------------------------------------------------
        |
        | The password sync option allows you to automatically synchronize users
        | LDAP passwords to your local database. These passwords are hashed
        | natively by Laravel using the bcrypt() method.
        |
        | Enabling this option would also allow users to login to their accounts
        | using the password last used when an LDAP connection was present.
        |
        | If this option is disabled, the local database account is applied a
        | random 16 character hashed password upon every login, and will
        | lose access to this account upon loss of LDAP connectivity.
        |
        | This option must be true or false and is only applicable
        | to the DatabaseUserProvider.
        |
        */

        'sync' => env('ADLDAP_PASSWORD_SYNC', true),

        /*
        |--------------------------------------------------------------------------
        | Column
        |--------------------------------------------------------------------------
        |
        | This is the column of your users database table
        | that is used to store passwords.
        |
        | Set this to `null` if you do not have a password column.
        |
        | This option is only applicable to the DatabaseUserProvider.
        |
        */

        'column' => 'password',

    ],

    /*
    |--------------------------------------------------------------------------
    | Login Fallback
    |--------------------------------------------------------------------------
    |
    | The login fallback option allows you to login as a user located on the
    | local database if active directory authentication fails.
    |
    | Set this to true if you would like to enable it.
    |
    | This option must be true or false and is only
    | applicable to the DatabaseUserProvider.
    |
    */

    'login_fallback' => env('ADLDAP_LOGIN_FALLBACK', true),

    /*
    |--------------------------------------------------------------------------
    | Sync Attributes
    |--------------------------------------------------------------------------
    |
    | Attributes specified here will be added / replaced on the user model
    | upon login, automatically synchronizing and keeping the attributes
    | up to date.
    |
    | The array key represents the users Laravel model key, and
    | the value represents the users LDAP attribute.
    |
    | This option must be an array and is only applicable
    | to the DatabaseUserProvider.
    |
    */

    'sync_attributes' => [

        'email' => 'mail',

        'name' => 'cn',

    ],

    /*
    |--------------------------------------------------------------------------
    | Logging
    |--------------------------------------------------------------------------
    |
    | User authentication attempts will be logged using Laravel's
    | default logger if this setting is enabled.
    |
    | No credentials are logged, only usernames.
    |
    | This is usually stored in the '/storage/logs' directory
    | in the root of your application.
    |
    | This option is useful for debugging as well as auditing.
    |
    | You can freely remove any events you would not like to log below,
    | as well as use your own listeners if you would prefer.
    |
    */

    'logging' => [

        'enabled' => true,

        'events' => [

            \Adldap\Laravel\Events\Importing::class => \Adldap\Laravel\Listeners\LogImport::class,
            \Adldap\Laravel\Events\Synchronized::class => \Adldap\Laravel\Listeners\LogSynchronized::class,
            \Adldap\Laravel\Events\Synchronizing::class => \Adldap\Laravel\Listeners\LogSynchronizing::class,
            \Adldap\Laravel\Events\Authenticated::class => \Adldap\Laravel\Listeners\LogAuthenticated::class,
            \Adldap\Laravel\Events\Authenticating::class => \Adldap\Laravel\Listeners\LogAuthentication::class,
            \Adldap\Laravel\Events\AuthenticationFailed::class => \Adldap\Laravel\Listeners\LogAuthenticationFailure::class,
            \Adldap\Laravel\Events\AuthenticationRejected::class => \Adldap\Laravel\Listeners\LogAuthenticationRejection::class,
            \Adldap\Laravel\Events\AuthenticationSuccessful::class => \Adldap\Laravel\Listeners\LogAuthenticationSuccess::class,
            \Adldap\Laravel\Events\DiscoveredWithCredentials::class => \Adldap\Laravel\Listeners\LogDiscovery::class,
            \Adldap\Laravel\Events\AuthenticatedWithWindows::class => \Adldap\Laravel\Listeners\LogWindowsAuth::class,
            \Adldap\Laravel\Events\AuthenticatedModelTrashed::class => \Adldap\Laravel\Listeners\LogTrashedModel::class,

        ],
    ],

];

Steps To Reproduce:

stevebauman commented 6 years ago

Hi @shawnbyday,

You need to modify your sync_attributes configuration if you're using a username instead of email for authentication:

'sync_attributes' => [

    'email' => 'mail', // Remove

    'username' => 'samaccountname', // Add

    'name' => 'cn',

],

Please read the quick-start as it walks you through this process if you're using a username:

https://github.com/Adldap2/Adldap2-Laravel/blob/master/docs/quick-start.md

stevebauman commented 6 years ago

If you still encounter issues, comment back and I'll re-open this.