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 !
Related
I have a very basic Codeigniter 4 REST API with only one user and one function (POST). I need to add basic authentication where the username and password are in the HTTP authentication header. How do I add that to the code below? i don't need anything very sophisticated, just enough to authenticate the one user.
namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\API\ResponseTrait;
use App\Models\ApiModel;
use Config\Services;
class Api extends ResourceController {
use ResponseTrait;
protected $request;
public function create() {
$model = new ApiModel();
$data = [
'uid' => $this->request->getPost('uid'),
'request' => $this->request->getPost('request'),
'data' => $this->request->getPost('data')
];
$model->insert($data);
$response = [
'status' => 201,
'error' => null,
'messages' => [
'success' => 'Data Saved'
]
];
return $this->respondCreated($data, 201);
}
}
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.
I'm building an API for a mobile app where login is achieved through OTP sen via SMS to mobile phone devices.
The user can login after he enters his phone number and an OTP code sent to his device.
What am I trying to do?
I'm trying to use otp code to authenticate users without passwords.
How to disable passwords in laravel ?
What is the best approach?
Or if there's a way to use otp field instead of password for authentication.
public function generateOtp(Request $request)
{
$identifier = $request->phone;
$otp = new Otp();
$code = $otp->generate($identifier, 6, 15);
User::create([
'phone'=>$request->phone,
'otp'=>$code
]);
//Todo::Send OTP number to sms
return response()->json(['otp' => $code]);
}
public function login(Request $request)
{
$validator = Validator::make($request->all(), [
'phone' => 'required',
'otp' => 'required|min:6',
]);
if ($validator->fails()) {
return response()->json(['success' => false, 'data' => $validator->errors()], 400);
}
$otp = new Otp();
$otp = $otp->validate($request->phone, $request->otp);
if ($otp->status == true) {
$credentials = [
'phone' => $request->phone,
];
if (auth()->attempt($credentials)) {
$user = new UserResource(User::find($user->id));
$this->revokeTokens($user->id);
$token = $user->createToken('AccessToken')->accessToken;
$user->token = $token;
unset($user->code, $user->id, $user->created_at, $user->updated_at);
return response()->json(['success' => true, 'code' => 1500, 'user' => $user, 'token' => $token]);
} else {
return ResponseHelper::notSuccessful(1502, 'login credentials are wrong');
}
}
if ($otp->status == false) {
return response()->json(['code'=>2, 'message'=>'OTP Expired. Generate New Code']);
}
}
You need to create your own user provider class and change the default in auth config
So what i want is to put 'g-recaptcha-response' in a variable to be able to use it in my condition to verify recaptcha but I haven't been able to do this. Is there any way to only use recaptcha field from the array inside validate() because my code as it is, redirects me back to homepage. It goes straight to else statement.
public function contactanospost(Request $request){
$request->validate([
'nombre' => 'required|distinct',
'telefono'=> 'required|telefono',
'correo' => 'required|email',
'mensaje' => 'required',
'g-recaptcha-response' => 'required|captcha',
]);
if(POST['g-recaptcha-response']){ /*here I am trying to
check with a condition if recaptch was really validated once the form is submitted */
$token= POST['g-recaptcha-response'];
$client = new Client();
$response = $client->post('https://www.google.com/recaptcha/api/siteverify', [
'form_params' => array('secret' => 'mycaptchakey',
'response'=> $token /*Checking with google parameters for recaptcha if the user was indeed verified */
)
]);
$resultados = json_decode($response->getBody()->getContents()); //decode with json
if($resultados->success){ /*if this was a success then return a page with parameters from google recaptcha such as: secret, response, remote ip.*/
dd($resultados); /*show the results from verified user and that recaptcha is working*/
$contactanos = Contactanos::create($request->all());/* and create all fields for model Contactanos*/
Mail::to('some#mail')->send(new enviacorreo($contactanos)); /* since it is a contact form then send all the information to some mail*/
\Session::flash('flash_message','Tu mensaje ha sido enviado!'); /* send a message with "email delivered" verification*/
return redirect()->back();
}
else{
\Session::flash('flash_message','Robot');
return redirect('/');
}
}
else{
return redirect('/');
}
}
I'm now able to access request properties using input() what got me confused were my if statements. The real problem is that after:
$resultados = json_decode($response->getBody()->getContents());
next if statement is not getting the expected success but instead it goes straight to else with robot message:
else{
\Session::flash('flash_message','Robot');
return redirect('/');
}
You can access all the properties of the request from the $request object by calling e.g, $request->input('g-recaptcha-response') This is the basic of Accessing the request if you have read through the documentation.
I can lend you a snippet to do this perhaps it will help you rethink how you're validating the captcha:
use GuzzleHttp\Client;
....
$v = Validator::make($request->all(), [
'name' => 'required|min:2',
'email' => 'required|email|max:255',
'subject' => 'sometimes|required|min:3',
'message' => 'required|min:3',
'g-recaptcha-response' => 'sometimes|required'
], [
'g-recaptcha-response.*' => 'Please verify that you are not a robot'
]);
if ($v->fails()) {
return [
'success' => 'no',
'data' => $v->errors()->first()
];
}
if ($request->get('g-recaptcha-response')) {
$verify_form = [
'secret' => env('GOOGLE_RECAPTCHA_SECRET', 'default'), //better to save in config though
'response' => $request->get('g-recaptcha-response')
];
$client = new Client();
$verify_serial = '?'.http_build_query($verify_form);
$response = $client->post('https://www.google.com/recaptcha/api/siteverify'.$verify_serial);
$arrayed_response = json_decode($response->getBody()->getContents(), true);
if(!$arrayed_response['success']){
Log::notice('There is something wrong with the verification of recaptcha: ',$arrayed_response );
return [
'success' => 'no',
'data' => 'Something went wrong in verification process',
];
}
}
The idea is that, you build the secret and response body and use that to request validation check from Google just as you have done but building the query as query parameters directly to the url.
PS: you don't have to return the snippet :)
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);
}
}
}