Adldap2 / Adldap2-Laravel

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

Successfully logged in -- Endless Loop #538

Closed macmedia closed 6 years ago

macmedia commented 6 years ago

Description:

Hello!

Im able to authenticate successfully but Im not redirected past the login screen. The logs show everything worked but Im returned to the /login again with out any errors.

Im only interested in the authentication part. No need to save anything to a database (NoDatabaseUserProvider).

local.INFO: User '{MyUserName}' has been successfully found for authentication.  
local.INFO: User '{MyUserName}' is authenticating with username: 'uid={uid},cn=users,dc=mydomain,dc=com'  
local.INFO: User '{MyUserName}' has successfully passed LDAP authentication.  
local.INFO: User '{MyUserName}' has been successfully logged in. 

Steps To Reproduce:

Every login is an endless loop. If I try to visit the url mydomain.com/home, I'm redirected to /login again.

.env

ADLDAP_CONTROLLERS='mydomain.com'
ADLDAP_BASEDN='cn=users,dc=mydomain,dc=com'
CACHE_DRIVER=file
SESSION_DRIVER=file

adldap_auth.php

return [
    'connection' => env('ADLDAP_CONNECTION', 'default'),
    'provider' => Adldap\Laravel\Auth\NoDatabaseUserProvider::class,
    'rules' => [Adldap\Laravel\Validation\Rules\DenyTrashed::class],
    'scopes' => [Adldap\Laravel\Scopes\UidScope::class],
    'usernames' => [
         'ldap' => [
             'discover' => 'uid',
             'authenticate' => 'dn'
        ]
    ],
    'login_fallback' => env('ADLDAP_LOGIN_FALLBACK', false),
    'sync_attributes' => [
        'username' => 'uid',
        'name' => 'cn',
    ]
];

adldap.php

return [
    'connections' => [
        'default' => [
            'auto_connect' => env('ADLDAP_AUTO_CONNECT', true),
            'connection' => Adldap\Connections\Ldap::class,
            'schema' => Adldap\Schemas\OpenLDAP::class,
            'connection_settings' => [
                'account_prefix' => env('ADLDAP_ACCOUNT_PREFIX', ''),
                'account_suffix' => env('ADLDAP_ACCOUNT_SUFFIX', ''),
                'domain_controllers' => explode(' ', env('ADLDAP_CONTROLLERS', '')),
                'port' => env('ADLDAP_PORT', 389),
                'timeout' => env('ADLDAP_TIMEOUT', 5),
                'base_dn' => env('ADLDAP_BASEDN', ''),
                'admin_account_prefix' => env('ADLDAP_ADMIN_ACCOUNT_PREFIX', ''),
                'admin_account_suffix' => env('ADLDAP_ADMIN_ACCOUNT_SUFFIX', ''),
                'admin_username' => env('ADLDAP_ADMIN_USERNAME', ''),
                'admin_password' => env('ADLDAP_ADMIN_PASSWORD', ''),
                'follow_referrals' => false,
                'use_ssl' => env('ADLDAP_USE_SSL', false),
                'use_tls' => env('ADLDAP_USE_TLS', false),
            ],
        ],
    ],
];

LoginController.php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{

    use AuthenticatesUsers;

    protected $redirectTo = '/home';
    protected $username = 'username';

    public function username()
    {
        return 'uid';
    }

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
}

login.blade.php

...
<div class="form-group row">
  <label for="uid" class="col-sm-4 col-form-label text-md-right">{{ __('User Name') }}</label>

  <div class="col-md-6">
    <input id="uid" type="text" class="form-control{{ $errors->has('uid') ? ' is-invalid' : '' }}" name="uid" value="{{ old('uid') }}"
      required autofocus> @if ($errors->has('uid'))
    <span class="invalid-feedback">
      <strong>{{ $errors->first('uid') }}</strong>
    </span>
    @endif
  </div>
</div>
...
gdhnz commented 6 years ago

