Подтвердить что ты не робот

Laravel Passport Password Grant - Ошибка аутентификации клиента

Услышав много о паспорте laravel, я подумал о том, чтобы внедрить его в свой новый проект, где мне нужно создать API, который будет использоваться в мобильном приложении.

Так что мое мобильное приложение - это client, который в дальнейшем будет иметь своих пользователей.

Я выполнил шаги, упомянутые Тейлором, а также прочитал об этом здесь. В двух словах, я следовал этим шагам:

  1. Установлен laravel/passport.
  2. Создан пользователь сайта.
  3. Сгенерированные ключи паспорта php artisan passport:install
  4. Сгенерированные client_id и client_secret с использованием php artisan passport:client
  5. Добавлены маршруты redirection и callback в web.php
  6. Авторизовал пользователя и получил окончательный токен доступа.

Затем я попытался вызвать api/userAuthorization заголовка, содержащей значение Bearer eyJ0eXAiOiJKV1...(token)

Я получил данные. Довольно просто и аккуратно.

Но у пользователей моего приложения не будет этих деталей. Поэтому я подумал о настройке токенов паролей, которые идеально соответствуют моим требованиям.

Теперь начинается настоящая головная боль. Я пытался настроить это в течение последних 3 дней и постоянно получаю

{"error":"invalid_client","message":"Client authentication failed"}

Я испробовал практически все инструкции, которые следовал в Интернете: проблемы с перенаправлением, добавление решения Atleast One Scope, проблема P100Y и т.д.

Но я все еще получаю invalid client ошибку invalid client. Вот что я передаю через POSTMAN в oauth/token:

{
    "grant_type": "password,"
    "client_id": "3,"
    "client_secret": "8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g,"
    "username": "[email protected],"
    "password": "123456,"
    "scope": ""
}

Любая помощь будет оценена.

4b9b3361

Ответ 1

Сначала проверьте свои учетные данные, если они верны. Во-вторых, проверьте таблицу моделей, в которой используется \Laravel\Passport\HasApiTokens, который содержит столбец email, потому что по умолчанию он используется для идентификации пользователя при проверке учетных данных. если в таблице есть столбец username или любой другой столбец, который используется для проверки учетных данных, вы должны определить функцию findForPassport в этой модели. например,

public function findForPassport($username) {
       return self::where('username', $username)->first(); // change column name whatever you use in credentials
    }

Я использую имя пользователя и пароль для проверки пользователя, в {project_directory}\vendor\laravel\passport\src\Bridge\UserRepository.php

эта функция проверяет ваши учетные данные,

public function getUserEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity)
    {
        if (is_null($model = config('auth.providers.users.model'))) {
            throw new RuntimeException('Unable to determine user model from configuration.');
        }

        if (method_exists($model, 'findForPassport')) { // if you define the method in that model it will grab it from there other wise use email as key 
            $user = (new $model)->findForPassport($username);
        } else {
            $user = (new $model)->where('email', $username)->first();
        }

        if (! $user || ! $this->hasher->check($password, $user->password)) {
            return;
        }

        return new User($user->getAuthIdentifier());
    }

обратите внимание на второй оператор if, и вы узнаете, что там происходит.

надеюсь, что эта помощь:)

Ответ 2

Это может помочь вам в правильном направлении, потому что мы реализуем сам пароль.

1 - На шаге 4 вместо этого:

php artisan passport:install

выполните следующие действия, чтобы создать свой пароль. Клиент:

php artisan passport:client --password

Вышеупомянутая команда даст следующий вопрос, чтобы задать имя вашего клиента для предоставления пароля. Обязательно получите идентификатор и секрет этой новой записи в своей базе данных.

2 - Ваш объект POSTMAN Post request должен быть обернут внутри объекта, подобного следующему:

'form_params' => [
    'grant_type' => 'password',
    'client_id' => 'my_client-id',
    'client_secret' => 'my_client-secret',
    'username' => 'username or email', <-pass through variables or something
    'password' => 'my-user-password', <- pass through variables or something
    'scope' => '',
],

Обновление 1 10/12/2016:

В ходе дальнейшего расследования этого вопроса я столкнулся с тем же местом, в котором вы находитесь, и был вынужден погрузиться в кроличью нору паспорта.

В настоящее время из того, что я вижу, система установила идентификатор клиента как "authorization_code", когда он должен быть "паролем". Я исследую, как решить эту проблему, с которой вы столкнулись, когда я столкнулся с ней. Я отправлю код, чтобы помочь людям следовать дальше, где я был и что я делал, но сейчас 2:40, поэтому мне нужно немного поспать.

Обновление 2 10/12/2016

