DirectoryTree / LdapRecord-Laravel

Multi-domain LDAP Authentication & Management for Laravel.
https://ldaprecord.com/docs/laravel/v3
MIT License
508 stars 54 forks source link

Is it possible to use Laravel Passport with LdapRecord-Laravel? #111

Closed ovitor closed 4 years ago

ovitor commented 4 years ago

Hi, thanks in advance and sorry to use this channel to ask a question and not report a bug.

I'm trying to setup Passport in a project that already works with LdapRecord. I followed the initial official documentation from Laravel Passport site and then I changed the files specified in LdapRecord docs like guards and providers in config/auth.php:

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'ldap',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'ldap',
            'hash' => false,
        ],
    ],
...
'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

        'ldap' => [
            'driver' => 'ldap',
            'model' => LdapRecord\Models\ActiveDirectory\User::class,
            'rules' => [],
            'database' => [
                'model' => App\User::class,
                'sync_passwords' => false
            ],
        ],
]

I think I must create another LoginController that handles the Ldap auth and create the Passport token, but don't know if when I use Auth::attempt (see below) I'm already using LdapRecord methods to authenticate using ldap provider.

public function login(Request $request)
    {
            if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) {
            $user = Auth::user();
            $success['token'] =  $user->createToken('intranet')-> accessToken;
            return response()->json(['success' => $success], 200);
        }
        else {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
    }
stevebauman commented 4 years ago

Hi @vcml10,

If you're using the ldap driver for authentication, you must pass in the attribute name you would like to locate the user by for authentication.

You can refer to this documentation for more information:

https://ldaprecord.com/docs/laravel/auth/quickstart/#database-controller-setup

For example, using your code:

// Before...
if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) {
    //
}

// After...
if (Auth::attempt(['samaccountname' => $request->username, 'password' => $request->password])) {
    //
}

I also see that you have no sync_attributes defined in your config/auth.php file inside of the ldap provider. Is this intended?

// ...

'ldap' => [
    'driver' => 'ldap',
    'model' => LdapRecord\Models\ActiveDirectory\User::class,
    'rules' => [],
    'database' => [
        'model' => App\User::class,
        'sync_passwords' => false,
    ],
],

If no sync attributes are defined, you will only be able to login pre-existing users into your database, otherwise, an exception will be thrown if you have any non-nullable database columns for a brand new LDAP user logging in (for example, the name column default in the Laravel users migration).

ovitor commented 4 years ago

Hi @stevebauman . Thanks for your answer. Just changed the attribute name and all works very well! In fact I'm using sync_attributes, I just deleted a few lines while I copied here.

stevebauman commented 4 years ago

Awesome, glad you’re up and running!

brinkonaut commented 4 years ago

LdapRecord could support Passport out of the box if the following class include:

public function findForPassport($username)
{
    return $this->where('email', $username)->first();
}

public function findAndValidateForPassport($username, $password)
{
    if(Auth::attempt(['email' => $username, 'password' => $password])) {
        return Auth::user();
    }

I have changed it to use the username without the @test.email:

<?php

namespace App\Models;

use Illuminate\Support\Facades\Auth;
use Laravel\Passport\HasApiTokens;
use LdapRecord\Models\ActiveDirectory\User;

class ActiveDirectoryUser extends User
{
    public function findForPassport($username)
    {
        return $this->where('samaccountname', $username)->first();
    }

    public function findAndValidateForPassport($username, $password)
    {
        if(Auth::attempt(['samaccountname' => $username, 'password' => $password])) {
            return Auth::user();
        }
    }
}
jcrann commented 4 years ago

Hello,

I've got passport installed and LDAPRecord works great, Im trying to integrate the 2 now.

What file do I add these lines of code to? I'm using laravel 7. ` public function findForPassport($username) { return $this->where('samaccountname', $username)->first(); }

public function findAndValidateForPassport($username, $password)
{
    if(Auth::attempt(['samaccountname' => $username, 'password' => $password])) {
        return Auth::user();
    }
}`

Any help would be greatly appreciated.

brinkonaut commented 4 years ago

Hello,

I've got passport installed and LDAPRecord works great, Im trying to integrate the 2 now.

What file do I add these lines of code to? I'm using laravel 7. ` public function findForPassport($username) { return $this->where('samaccountname', $username)->first(); }

public function findAndValidateForPassport($username, $password)
{
    if(Auth::attempt(['samaccountname' => $username, 'password' => $password])) {
        return Auth::user();
    }
}`

Any help would be greatly appreciated.

You have to create a separate model class just for LDAPRecord. In your config/auth.php you have to use your custom model then:

'ldap' => [
            'driver' => 'ldap',
            'model' => \App\Models\ActiveDirectoryUser::class,
 ],