I've got this same issue after changing the session driver to database.

If I set the session driver to files, I get redirected on a successful login as expected.

stevebauman commented 6 years ago

Hi @macmedia, as @gdhnz suggested, what is your session driver currently?

macmedia commented 6 years ago

Hi @stevebauman. My .env files has the session driver set to file:

SESSION_DRIVER=file
stevebauman commented 6 years ago

Can you try changing session drivers? Such as database and see if you encounter this issue?

This seems like it may be an application (Laravel) issue...

gdhnz commented 6 years ago

Looking further with regards to the endless loop when using database sessions, the user_id column in the sessions table is of type int but as auth is using the NoDatabaseProvider, I'm guessing this isn't being set.

stevebauman commented 6 years ago

Hmm, are you running 32 bit or 64 bit PHP?

gdhnz commented 6 years ago

64 bit.

macmedia commented 6 years ago

I have tried Database, file, cookie. All do the same loop.

gdhnz commented 6 years ago

It looks like something not being returned to laravel. The $guard variable in the RedirectIfAuthenticated middleware is empty so it's redirecting back to the login form.

macmedia commented 6 years ago

When I look at authenticated function invendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php

protected function authenticated(Request $request, $user)
{
    dd(Auth::guard()); // Check if guard is null
 }

I see a value for Auth::guard()

SessionGuard {#688 ▼
  #name: "web"
  #lastAttempted: User {#781 ▶}
  #viaRemember: false
  #session: Store {#651 ▼
    #id: "Ec58FMdxrZOp6GE9csz8bbPXaRNpWSqwKJXGTnZ9"
    #name: "laravel_session"
    #attributes: array:5 [▶]
    #handler: FileSessionHandler {#650 ▶}
    #started: true
  }
  #cookie: CookieJar {#640 ▶}
  #request: Request {#59 ▶}
  #events: Dispatcher {#39 ▶}
  #loggedOut: false
  #recallAttempted: false
  #user: User {#781 ▼
    +exists: true
    #query: Builder {#764 ▶}
    #schema: OpenLDAP {#742}
    #modifications: []
    +dateFormat: "Y-m-d H:i:s"
    #timestampFormat: "YmdHis.0Z"
    #attributes: array:33 [▶]
    #original: array:33 [▶]
  }
  #provider: NoDatabaseUserProvider {#687}
}
gdhnz commented 6 years ago

I've just setup a new laravel install with authentication, added adldap2/adldap2-laravel and configured the auth to use samaccountname with the NoDatabaseUserProvider and it works as expected for file sessions but not for database sessions.

Using DatabaseUserProvider and database sessions work as expected.

stevebauman commented 6 years ago

Hmmm, @gdhnz, is there anything in your log file when authenticating using NoDatabaseUserProvider and database sessions?

gdhnz commented 6 years ago

It tells me it's all good.

[2018-05-03 21:00:36] local.INFO: User 'myusername' has been successfully found for authentication.  
[2018-05-03 21:00:36] local.INFO: User 'myusername' is authenticating with username: 'myusername'  
[2018-05-03 21:00:36] local.INFO: User 'myusername' has successfully passed LDAP authentication.  
[2018-05-03 21:00:36] local.INFO: User 'myusername' has been successfully logged in.  
stevebauman commented 6 years ago

Hmm, and nothing inside your database table?

Have you also tried clearing your cached config after changing the session driver to database using php artisan config:clear?

gdhnz commented 6 years ago

There is a row in the session table but no user_id

gdhnz commented 6 years ago

Running php artisan config:clear makes no difference.

stevebauman commented 6 years ago

Ohhh yes hang on, this is because the default session table created by Laravel uses an unsigned integer as the user_id.

User ID's coming from LDAP will be GUIDs, which contain dashes and letters.

Can you change this migration to use varchar for user_id instead and try again?

You'll have to drop and re-create this table, or change the user_id column to a varchar data type.

gdhnz commented 6 years ago

