I'm issuing some problems with Laravel/Passport while trying to test the auth flow of my application...
The stranger thing is that it only happens when I'm on testing env. The expects the 200 http code but instead receive a 500.
I'm using the Laravel 5.8 version, I'm also have installed Horizon and Telescope. My PHP version is 7.3.4.
My test
public function testLogin()
{
$user = factory(\App\Models\User::class)->create();
$response = $this->json('post', 'v1/login', [
'email' => $user->email,
'password' => 'secret',
]);
$response->assertStatus(Response::HTTP_OK);
}
My AuthController
public function login(AuthRequest $request)
{
try {
$credentials = $request->only(['email', 'password']);
throw_if(!auth()->attempt($credentials), UnauthorizedAccess::class, __('auth.auth_required'));
$accessToken = $this->handleAccessToken($credentials);
return response()->json($accessToken);
} catch (UnauthorizedAccess $ex) {
return response()->json([
'success' => false,
'message' => $ex->getMessage()
], Response::HTTP_UNAUTHORIZED);
}
}
private function handleAccessToken(array $credentials)
{
$user = User::where(['email' => $credentials['email']])->first();
$http = new Client();
$response = $http->post(url('oauth/token'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => $user->client->id,
'client_secret' => $user->client->secret,
'username' => $credentials['email'],
'password' => $credentials['password'],
'scope' => '*',
],
]);
return json_decode((string) $response->getBody(), true);
}
This is the erro that is produced:
on terminal
1) Tests\Feature\AuthTest::testLogin
Expected status code 200 but received 500.
Failed asserting that false is true.
laravel.log
[2019-04-26 09:02:53] local.ERROR: Client authentication failed {"exception":"[object] (League\\OAuth2\\Server\\Exception\\OAuthServerException(code: 4): Client authentication failed at /home/***/workspace/***/vendor/league/oauth2-server/src/Exception/OAuthServerException.php:138)
[stacktrace]
[2019-04-26 09:02:53] testing.ERROR: Client error: `POST http://***/oauth/token` resulted in a `401 Unauthorized` response:
{"error":"invalid_client","error_description":"Client authentication failed","message":"Client authentication failed"}
{"userId":"52b19d0d-e0c5-4924-84ae-d07700c672df","exception":"[object] (GuzzleHttp\\Exception\\ClientException(code: 401): Client error: `POST http://***/oauth/token` resulted in a `401 Unauthorized` response:
{\"error\":\"invalid_client\",\"error_description\":\"Client authentication failed\",\"message\":\"Client authentication failed\"}
at /home/***/workspace/***/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113)
[stacktrace]
Well, the error seems to be something with Guzzle itself while in testing env. That happens because Guzzle is set for the default env.
Then, I solve it following the answer gave by #lawrencedawson, that you can see here
Related
My API route in routes/api.php file is like below.
Route::post('/register', [RegisterController::class, 'register']);
My register function of RegisterController is like below
public function register(RegistrationValidate $request)
{
$user = User::create([
'username' => request('username'),
'email' => request('email'),
'full_name' => request('full_name'),
'store_name' => request('store_name'),
'store_logo' => $fileName,
'password' => Hash::make(request('password')),
]);
$token = $user->createToken($this->clientToken())->accessToken;
return response()->json([
'user' => $user,
'token' => $token,
], 201);
}
I am getting SERVICE UNAVAILABLE error like below
I used php artisan up command and clear the cache. But the result is as like before.
Trying to retrieve an access token from MS Azure
something like this:
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Response;
class HttpController extends Controller
{
public function index()
{
$url = "https://login.microsoftonline.com/[tenantId]/oauth2/token";
$response = HTTP::post($url,
[
'grant_type' => 'client_credentials',
'client_Id' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
'client_secret' => '***************************',
'resource' => 'https://management.azure.com',
]);
dd($response);
}
}
get the following error:
"error": "invalid_request",
"error_description": "AADSTS900144: The request body must contain the following parameter: 'grant_type'
$response = HTTP::asForm()->post($url,
[
'grant_type' => 'client_credentials',
'client_Id' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
'client_secret' => '***************************',
'resource' => 'https://management.azure.com',
]
);
Using the authentication plugin, I'm unable to verify my credentials via json. I can use Form, Jwt and Basic(For testing it works). The error returned is 'FAILURE_CREDENTIALS_INVALID'. Here's the sample code "simplified for brevity"
public function token()
{
$result = $this->Authentication->getResult();
if ($result->isValid()) {
//new jwt token etc
$message = true;
$this->log($result->getStatus());
}else{
$message = false;
$this->log($result->getStatus());
}
$this->set([
'message' => $message,
]);
$this->viewBuilder()->setOption('serialize', ['message']);
}
My application class has the method
public function getAuthenticationService(ServerRequestInterface $request) : AuthenticationServiceInterface
{
$service = new AuthenticationService();
$service->setConfig([
'unauthenticatedRedirect' => '/users/login',
'queryParam' => 'redirect',
]);
$fields = [
'username' => 'email',
'password' => 'password'
];
// Load the authenticators, you want session first
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Authentication.Form', [
'fields' => $fields,
'loginUrl' => '/users/login'
]);
//Testing jwt
$service->loadAuthenticator('Authentication.Jwt', [
'secretKey' => Security::getSalt()]);
// Load identifiers
$service->loadIdentifier('Authentication.Password', compact('fields'));
$service->loadIdentifier('Authentication.JwtSubject');
return $service;
}
The app is serving some json well if I pass in the jwt, but somehow I can't figure out how to request a new one, when the old expires.
Here's my middlewareQueue:
//some code
$middlewareQueue
->add(new ErrorHandlerMiddleware(Configure::read('Error')))
->add(new AssetMiddleware([
'cacheTime' => Configure::read('Asset.cacheTime'),
]))
->add(new RoutingMiddleware($this))
->add($csrf)
->add(new BodyParserMiddleware())
->add(new AuthenticationMiddleware($this));
//more code
I DO NOT use basic
As mentioned in the comments, if you want to authenticate using the form authenticator on your token retrieval endpoint, then you need to make sure that you include the URL path of that endpoint in the authenticators loginUrl option.
That option accepts an array, so it should be as simple as this:
$service->loadAuthenticator('Authentication.Form', [
'fields' => $fields,
'loginUrl' => [
'/users/login',
'/api/users/token.json',
],
]);
The error that you were receiving was because the form authenticator simply wasn't applied on the token endpoint, and therefore the authentication service would go to the next authenticator, the JWT authenticator, which isn't bound to a specific endpoint, and therefore can run for all endpoints, and the JWT authenticator of course expects a different payload, it looks for a token, and if it can't find it, it will return the error status FAILURE_CREDENTIALS_INVALID.
I am new to both laravel and lumen.
I was creating a login api with oauth2.0 in lumen 5.6, i have installed passport and generated token.
Below is my login controller function and it is working fine. It returns token.
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Route;
//use Illuminate\Support\Facades\DB;
use App\User;
use Auth;
public function login(Request $request)
{
global $app;
$proxy = Request::create(
'/oauth/token',
'post',
[
'grant_type' => env('API_GRAND_TYPE'),
'client_id' => env('API_CLIENT_ID'),
'client_secret' => env('API_CLIENT_SECRET'),
'username' => $request->username,
'password' => $request->password,
]
);
return $app->dispatch($proxy);
}
Since i have to check user status apart from username and password, i need to check the user credential first. so i do like this.
public function login(Request $request)
{
$credentials = $request->only('username', 'password');
if (Auth::attempt($credentials)) {
return ['result' => 'ok'];
}
return ['result' => 'not ok'];
}
Here i am getting this error.
Method Illuminate\Auth\RequestGuard::attempt does not exist.
So i tried Auth::check instead of Auth::attempt.
Now there is no error but it always return false even though the credentials are valid.
I searched a lot for a solution but i didn't get.
The function guard is only available for routes with web middleware
public function login() {
if(Auth::guard('web')->attempt(['email' => $email, 'password' => $password], false, false)) {requests
// good
} else {
// invalid credentials, act accordingly
}
}
Changing default guard to "web" fixed my problem.
config/auth.php:
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
using jwt it's worked for me
1-Auth::attempt($credentials)
just replace line 1 to line 2
2-$token = Auth::guard('api')->attempt($credentials)
I use Filsh/yii2-oauth2-server,
I can use client token using $_pos to access my API.
In controller:
if (!isset($_post['token'])){
//exeption
}
else{
token = $_post('token');
}
if ((Accesstokens::isAccessTokenValid($token))) {
// do some thing.
}
in my Accesstokens model :
public static function isAccessTokenValid($token)
{
if (empty($token)) {
return false;
}
$query = (new \yii\db\Query())
->select(['access_token','expires'])
->from('oauth_access_tokens')
->where(['access_token' => $token])
// ->limit(10)
->one();
if (empty($query)) {
return false;
}
$expire = $query['expires'];
return $expire > date('Y-m-d h:i:s');
}
If I use password (user_credential) token, I can implementation bearer auth using :
public function behaviors()
{
return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [
'class' => CompositeAuth::className(),
'authMethods' => [
['class' => HttpBearerAuth::className()],
['class' => QueryParamAuth::className(), 'tokenParam' => 'accessToken'],
]
],
'exceptionFilter' => [
'class' => ErrorToExceptionFilter::className()
],
]);
}
But this method is using user table in authenticate user, not oauth_client table to authenticate client without user.
How to authenticate token base on client table only, without user table?
Request:
GET http://myapi.com/api/www/index.php/oauth2/token
grand_type = client_credentials
client_id = id1
client_secret = secret1
Response:
"access_token": "thisistheccesstoken",
"expires_in": 31104000,
"token_type": "Bearer",
"scope": "default"
Request:
GET http://myapi.com/api/www/index.php/oauth2/v1/get/frogs
HEADER Authorization: Bearer thisistheaccesstoken
Response:
all the frogs
How to use: HEADER Authorization: Bearer? Can anyone help?