Отладка этой проблемы в течение 7 часов. В паспорте есть метод, который проверяет клиента. Этот метод использует входы, добавленные вами в объект (упомянутые выше), и пытается получить объект клиента через класс репозитория клиента на основе того, что вы прошли. Если клиент найден, он будет проверен, чтобы узнать, экземпляр объекта "Клиент" действительно существует в интерфейсе клиентского объекта, который СМОТРЕТЬ, как он извлекает учетные данные клиента из базы данных. Однако есть блок кода, который возвращает NULL. Из того, что я получаю в своем тестировании. Все поля вводятся должным образом до сих пор, но между репозиторием и интерфейсом, похоже, существует путаница. Это вызывает ошибку.

В конце концов, я чувствую, что приближаюсь к решению этой проблемы. Ваше терпение очень ценится. =)

Обновление 3 10/12/2016

После длительного периода отладки я обнаружил исходную проблему. Были поля, которые не совпадали. Короче говоря, это проблема установки.

SO

Решение в этом случае:

ДВОЙНАЯ ПРОВЕРКА ВСЕХ ПОЛЕЙ В базе данных с переданными учетными данными ВСЕ. Справа до периодов, тире, пробелов паролей, идентификатора клиента, секрет клиента, URI с перенаправлением VALID/URLs, grant_types и области действия (если вы их используете):

Убедитесь, что клиент в базе данных имеет ENUM из 1 в столбце "password_client", если вам не нужно создавать его, используя указанную выше команду php artisan, о которой я расскажу здесь:

php artisan passport:client --password

Убедитесь, что секрет, который вы передаете, совпадает с тем, что указано для этого клиента в символе базы данных для символа

Убедитесь, что идентификатор, который вы передаете, совпадает и имеет целочисленный тип данных.

Убедитесь, что для клиента есть какое-то имя.

Не беспокойтесь о столбце user_id при использовании паролей.

убедитесь, что маршрут правильный.

Убедитесь, что адрес электронной почты, который вы вводите (имя пользователя), является фактическим пользователем внутри вашей таблицы пользователей в вашей базе данных (или в любой другой таблице, которую вы настроили для системы laravel 5.3 в качестве таблицы ваших пользователей, я добавлю ссылку о том, как настройте систему laravel 5.3, чтобы принять другую таблицу пользователей по умолчанию, если это необходимо).

Убедитесь, что параметр grant_type правильно указан.

Убедитесь, что вы настроены на прием токена-ответчика-носителя (то есть access_token и refresh_token).

Кроме этого, начальные шаги, описанные в вышеприведенной части этого ответа, должны вернуть вас на правильный путь. Здесь есть и другие, которые упомянули о некоторых подобных шагах, которые полезны, но относятся к той же ошибке, которая связана с отдельной проблемой (что, я уверен, является результатом проблемы установки, связанной с их конкретной настройкой системы).

Я надеюсь, что это поможет.

Ответ 3

Попробуйте выполнить php artisan config:cache после всех команд паспорта.

Ответ 4

У меня была такая же проблема, и я получил исправление, установив заголовки basic.auth, с именем client_id и именем пользователя в качестве пароля.

Тогда он работал нормально.

Ответ 5

используйте приведенный ниже код для создания токена доступа, он работал у меня раньше:

$request->request->add([
      'client_id' => '2',
      'client_secret' => 'm3KtgNAKxq6Cm1WC6cDAXwR0nj3uPMxoRn3Ifr8L',
      'grant_type' => 'password',
      'username' => '[email protected]',
      'password' => 'pass22'
    ]);
    $tokenRequest = $request->create('/oauth/token', 'POST', $request->all());

    $token =  \Route::dispatch($tokenRequest);

Ответ 6

Мне удалось получить паспорт Laravel - Password_Grant_Token, работающий через RESTED (как сервис POSTMAN) без каких-либо дополнительных контроллеров или посредников. Вот как я это сделал!

Установите по умолчанию Auth-Scaffolding в laravel doc здесь
Установить паспорт doc here
Зарегистрировать пользователя через auth-scaffolding
Goto RESTED или POSTMAN, или любой другой подобный сервис
Проверьте данные в таблице oauth_clients для вашего form_params
С помощью RESTED через Request_body_form_data заголовки не записывают ваши form_params и отправляют запрос POST в */oauth/token (требуется полный url)

(требуемые form_params - grant_type, client_id, client_secret, имя пользователя и пароль)

Вы должны получить в результате объект с 4 ключами (token_type, expires_in, access_token и refresh_token) и состояние 200 OK.

Если бы все было успешным до сих пор...

Откройте другое окно RESTED:

Отправить запрос GET/api/user (требуется полный URL-адрес) В заголовках пишите 2 пары имя-значение (Accept = > application/json, Authorization = > Bearer ACCESS_TOKEN_GOTTEN_IN_PREVIOUS_REQUEST (to/oauth/token)

И это должно быть так. Вы должны получить объект пользователя в качестве ответа от/api/user.

Ответ 7

Попробуйте создать новый клиент с паролем, используя php artisan passport: client --password, тогда, скорее всего, пользователь не будет назначен этому клиенту с паролями. отредактируйте строку базы данных и добавьте в нее существующий идентификатор пользователя.

{
    "grant_type": "password,"
    "client_id": "" <- edited and added user id
    "client_secret": "8BU......," <- new secret
    "username": "[email protected]," <- email of above added user id
    "password": "123456,"<- password 
    "scope": ""
}

Надеюсь, вы сможете получить токен сейчас

Ответ 8

Проверьте URL-адрес перенаправления/обратного вызова, когда клиент настроен на сервере паспорта. Проверьте запись, в которой вы получаете идентификатор клиента и секрет, с тем, что URL-адрес перенаправления правильный.

Я получал ту же ошибку и обнаружил, что URL-адрес перенаправления неверен.

Он должен указывать на маршрут/обратный вызов (в примерах, которые дает Тейлор)

Ответ 9

{"error":"invalid_client","message":"Client authentication failed"}

означает, что client_id и client_secret, которые вы сейчас отправляете, являются одним из следующих:

  • client_id и client_secret отправляются не зарегистрированы на сервере oauth
  • client_id и client_secret отправляются не типа гранта, который вы указываете в теле сообщения

Для меня значение столбца password_client для этого конкретного клиента было 0. Я вручную изменил его на 1, но это не помогло. - Канав 4 октября в 3:25

Когда я прочитал ваш комментарий к одному из ответов, это очевидно, что вы используете неверный тип client_id и client_secret для потока потока паролей, поэтому ваш случай был последним. Вы можете проверить, что, найдя запись в таблице oauth_clients для предоставленных вами client_id и client_secret

"grant_type": "password,"    
"client_id": "3,"
"client_secret": "8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g,"

SELECT * FROM oauth_clients WHERE id = 3 AND secret = '8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g' AND password_client=1;

в вашей таблице oauth_clients, чтобы проверить, существует ли ваш поставляемый client_id и client_secret для потока предоставления пароля на вашем сервере oauth. Кроме того, вы не вручную меняете тип клиента, просто переключая значение этого столбца, вам нужно создать новый клиент для типа предоставления пароля.

php artisan migrate

Эта команда будет переносить файл миграции laravel/passport для создания двух клиентов по умолчанию для каждого типа, который в настоящее время поддерживается larvel/pat. Вы также можете создать клиент для потока предоставления пароля с помощью

php artisan passport:client --password

Если у вас есть новый клиент для типа типа пароля, попробуйте снова выполнить POSTing в /oauth/token, чтобы создать токен с новым сгенерированным client_id и client_secret

Ответ 10

Тщательно проверьте тип гранта.

{
    "grant_type": "password",
    "client_id": 2,
    "client_secret": 
    "username": ,
    "password": 
    "scope": ""
}

В приведенном выше примере это говорит пароль. Теперь проверьте таблицу: oauth_clients и убедитесь, что значение столбца password_client = 1

или найдите запись с password_client = 1

Ответ 11

Я также столкнулся с той же проблемой, я получил решение по этой ссылке. Пожалуйста, проверьте это. https://github.com/laravel/passport/issues/71

Это говорит о том, что: Вы делаете вызов /oauth/token так же, как всегда, чтобы получить свой токен. Но сделайте это с grant_type из custom_request. Вам нужно будет добавить метод byPassportCustomRequest ($ request) в вашу модель User (или любую другую модель, настроенную для работы с Passport). Этот метод примет Illuminate\Http\Request и вернет модель пользователя, если вы сможете аутентифицировать пользователя с помощью запроса, или он вернет null.

Ответ 12

если вы все перепробовали и все еще не работали значит попробуйте это решение !! просто дайте сферу *.

$query = http_build_query([
    'client_id' => 1,
    'redirect_uri' => 'http://localhost:3000/callback',
    'response_type' => 'code',
    'scope' => '*'
]);

в моем случае это решение. я проверил

Ответ 13

У меня такая же проблема. Когда вы выполняете php artisan passport:install он выдает два типа секретов: один для типа предоставления CLIENT, а другой для типа предоставления PASSWORD.

Я использовал секрет КЛИЕНТА для выдачи токенов ПАРОЛЯ. Как только я изменил это, я смог нормально генерировать access_token и refresh_token.

Ответ 14

В моем случае решение заключалось в том, чтобы обернуть его внутри Form-data, не пропустите, если вы используете нормальные параметры с почтальоном, это не сработает, убедитесь, что для запроса тела установлено значение FORM-DATA.

Ответ 15

вы можете определить две переменные, такие как

$client_id = '111';
$client_secret = '1212';

и условие находится в вашей функции, подобной этой

protected $clientID = '578324956347895';
protected $clinetSecret ='hflieryt478';

public function index(Request $request)
{

    if (!($request->input('clientID') && $request->input('clinetSecret'))) {
        return false;
    }

    $project = User::all();

   return $project
}