👍 👍 👍

Database sessions now working.

Not sure if this sorts the OP's issue though 😃

stevebauman commented 6 years ago

Awesome thanks @gdhnz! Appreciate the quick responses. This slipped my mind completely. I'll put this in the documentation for the NoDatabaseUserProvider.

@macmedia, can you try this change with the database session driver and see if it resolves your issue?

macmedia commented 6 years ago

I also tried to create a new project and Im still getting the same looping. Here are my steps.

Setup Info

Commands

composer create-project laravel/laravel ldap && cd ldap
composer require adldap2/adldap2-laravel
php artisan make:auth
php artisan vendor:publish
php artisan session:table
php artisan migrate

Files edited

Edit: create_sessions_table.php

Changed to: $table->string('user_id')->nullable(); (before migration)

Edit: .env

APP_ENV=local
DB_CONNECTION=mysql
CACHE_DRIVER=file
SESSION_DRIVER=file

Also tried (same return to login.php)

php artisan cache:clear && php artisan view:clear

SESSION_DRIVER=database

The database records this record

FM1m56hK1IBrSJe0urR6e8EvJZLhB7roChTcnvj0    NULL    127.0.0.1   Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15   YTo1OntzOjY6Il90b2tlbiI7czo0MDoiaTFkNXdXM09sQ1NIOTE5bVJhN3JrWXRmR1pPMTJTSnkydE95YkdUaCI8czo5OiJfcHJldmlvdXMiO2Z6MTp7czozLiJ1cmwiO3M6MjI6Imh0dHA6Ly9sZGFwLnRlc3QvbG9naW4iO31zOjY6Il9mbGFzaCI7YToyOntzOjM6Im9sMCI7YTowOnt9czozOiJuZXciO2E6MDp7fX1zOjUwOiJsb2dpbl93ZWJfNTliMEM2YWRkYzJiMmY5ADAxNTgwZjAxNGM3ZjU4ZWE0ZTMwOTg5ZCI7TjtzOjM6InVybCI7YToxOntzOjg6ImludGVuZGVkIjtzOjIxOiJodHRwOi8vbGRhcC50ZXN0L2hvbWUiO319    1522451866

Edit: auth.php

'providers' => [
        'users' => [
            'driver' => 'adldap',
            'model' => App\User::class,
        ],
]

Edit: adldap.php/adlap_auth.php

    'connection' => env('ADLDAP_CONNECTION', 'default'),
    'provider' => Adldap\Laravel\Auth\NoDatabaseUserProvider::class,
    'rules' => [Adldap\Laravel\Validation\Rules\DenyTrashed::class,],
    'scopes' => [Adldap\Laravel\Scopes\UidScope::class,],
    'usernames' => [
        'ldap' => [
            'discover' => 'uid',
            'authenticate' => 'dn',
        ],
        'eloquent' => 'email',
        'windows' => [
            'discover' => 'uid',
            'key' => 'AUTH_USER',
        ],
    ],
    'passwords' => [
        'sync' => env('ADLDAP_PASSWORD_SYNC', false),
        'column' => 'password',
    ],
    'login_fallback' => env('ADLDAP_LOGIN_FALLBACK', false),
     // Have tried:
     // 'id' => 'uid',
     // 'user' => 'uid',
     // 'userid' => 'uid',
     // 'username' => 'uid',
    'sync_attributes' => [
        'username' => 'uid',
        'name' => 'cn',
    ],
