Laravel HTTP Client Retrieve REST API Access Token - authentication

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',
]
);

Related

Laravel 7 Passport with different and multiple Models

I am currently developing an API with Laravel 7 and I want to authenticate users coming from different applications with Passport : 3 applications communicate with the API, so 3 different user tables.
It's working fine with the User model provided but when I use my own model, I can't login : it responds "Bad credentials" with the good credentials.
So my question is : Is it possible to use a different model from User provided and also multiple model at the same time for each APP/Client ?
Here is a diagram of the structure I want : Diagram
My App\User :
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable{
use Notifiable, HasApiTokens;
....
}
Here is my login function :
public function login(Request $request)
{
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string'
]);
$credentials = request(['email', 'password']);
if(!Auth::attempt($credentials))
return response()->json([
'message' => 'Bad credentials'
], 401);
$user = $request->user();
$tokenResult = $user->createToken('Personal Access Token');
$token = $tokenResult->token;
$token->expires_at = Carbon::now()->addHours(1);
$token->save();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse(
$tokenResult->token->expires_at
)->toDateTimeString()
]);
}
}
My config/auth
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'userstest',
],
'api' => [
'driver' => 'passport',
'provider' => 'userstest',
'hash' => false,
],
], 'providers' => [
'userstest' => [
'driver' => 'eloquent',
'model' => App\User::class,
],

SERVICE UNAVAILABLE error at REST API calling

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.

Simple API Call gets redirected

I'm creating a Nextcloud-App (using Nextcloud 20). I want a simple call to my external service. Due to CSP restrictions (set by default by netxcloud), I simply can't.
Everytime I request my URL, using window.OC.generateUrl('/apps/[MYAPP]/video/trim'); I get a redirect response (code 302), instead of a success (code 200). What did I miss?
I registered my route:
// [MYAPP]/appinfo/routes.php
return [
'routes' => [
['name' => 'video#trim', 'url' => '/trim', 'verb' => 'POST']
]
];
I've build my controller:
// [MYAPP]/lib/controller/VideoController.php
namespace OCA\[MYAPP]\Controller;
use OCP\IRequest;
use GuzzleHttp\Client;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
class VideoController extends Controller
{
/**
* #NoAdminRequired
*/
public function trim(string $title, string $content)
{
$client = new Client([
'base_uri' => 'http://localhost:3000/push',
'timeout' => 2.0,
]);
$response = $client->request('POST', ['json' => $content]);
return new DataResponse(['foo' => 'bar']);
}
}
I'm POSTing my request to it. In console I see a redirect to Location http://localhost:9000/apps/dashboard/.
// js
const opts = {}; // my payload
const url = window.OC.generateUrl('/apps/[MYAPP]/video/trim');
fetch(url, {method: 'post', body: JSON.stringify(opts)})
.catch((err) => console.error(err))
.then((response) => response.json())
.then((data) => console.log(data));
I finally found the problem in routes.php!
Since I'm generating the URL for /apps/[MYAPP]/video/trim, the url in routes.php should look like /video/trim instead of /trim.
// [MYAPP]/appinfo/routes.php
return [
'routes' => [
['name' => 'video#trim', 'url' => '/video/trim', 'verb' => 'POST']
]
];

Error trying to test laravel/passport auth cicle

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

Yii2 oauth2 client_credential token authentication

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?