DirectoryTree / LdapRecord-Discussions

A place to ask questions, get help, or share what you've built with LdapRecord.
4 stars 1 forks source link

Trouble using LdapRecord + Passport + Laravel + API #17

Open merlinnusr opened 3 years ago

merlinnusr commented 3 years ago

ok, I'm trying to create a simple API with authetication with a LDAP server ldap.forumsys.com this is a test ldap server but I get this error

BadMethodCallException with message 'Method Illuminate\Auth\RequestGuard::attempt does not exist.'

I'm not sure if this is an passport error or a ldaprecord error.

I check my connection and its correct

docker exec -it api php artisan ldap:test
Testing LDAP connection [default]...
+------------+------------+----------+-------------------------+---------------+
| Connection | Successful | Username | Message                 | Response Time |
+------------+------------+----------+-------------------------+---------------+
| default    | ✔ Yes      |          | Successfully connected. | 271.31ms      |
+------------+------------+----------+-------------------------+---------------+

.env file

LDAP_LOGGING=true
LDAP_CONNECTION=default
LDAP_HOST=ldap.forumsys.com
LDAP_USERNAME=null
LDAP_PASSWORD=null
LDAP_PORT=389
LDAP_BASE_DN="DC=example,DC=com"
LDAP_TIMEOUT=5
LDAP_SSL=false
LDAP_TLS=false

config/auth.php

return [
    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
            'hash' => false,
        ],
        'api' => [
            'driver' => 'passport',
            'provider' => 'ldap',
            'hash' => false,
        ],
    ],
    'providers' => [
        'ldap' => [
            'driver' => 'ldap',
            'model' => LdapRecord\Models\ActiveDirectory\User::class,
            'database' => [
                'model' => App\Models\User::class,
                'sync_passwords' => false,
                'sync_attributes' => [
                    'name' => 'cn',
                    'email' => 'mail',
                ],
            ],
        ],
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

    ],
]

App\Models\User I alredy implemented LdapRecord\Laravel\Auth\LdapAuthenticatable; and LdapRecord\Laravel\Auth\AuthenticatesWithLdap; as documentation says

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes; //línea necesaria
use App\Http\Traits\LogTrait;
use Spatie\Permission\Traits\HasRoles;
use Laravel\Passport\HasApiTokens;
use LdapRecord\Models\Model;
use LdapRecord\Laravel\Auth\LdapAuthenticatable;
use LdapRecord\Laravel\Auth\AuthenticatesWithLdap;
class User extends Authenticatable implements LdapAuthenticatable
{
    use HasFactory, Notifiable, 
    SoftDeletes,LogTrait,
    Authenticatable,HasRoles, HasApiTokens, 
    AuthenticatesWithLdap;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'username',
        'email',
        'password',
        'modules',
        'bearer_token',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [

        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    protected $dates = ['deleted_at'];

    public function employee()
    {
        return $this->hasOne('App\Models\Employee');
    }
    public function ticket_historics()
    {
        return $this->hasMany('App\Models\TicketHistoric');
    }
    public function department()
    {
        return $this->hasOne('App\Models\Department');
    }
}

So when I try to authenticate with a User I get this error. Is this a right way to use ldap in API mode?

Auth::attempt(['email' => 'tesla', 'password' => 'password'])
BadMethodCallException with message 'Method Illuminate\Auth\RequestGuard::attempt does not exist.'
stevebauman commented 3 years ago

Hi @merlinnusr,

If you're attempting to create a simple API, I would heavily suggest moving to Laravel Sanctum instead of using Laravel Passport. Laravel Passport requires a decent understanding of OAuth2, along with some heavy setup and configuration.

Here's a step-by-step guide for getting up and running with Laravel Sanctum:

https://laravel.com/docs/8.x/sanctum#spa-authentication

To answer to your specific issue -- Laravel Passport does not use credentials to authenticate users. It uses tokens. Therefore it does not have the attempt() method as the exception describes.

https://laracasts.com/discuss/channels/laravel/method-illuminateauthrequestguardattempt-does-not-exist#best-reply-559749

You must first issue a token (which creates a token inside of your database owned by the user), then provide that token alongside requests to your protected application routes. This is how Laravel Passport "authenticates" requests made to protected routes -- not by providing user credentials.

Laravel Sanctum allows you to use session cookies alongside tokens -- making it a great choice on building an API.

Hope this helps! 👍