'default' => [
    'auto_connect' => env('ADLDAP_AUTO_CONNECT', true),
    'connection' => Adldap\Connections\Ldap::class,
    'schema' => Adldap\Schemas\OpenLDAP::class,
    'connection_settings' => [
        'account_prefix' => env('ADLDAP_ACCOUNT_PREFIX', ''),
        'account_suffix' => env('ADLDAP_ACCOUNT_SUFFIX', ''),
        'domain_controllers' => explode(' ', env('ADLDAP_CONTROLLERS', '{domainname}')),
        'port' => env('ADLDAP_PORT', 389),
        'timeout' => env('ADLDAP_TIMEOUT', 5),
        'base_dn' => env('ADLDAP_BASEDN', 'cn=users,dc={domainame}c,dc=com'),
        'admin_account_prefix' => env('ADLDAP_ADMIN_ACCOUNT_PREFIX', ''),
        'admin_account_suffix' => env('ADLDAP_ADMIN_ACCOUNT_SUFFIX', ''),
        'admin_username' => env('ADLDAP_ADMIN_USERNAME', ''),
        'admin_password' => env('ADLDAP_ADMIN_PASSWORD', ''),
        'follow_referrals' => false,
        'use_ssl' => env('ADLDAP_USE_SSL', false),
        'use_tls' => env('ADLDAP_USE_TLS', false),
    ],
],

Edit: Http/Controllers/Auth/LoginController.php

public function username()
{
    return 'uid';
}

Edit: resources/views/auth/login.blade.php

Changed to 'uid' from email
<div class="form-group row">
    <label class="col-sm-4 col-form-label text-md-right" for="uid">
        {{ __('User Name') }}
    </label>
    <div class="col-md-6">
        <input autofocus="" class="form-control{{ $errors->has('uid') ? ' is-invalid' : '' }}" id="uid" name="uid" required="" type="text" value="{{ old('uid') }}">
            @if ($errors->has('uid'))
            <span class="invalid-feedback">
                <strong>
                    {{ $errors->first('uid') }}
                </strong>
            </span>
            @endif
        </input>
    </div>
</div>

Loggin In

First php artisan cache:clear && php artisan view:clear

Entered: username Entered: password

Results

Returned to login page

Log file

[2018-05-04 16:32:29] local.INFO: User '{username}' has been successfully found for authentication.  
[2018-05-04 16:32:29] local.INFO: User '{username}' is authenticating with username: 'uid={uid},cn=users,dc={domainname},dc=com'  
[2018-05-04 16:32:29] local.INFO: User '{username}' has successfully passed LDAP authentication.  
[2018-05-04 16:32:29] local.INFO: User '{username}' has been successfully logged in.  
macmedia commented 6 years ago

Possible fix? Or do I have something not configured correctly?

Does adldap2/adldap2-laravel have a way to override vendor/adldap2/adldap2/src/Schemas/OpenLDAP.php

I made a change to the OpenLDAP.php schema and eveything worked! I was able to login and redirected to /home page.

I tested both: SESSION_DRIVER=file SESSION_DRIVER=database

Both successfully logged me in.

    public function objectGuid()
    {
        //return 'entryuuid';
        return 'apple-generateduid';
    }
screen shot 2018-05-04 at 11 40 00 am
stevebauman commented 6 years ago

Hi @macmedia, that's great that you figured out your issue!

Are you sure you're using OpenLDAP? I've never seen an OpenLDAP server with that GUID name before.

To answer your question about customizing schemas, yes absolutely, here are the steps:

  1. Create your own schema (for example app/Schemas/CustomSchema.php)
  2. Extend from the OpenLDAP schema currently in Adldap2
  3. Override the objectGuid() method with your above working attribute
  4. Change the schema in your config/adldap.php file to your own custom schema

Can you give that a shot and let me know?

macmedia commented 6 years ago

Thanks @stevebauman. The server is a Mac running OSX 10.12 and OpenLDAP version is: OpenLDAP: slapd 2.4.28 (Oct 14 2016 16:25:43)

I did create a custom Schema and it is working.

class AppleOpenLDAP extends \Adldap\Schemas\OpenLDAP
{
    /**
     * {@inheritdoc}
     */
    public function objectGuid()
    {
        return 'apple-generateduid';
    }
}
test98123456 commented 6 years ago

I've got this same issue when i configure adldap step by step as auth.md the storage/logs seems that works fine,but when i auth success, redirect to login page loopless