I am trying to validate apikey but I am stuck on this issue if a user enters a apikey it should be validated from MailChimp account and should show a message of in-valid key if api key is not matched with MailChimp.
My Code:
public function authenticateApiKey(Request $request)
{
$fieldsValidation = [
'api_key' => 'required|unique:apikey,api_key',
];
$validator = Validator::make($request->all(), $fieldsValidation);
if ($validator->fails()) {
$resultArray = [
'status' => 0,
'message' => $validator->errors()->first(),
'dataArray' => []
];
} else {
$api = new APIKEY($request->all());
$mc = new MailChimp($api);
$mailchimp_ping = ($mc->call('helper/ping'));
if(!$mailchimp_ping){
}
$request->user()->apikey()->save($api);
$resultArray = ['status' => 1, 'message' => 'Mailchimp Api key added into system successfully!', 'dataArray' => $api];
}
return \Illuminate\Support\Facades\Response::json($resultArray, 200);
}
When I hit this call it said call to aundefined method is there any other in which I can validate apikey.
Any help would be appreciated!
namespace App\Http\Controllers;
use App\APIKEY;
use DrewM\MailChimp\MailChimp;
use Illuminate\Auth\Access\Response;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
class ApiController extends Controller
{
public function authenticateApiKey(Request $request)
{
$fieldsValidation = [
'api_key' => 'required|unique:apikey,api_key',
];
$validator = Validator::make($request->all(), $fieldsValidation);
if ($validator->fails()) {
$resultArray = [
'status' => 0,
'message' => $validator->errors()->first(),
'dataArray' => []
];
} else {
$api = new APIKEY($request->all());
$mc = new MailChimp($api);
$mailchimp_ping = $mc->get('/ping');
if ($mailchimp_ping["status"] == 401) {
return redirect()->back()->with("errorMessage","api key is invalid")->withInput(Input::all());
}
///do here if api key is valid
$request->user()->apikey()->save($api);
$resultArray = ['status' => 1, 'message' => 'Mailchimp Api key added into system successfully!', 'dataArray' => $api];
// }
return \Illuminate\Support\Facades\Response::json($resultArray, 200);
}
}
Make a request. If the request works, the key is valid. Follow this link to make a ping request. It's a health check endpoint for MailChimp API 3.0.
$mailchimp_ping = $mc->get('/ping');
dd($mailchimp_ping);
Here is your requested full controller that works fine-
<?php
namespace App\Http\Controllers;
use App\APIKEY;
use DrewM\MailChimp\MailChimp;
use Illuminate\Auth\Access\Response;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
class ApiController extends Controller
{
public function authenticateApiKey(Request $request)
{
$fieldsValidation = [
'api_key' => 'required|unique:apikey,api_key',
];
$validator = Validator::make($request->all(), $fieldsValidation);
if ($validator->fails()) {
$resultArray = [
'status' => 0,
'message' => $validator->errors()->first(),
'dataArray' => []
];
} else {
$mc = new MailChimp($request->input('api_key'));
$mailchimp_ping = $mc->get('/ping');
if ($mailchimp_ping["status"] != 401) {
$api = new APIKEY($request->all());
$request->user()->apikey()->save($api);
$resultArray = ['status' => 1, 'message' => 'Mailchimp Api key added into system successfully!', 'dataArray' => $api];
return \Illuminate\Support\Facades\Response::json($resultArray, 200);
}
$errorResponse = [
'message' => 'Not valid api key!',
'code' => '401'
];
return $this->apiResponse('error', '401', $errorResponse);
}
}
}
Related
I am made an App with Laravel 9 back-end and ReactJS front-end and get a 401 unauthorized error even I am successfully logged-in in to my App. For Authentication I am using Laravel's build-in Passport and Cross-Domain Middleware.
Code is in api.php router and looks like below:
Route::group(['prefix' => 'users', 'middleware' => 'CORS'], function ($router) {
Route::post('/register', [AuthController::class, 'register'])->name('register.auth');
Route::post('/login', [AuthController::class, 'login'])->name('login.auth');
Route::get('/userdata', [AuthController::class, 'userData'])->name('userdata.auth');
Route::get('/checkifemailverified/{token}', [AuthController::class, 'checkIfEmailVerified'])->name('user.verify');
Route::get('/logout', [AuthController::class, 'logout'])->name('logout.auth');
Route::get('/me', [AuthController::class, 'me'])->name('me.auth');
});
And here is a AuthController:
<?php
namespace App\Http\Controllers;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Auth;
use App\Models\User;
use App\Models\UserVerify;
use Validator;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Carbon;
use Mail;
use Illuminate\Support\Facades\View;
class AuthController extends Controller
{
//private $apiToken;
protected $user;
public function __construct()
{
//$this->apiToken = uniqid(base64_encode(Str::random(40)));
$this->middleware("auth:api",["except" => ["login","register","logout","verifyAccount","checkIfEmailVerified","me"]]);
$this->user = new User;
}
/**
*
* #return \Illuminate\Http\Response
*/
public function login(Request $request){
$validator = Validator::make($request->all(),[
'email' => 'required|string',
'password' => 'required|min:8',
]);
if($validator->fails()){
return response()->json([
'success' => false,
'message' => $validator->messages()->toArray()
], 500);
}
//User check
$credentials = $request->only(["email","password"]);
$user = User::where('email',$credentials['email'])->first();
if($user->is_active===1){
if(auth()->attempt($credentials)){
//$user = Auth::user();
if($user->email_verified_at !== NULL){
if (DB::table('domains')
->select('domain', 'valid_before')
->where('domain', $user->domain)
->whereDate('valid_before_at', '<=', Carbon::now())
->count()){
return response()->json([
'success' => false,
'data' => 'Username and password do not match or domain subscription is not valid or expired!'
], 200);
} else {
// Login and "remember" the given user...
//Auth::login($user, true);
//Setting login response
$accessToken = auth()->user()->createToken('authToken')->accessToken;
/*$success['token'] = $this->apiToken;
$success['name'] = $user->name;
return response()->json([
'success' => true,
'data' => $success
], 200);*/
$responseMessage = "Login Successful";
return $this->respondWithToken($accessToken,$responseMessage,auth()->user());
}
} else {
return response()->json([
'success' => false,
'data' => 'Please Verify Email!'
], 200);
}
} else {
//$success['success'] = false;
return response()->json([
'success' => false,
'data' => 'Username and password do not match or domain subscription is not valid or expired!'
], 200);
}
}
}
public function register(Request $request){
$validator = Validator::make($request->all(),[
'email' => 'required|string',
'name' => 'required|string',
'domain' => 'required|string',
'password' => 'required|min:8',
]);
if($validator->fails()){
return response()->json([
'success' => false,
'message' => $validator->messages()->toArray()
], 500);
}
DB::beginTransaction();
try {
DB::table('domains')->insert([
['domain' => $request->domain, 'valid_before_at' => date('Y-m-d H:i:s', strtotime("+30 day")), 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s')]
]);
DB::table('users')->insert([
['name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), 'domain' => $request->domain]
]);
DB::commit();
// all good
/*return response()->json([
'success' => true,
'data' => 'User and domain is now created!'
], 200);*/
try {
$id = DB::table('users')
->select('id')
->where('email', $request->email)
->first()->id;
$token = Str::random(64);
DB::table('users_verify')->insert([
['user_id' => $id, 'token' => $token, 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s')]
]);
Mail::send('emails.userverify', ['token' => $token], function($message) use($request){
$message->from(env('MAIL_FROM_ADDRESS'), env('MAIL_FROM_NAME'));
$message->to($request->email);
$message->subject('Email Verification Mail');
});
return response()->json([
'success' => true,
'data' => 'User and domain is now created!'
], 200);
} catch (\Exception $e) {
// something went wrong
return response()->json([
'success' => false,
'data' => $e->getMessage()
], 200);
}
} catch (\Exception $e) {
DB::rollback();
// something went wrong
return response()->json([
'success' => false,
'data' => $e->getMessage()
], 200);
}
}
/**
* Write code on Method
*
* #return response()
*/
public function verifyAccount($token)
{
$verifyUser = UserVerify::where('token', $token)->first();
$message = 'Sorry your email cannot be identified.';
if(!is_null($verifyUser) ){
$user = $verifyUser->user;
if($user->email_verified_at == null) {
$verifyUser->user->email_verified_at = date('Y-m-d H:i:s');
$verifyUser->user->save();
$message = "Your e-mail is verified. You can now login.";
} else {
$message = "Your e-mail is already verified. You can now login.";
}
}
return redirect(env('APP_UI_URL').'/verifyemail?token='.$token);
}
/**
* Write code on Method
*
* #return response()
*/
public function checkIfEmailVerified($token)
{
$verifyUser = UserVerify::where('token', $token)->first();
$message = 'Sorry your email cannot be identified.';
if(!is_null($verifyUser) ){
$user = $verifyUser->user;
if($user->email_verified_at == null) {
$message = "Your e-mail is verified. You can now login.";
} else {
$message = "Your e-mail is already verified. You can now login.";
}
}
return response()->json([
'success' => true,
'data' => $message
], 200);
}
/**
* Logout the current user and revokes its crenedials.
*
* #return response()
*/
public function logout(Request $request){
$user = Auth::guard("api")->user()->token();
$user->revoke();
$responseMessage = "successfully logged out";
return response()->json([
'success' => true,
'message' => $responseMessage
], 200);
}
/**
* Get the user's profile.
*
* #param Request $request
* #return Response
*/
public function userData(Request $request)
{
$data = Auth::guard("api")->user();
//var_dump($user);
return $data;
}
/**
* Get the user's profile name.
*
* #param Request $request
* #return Response
*/
public function me(Request $request)
{
$data = Auth::guard("api")->user();
//var_dump($data);
return $data;
}
}
Purpose is to get logged-in users details for ReactJS GUI with userdata route and/or me router user name E.g Matti Kiviharju.
Also if anyone wants to see whole source codes of am App there re publically here in my GIT repositories in Atlassian Bitbucket for investigation:
React Front-end: https://bitbucket.i4ware.fi/projects/LOG/repos/login-form/browse?at=refs%2Fheads%2Fmatti_0006
Laravel Back-end: https://bitbucket.i4ware.fi/projects/SAAS/repos/saas-app/browse?at=refs%2Fheads%2Fmatti_0008
However, right answer for this that solves a problem helps multiple people, because source codes is available on our public GIT repos.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Auth,Str,Storage,Image,DB;
use GuzzleHttp\Client;
class SmsController extends Controller
{
//
public function index()
{
//
$data =[
'title'=>$description='Envoie SMS',
'description'=>$description,
//'membre'=>$membre,
//'membres'=>$membres,
//'departement'=>$departement,
];
return view('sms.index',$data);
}
public function envoyer(Request $request)
{
//
$senderid=$request->senderid;
$numero=$request->numero;
$message=$request->message;
$dateheure=date('Y-m-d h:i:s', time());
//dd($dateheure);
$client = new Client();
$res = $client->request('POST', 'http://africasmshub.mondialsms.net/api/api_http.php', [
'form_params' => [
'username' => 'test',
'password' => '0758224162',
'sender' => 'test',
'text' => 'Hello World!',
'type' => 'text',
'numero' => $numero,
'message' => $message,
'datetime' => $dateheure,
]
]);
//dd($res);
$success = 'message envoyé avec succès';
return redirect()->route('sms')->withSuccess($success);
}
}
Hello everyone ! I have a problem with Laravel, I cannot make an Http request to the Http address of an API which should allow me to send SMS. I am sending you as attachments the source code of my Controller "Smscontroller.php". I need your help. Thank you !
I am new to laravel and trying to do a simple Authentication project using the laravel/passport package provided by the laravel team and I have no problem with sending the token via a httponly cookie and receiving it from a frontend framework Vuejs. I am able to get the authentication working by storing the token into a localstorage on the browser but all the blogs and documentations I have read suggest not to use localstorage for storing a jwt token and most of them suggest to use httponly cookie because it is not accessible from javascript.
and for my layers of authentication use
a proxyRequest util class
an Authcontroller
I do not use the default User model I have a person model
I have a Cors middleware for allowing requests
proxyRequest class
<?php
namespace App\Utilities;
// use Illuminate\Support\Facades\Http;
class ProxyRequest {
public function grantPasswordToken(string $email, string $password)
{
$params = [
'grant_type' => 'password',
'username' => $email,
'password' => $password,
];
return $this->makePostRequest($params);
}
public function refreshAccessToken()
{
$refreshToken = request()->cookie('refresh_token');
abort_unless($refreshToken, 403, 'Your refresh token is expired.');
$params = [
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
];
return $this->makePostRequest($params);
}
protected function makePostRequest(array $params)
{
$params = array_merge([
'client_id' => config('services.passport.password_client_id'),
'client_secret' => config('services.passport.password_client_secret'),
'scope' => '',
], $params);
$proxy = \Request::create('oauth/token', 'post', $params);
$resp = json_decode(app()->handle($proxy)->getContent());
$this->setHttpOnlyCookie($resp->refresh_token);
return app()->handle($proxy)->getContent();
return $resp;
}
protected function setHttpOnlyCookie(string $refreshToken)
{
cookie()->queue(
'refresh_token',
$refreshToken,
14400, // 10 days
null,
null,
false,
true // httponly
);
}
}
Authcontroller
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Person;
// use App\Person;
// use App\Person;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
use Cookie;
use App\Utilities\ProxyRequest;
class AuthController extends Controller
{
protected $proxy;
public function __construct(ProxyRequest $proxy)
{
$this->proxy = $proxy;
}
public function user(Request $request)
{
if (Auth::guard('api')->check()) {
return $request->user('api');
}
return "not auth";
}
public function register(Request $request)
{
// $this->validate(request(), [
// 'name' => 'required',
// 'email' => 'required|email',
// 'password' => 'required',
// ]);
$user = Person::create([
'f_name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$resp = $this->proxy->grantPasswordToken(
$user->email,
$request->password
);
// return response([
// 'token' => $resp->access_token,
// 'expiresIn' => $resp->expires_in,
// 'message' => 'Your account has been created',
// ], 201);
return response()->json($resp);
}
public function check() {
return "Authenticated";
}
public function refreshToken()
{
$resp = $this->proxy->refreshAccessToken();
return response([
'token' => $resp->access_token,
'expiresIn' => $resp->expires_in,
'message' => 'Token has been refreshed.',
], 200);
}
public function logout(Request $request)
{
$token = $request->user()->token();
$token->delete();
// remove the httponly cookie
cookie()->queue(cookie()->forget('refresh_token'));
return response([
'message' => 'You have been successfully logged out',
], 200);
return $request->all();
}
public function login(Request $request)
{
$user = Person::where('email', $request->email)->first();
abort_unless($user, 404, 'User not found.');
abort_unless(
Hash::check($request->password, $user->password),
403,
'Password or mail address not correct.'
);
$resp = $this->proxy->grantPasswordToken($user->email, $request->password);
return response([
'token' => $resp->access_token,
'expiresIn' => $resp->expires_in,
'message' => 'You have been logged in',
], 200);
}
}
routes
Route::middleware('guest')->group(function () {
Route::post('register', 'Api\AuthController#register')->name('register');
Route::post('login', 'Api\AuthController#login')->name('login');
Route::post('refresh-token', 'Api\AuthController#refreshToken')->name('refreshToken');
});
Route::middleware('auth:api')->group(function () {
Route::post('logout', 'Api\AuthController#logout')->name('logout');
});```
middlewares
protected $middleware = [
\App\Http\Middleware\addCookieToHeader::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\Cors::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
];
when I hit the login and register routes I am able to generate a token and could find it in my chrome (Application -> cookies with the name refresh token) but if I try to logout
i just get a response that says {message: "UnAuthenticated"} with a 401 error.
I couldnt find anything regarding this on the internet.
I do have trouble in setting password reset facility for custom user table (suppose 'customers' table). It was successful to generate a token for password reset but unable to do the reset because of Laravel considering its default table 'users', not the table I suppose to do reset. Changing default table users to customers in Config\Auth.php generate validation error
Passwords must be at least six characters and match the confirmation.
I just copy/pasting what I did so far
<?php
/*
Code Done by Arun
*/
namespace App\Http\Controllers\API\ResetPassword;
use App\Http\Controllers\API\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Support\Facades\Password;
use App\Model\Customer;
use Laravel\Passport\Client;
use Illuminate\Support\Facades\Auth;
class ResetPasswordController extends Controller
{
use ResetsPasswords;
public function __construct()
{
$this->middleware('api');
}
protected function guard()
{
return Auth::guard('api');
}
public function ResetPassword(Request $request)
{
$v = validator($request->only('email', 'token', 'password','confirm_password'), [
'token' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'required|string',
'confirm_password' => 'required|string|min:6',
]);
if ($v->fails()) {
return response()->json(["error"=>$v->errors()->all()], 400);
}
else
{
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
}
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($response)
: $this->customResetFailedResponse($request, $response);
// $client = Client::where('password_client', 1)->first();
// $request->request->add([
// 'grant_type' => 'password',
// 'client_id' => $client->id,
// 'client_secret' => $client->secret,
// 'username' => $request->email,
// 'password' => $request->password,
// 'scope' => null,
// ]);
// // Fire off the internal request.
// $proxy = Request::create(
// 'oauth/token',
// 'POST'
// );
// return $response ;
}
}
Any Laravel expert can help me with the problem?
Im finally able to figure this out, im just posting answer may help others come across the same problem.
<?php
namespace App\Http\Controllers\API\Auth;
use App\Http\Controllers\API\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Support\Facades\Password;
use App\Model\Customer;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
use GuzzleHttp\Client;
use DB;
class ResetPasswordController extends Controller
{
use ResetsPasswords;
protected $confirmEmail = false;
public function __construct()
{
}
public function resetPasswordCustomer(Request $request)
{
//Custome password reset mail has done in customer model
$v = validator($request->only('token', 'password','password_confirmation'), [
'token' => 'required|string|max:255',
'password' => 'required|string',
'password_confirmation' => 'required|string|min:6',
]);
if ($v->fails()) {
return response()->json(["error"=>$v->errors()->all()], 400);
}
else
{
$request->merge(['email'=> $this->checkTokenAgainstHashedValue($request->token)]);//Add new property to request..
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
}
return $response == Password::PASSWORD_RESET
? $this->authToken($request)
: $this->customResetFailedResponse($request, $response);
return $response ;
}
protected function checkTokenAgainstHashedValue($token)
{
$resetTable = DB::table('password_reset_customers')->select('token','email')->get();
foreach ($resetTable as $value) {
if (Hash::check($token, $value->token)) {
return $value->email;
}
}
return null;
}
protected function authToken(Request $request)
{
$http = new Client();
$response = $http->post('http://abcd.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 2,
'client_secret' =>'qazrxGbDwrwbYXwbEbbkUFNO1zGB3eFYQN3AbG3m',
'username' => Auth::user()->email,
'password' => $request->password,
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
public function broker()
{
return Password::broker('customers');
}
}
I am trying to validate apikey , my scenario here is when am as a user enter apikey like xxxxxxxxxxxxxxxx-us17 i am saving this apikey in database as a user_id what i want here when i enter this key this key should check from mailchimp if its valid apikey that a user is enter if its a valid then good to go. if its not there should be a message not valid api key. On my side its allowing to enter any randon apikey which is not allowed in any case.
I am trying to solve this problem from a couple of days:
Here is my full controller:
namespace App\Http\Controllers;
use App\APIKEY;
use DrewM\MailChimp\MailChimp;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Mailchimp\MailchimpFacade;
class ApiController extends Controller
{
public function authenticateApiKey(Request $request)
{
$fieldsValidation = [
'api_key' => 'required|unique:apikey,api_key',
];
$validator = Validator::make($request->all(), $fieldsValidation);
if ($validator->fails()) {
$resultArray = [
'status' => 0,
'message' => $validator->errors()->first(),
'dataArray' => []
];
} else {
$api = new APIKEY($request->all());
$mailchimp_ping = new MailChimp($api);
print_r($mailchimp_ping);die;
$mailchimp_ping = $mailchimp_ping->get('/helper/ping');
if (!$mailchimp_ping) {
$errorResponse = [
'message' => 'Not valid api key!',
'error' => '401'
];
return \Illuminate\Support\Facades\Response::json($errorResponse);
}
else
{
$request->user()->apikey()->save($api);
$resultArray = ['status' => 1, 'message' => 'Mailchimp Api key added into system successfully!', 'dataArray' => $api];
return \Illuminate\Support\Facades\Response::json($resultArray, 200);
}
}
}
THe main code where i am trying to validate apikey from maiilchimp is:
$api = new APIKEY($request->all());
$mailchimp_ping = new MailChimp($api);
print_r($mailchimp_ping);die;
$mailchimp_ping = $mailchimp_ping->get('ping');
if (!$mailchimp_ping) {
$errorResponse = [
'message' => 'Not valid api key!',
'error' => '401'
];
return \Illuminate\Support\Facades\Response::json($errorResponse);
Your help will be highly appreciated !