Package used is the : https://github.com/coderello/laravel-passport-social-grant
I have followed all the expected changed with the tutorial provided at :
https://medium.com/#hivokas/api-authentication-via-social-networks-for-your-laravel-application-d81cfc185e60
url :
http://myurl.com/oauth/token
output:
{
"error": "invalid_credentials",
"error_description": "The user credentials were incorrect.",
"message": "The user credentials were incorrect."
}
parameter have used with the postman is as followed:
grant_type' => 'social', // static 'social' value
'client_id' => $clientId, // client id
'client_secret' => $clientSecret, // client secret
'provider' => $providerName, // name of provider (e.g., 'facebook', 'google' etc.)
'access_token' => $providerAccessToken, // access token issued by specified provider
],
what can be the issue here ?
For Facebook you need to have the client_id and secret, in your services.php
Code inside FacebookProvider of Socialite
protected function getUserByToken($token)
{
$this->lastToken = $token;
$params = [
'access_token' => $token,
'fields' => implode(',', $this->fields),
];
if (! empty($this->clientSecret)) {
$params['appsecret_proof'] = hash_hmac('sha256', $token, $this->clientSecret);
}
$response = $this->getHttpClient()->get($this->graphUrl.'/'.$this->version.'/me', [
'headers' => [
'Accept' => 'application/json',
],
'query' => $params,
]);
return json_decode($response->getBody(), true);
}
So, google kinda works without secret.
Related
I am facing a problem where when I tried to login in postman, the data return after login is not a bearer token but such like this
{
"success": true,
"message": "User login succesfully, Use token to authenticate.",
"token": {
"name": "passport_token",
"abilities": [
"*"
],
"tokenable_id": 1,
"tokenable_type": "App\\Models\\User",
"updated_at": "2022-07-04T08:52:22.000000Z",
"created_at": "2022-07-04T08:52:22.000000Z",
"id": 6
}
}
Below is the login API
public function login(Request $request)
{
$input = $request->only(['email', 'password']);
$validate_data = [
'email' => 'required|email',
'password' => 'required|min:8',
];
$validator = Validator::make($input, $validate_data);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => 'Please see errors parameter for all errors.',
'errors' => $validator->errors()
]);
}
// authentication attempt
if (auth()->attempt($input)) {
$token = auth()->user()->createToken('passport_token')->accessToken;
return response()->json([
'success' => true,
'message' => 'User login succesfully, Use token to authenticate.',
'token' => $token
], 200);
} else {
return response()->json([
'success' => false,
'message' => 'User authentication failed.'
], 401);
}
}
How to get the bearer token instead of the json like that since I also not found the way in documentation.
Try change accessToken to plainTextToken
-------
$token = auth()->user()->createToken('passport_token')->plainTextToken;
return response()->json([
'success' => true,
'message' => 'User login succesfully, Use token to authenticate.',
'token' => $token,
'tokenType' => 'Bearer'
], 200);
---------
Hope this help you
That's weird behaviour of passport package, even though we follow the documentation. However if you want to generate the token then you can do it by following LOC.
$resultToken = $user->createToken($user->email);
I'm using passport auth with lumen for my project, and the setup with default routes . However i tryied to test my login route from the AuthLoginController and i have back :
"Client error: POST http://api.restservice/v1/oauth/token resulted in a 400 Bad Request response:\n{\"error\":\"invalid_request\",\"error_description\":\"The request is missing a required parameter, includes an invalid paramet (truncated...)\n".
postman json
{
"client_secret" : "IFCeKiKNA7zdmOC1yzgWQJvxtHKHOu1WwdDq1hMH",
"grant_type" : "password",
"client_id" : "2",
"email" : "fhegmann#example.com",
"username" : "fhegmann#example.com",
"password" : "123456"
}
AuthLoginController.php
{
public function login(Request $request)
{
$email = $request->email;
$password = $request->password;
//the fields if empty or not
if (empty($email) or empty($password)) {
return response()->json(['status' => 'error', 'message' => 'You must fill all fields']);
}
$client = new Client();
try {
return $client->post('http://api.restservice/v1/oauth/token', [
'form_params' => [
'client_secret' => 'IFCeKiKNA7zdmOC1yzgWQJvxtHKHOu1WwdDq1hMH',
'grant_type' => 'password',
'client_id ' => 2,
'username' => $request->email,
'password' => $request->password
]
]);
} catch (BadResponseException $e) {
return response()->json(['status' => 'error', 'message' => $e->getMessage()]);
}
}
After unnecessary searches for logic solutions i find that in form_params block client_id has a space caracter before parenthesis.
Greetings and Regards
I am designing an api with Laravel and using a passport for an app.
I'm having trouble logging in using the login endpoint.
The problem I encountered is as follows:
I will send the necessary parameters to the server including
client_id - grant_type - username - password - client_secret - scope:
{{server_url}}/api / v1 / login
In the login method:
After evaluating entries I send a request to oauth/token to receive theta token.
I get the error below.
GuzzleHttp\Exception\ClientException: Client error: POST
http://divar.local/oauth/token resulted in a 400 Bad Request
response: {"error":"invalid_grant","error_description":"The provided
authorization grant (e.g., authorization code, resource owner
(truncated...)
The contents of the login method
public function login()
{
$validator = Validator::make(request()->all(), [
'mobile_number' => 'required',
'password' => 'required',
]);
if ($validator->fails()) {
$response['errors'] = $validator->errors();
return response()->json($response, 401);
}
$clientOauthData = Client::where('password_client', 1)->where('name', 'Laravel Password Grant Client')->first();
$http = new \GuzzleHttp\Client;
$response = $http->post(env('APP_URL') . '/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => $clientOauthData->id,
'client_secret' => $clientOauthData->secret,
'username' => request('mobile_number'),
'password' => request('password'),
'scope' => '',
],
'headers' => [
'Accept' => 'application/json'
]
]);
$response = json_decode((string)$response->getBody(), true);
return response()->json($response, 200);
}
Request headers :
Request body :
This is how I always proceed this request.
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required|mobile_phone',
'password' => 'required|string',
]);
$http = new \GuzzleHttp\Client;
try {
$response = $http->post(config('services.passport.login_endpoint'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => 'your client ID',
'client_secret' => 'secret ID,
'username' => $request->mobile_phone,
'password' => $request->password,
// 'scope' => '',
],
]);
return $response->getBody();
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
if ($e->getCode() == 401) {
return response()->json(['message' => 'This action can\'t be perfomed at this time. Please try later.'], $e->getCode());
} else if ($e->getCode() == 400) {
return response()->json(['message' => 'These credentials do not match our records.'], $e->getCode());
}
return response()->json('Something went wrong on the server. Please try letar.', $e->getCode());
}
}
I am a novice with Lumen and have recently integrated dusterio/lumen-passport via composer into my project. Following a tutorial I have successfully created authentication for 'client' instances, so I am able to send variables
grant_type: client_credentials
client_id: {my id}
client_secret: {my secret}
to /oauth/token and get a bearer token. That is working great.
What I need to be able to do, and I cannot find sufficient documentation anywhere, is to create user login functionality. This is so that I can hook a UI up to the Lumen API and users be able to enter their email address and password to get access. If any one has any information to help me achieve this I would be extremely grateful. Below are edits I have made to set up the passport process...
bootstrap/app.php
$app->routeMiddleware([
'client.credentials' => Laravel\Passport\Http\Middleware\CheckClientCredentials::class,
]);
$app->register(App\Providers\AuthServiceProvider::class);
$app->register(Laravel\Passport\PassportServiceProvider::class);
$app->register(Dusterio\LumenPassport\PassportServiceProvider::class);
config/auth.php
'defaults' => [
'guard' => env('AUTH_GUARD', 'api'),
'passwords' => 'users'
],
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users'
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => \App\User::class
]
],
routes/web.php
$router->group(['middleware' => 'client.credentials'], function () use ($router) {
$router->get('/test', 'TestController#index');
});
The way I did it with my laravel based client (seperate apps) was to save the token to a cookie which gets called each request using middleware to authenticate the request heres my code.
<?php
namespace App\Http\Controllers;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
class AuthController extends Controller {
public function __construct()
{
}
public function showLoginPage()
{
return view('Login');
}
public function attemptLogin(Request $request)
{
$client_id = env('CLIENT_ID');
$client_secret = env('CLIENT_SECRET');
$username = $request->input('email');
$password = $request->input('password');
$guzzle = new Client;
$response = $guzzle->post('https://api.domain.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => $client_id,
'client_secret' => $client_secret,
'username' => $username,
'password' => $password,
'scope' => '*',
],
]);
$reply = json_decode($response->getBody(), true);
$token = $reply['access_token'];
return redirect('/')->cookie('token', $token);
}
public function attemptLogout(Request $request)
{
$accessToken = $request->cookie('token');
$client = new Client(['base_uri' => 'https://api.domain.com']);
$headers = [
'Authorization' => 'Bearer ' . $accessToken,
'Accept' => 'application/json',
];
$response = $client->request('GET', 'logout', [
'headers' => $headers
]);
$status = $response->getStatusCode();
if($status === 200)
{
return redirect('/login')->withCookie(Cookie::forget('token'))->with('success','Logout Successful');
} else {
return response('API Logout Failed', 500);
}
}
}
I'm setting up Laravel Passport's Client Grant and using Guzzle to retrieve a token, but I'm getting a 401 Unauthorized error.
I created the client using: php artisan passport:client --client.
The client generated is:
Client ID: 1
Client secret: NmJsEVFClXVqWJuQnZTWA3bnZEVZ0KaC13anHZt1
I saved these in my .env file and ran the command
php artisan config:clear
Here's my code:
$url = 'http://hub.local/oauth/token';
$client_secret = env('CLIENT_SECRET');
$client_id = env('CLIENT_ID');
$client = new Client();
try {
$response = $client->post($url, [
'json' => [
'grant_type' => 'client_credentials',
'client_id' => $client_id,
'client_secret' => $client_secret,
],
'headers' => [
'Content-Type' => 'application/json',
],
]);
return $response;
} catch (RequestException $e) {
dd($e);
} catch (Exception $e) {
dd($e);
}
And the resulting error message:
ClientException {#660 ▼
-request: Request {#649 ▶}
-response: Response {#657 ▶}
-handlerContext: []
#message: """
Client error: `POST http://hub.local/oauth/token` resulted in a `401 Unauthorized` response:
{"error":"invalid_client","error_description":"Client authentication failed","message":"Client authentication failed"}
"""
#code: 401
#file: "C:\repos\client\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php"
#line: 113
When I try the request using the same parameters and values in Insomnia, the request works.
Seems I can't post images yet.
https://i.imgur.com/w6Ollin.jpg
https://imgur.com/fXpzKjj.jpg
I'm using Laravel 5.8.12, Guzzle 6.3.3 and Passport 7.2.2.
What am I missing?
Update: The problem only occurred when I was running the ( Laravel) client and server instances on the same local xampp server. I separated them to run on their own individual xampp instances and the authentication worked without issue. What had confused me while testing solely locally was that the request worked with Insomnia, but not the browser. I'm assuming that the "machine to machine" part of this client grant was seeing my client + server sharing the same xampp instance as something unrecognized. In any event, there's no actual problem. Hopefully this helps someone else.
in laravel doc there is an example like this :
Route::get('/callback', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'redirect_uri' => 'http://example.com/callback',
'code' => $request->code,
],
]);
return json_decode((string) $response->getBody(), true);
});
when I tested this one with my info I changed to some thing like this :
Route::get('/users/login', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://payment.devenv/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 2,
'client_secret' => 'z8YWlJeaW0d7o7SFyPLISUxYOcO5CxjGrZ5YuItl',
'username' => 'athamidn#gmail.com',
'password' => '123456',
'scope' => '',
'code' => 200,
'redirect_uri' => 'http://example.com/callback',
],
]);
return json_decode((string) $response->getBody(), true);
});
And I received an error same with your error. After many hours I got issue :
In database at oauth_clients table this is my info :
2 name: Laravel Password Grant Client redirect: http://localhost
when I changed redirect url to this it works.
finally :
Route::get('/users/login', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://payment.devenv/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 2,
'client_secret' => 'z8YWlJeaW0d7o7SFyPLISUxYOcO5CxjGrZ5YuItl',
'username' => 'athamidn#gmail.com',
'password' => '123456',
'scope' => '',
'code' => 200,
'redirect_uri' => 'http://localhost'
],
]);
return json_decode((string) $response->getBody(), true);
});
I believe you can re-create passport public and private keys stored in /storage folder by executing the php artisan passport:install. Then you can define those keys in the .env file and pass it with client_id & client_secret.
command output
Personal access client created successfully.
Client ID: 31
Client secret: xxxx
Password grant client created successfully.
Client ID: 32
Client secret: xxxx
/.env
PERSONAL_CLIENT_ID=31
PERSONAL_CLIENT_SECRET=xxxx
PASSWORD_CLIENT_ID=32
PASSWORD_CLIENT_SECRET=xxxx
POST - API parameters - /oauth/token
'client_id' => env('PASSWORD_CLIENT_ID'),
'client_secret' => env('PASSWORD_CLIENT_SECRET')
This error could happen when those private and public keys are not matched properly with the already created ones.
Cheers!