Replacing Google OAuth API in Laravel - php

I have an app that I was tasked with to renew. However, the app runs a Google OAuth API to authenticate the users. However, this instance of the API no longer works as the company has changed name and thus the old mail domain no longer exists.
E.g: name#companyname.com
Is there a way for me to change the instance of the api so it will allow any gmail to get in.
here's my current controller for the oauth
public function checkUserByToken($social_token)
{
$client = new \Google_Client(['client_id' => env('GOOGLE_CLIENT_ID', '')]);
$payload = $client->verifyIdToken($social_token);
if ($payload) {
$validator = Validator::make($payload, [
'email' => 'required|email|regex:/(.*)oldcompany.com$/i',
]);
if ($validator->fails()) {
return false;
}
$user = User::where('email', $payload['email'])->first();
if (!$user) {
$data = [
'name' => $payload['family_name'],
'full_name' => $payload['name'],
'email' => $payload['email'],
'password' => bcrypt(str_random(8)),
];
$user = $this->createUser($data);
}
$user->forceFill([
'email' => $payload['email'],
'email_verified_at' => Carbon::now(),
])->save();
$tokenResult = $user->createToken('Personal Access Client');
$token = $tokenResult->token;
$token->expires_at = Carbon::now()->addMonth();
$token->save();
$data = [
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse($tokenResult->token->expires_at)->toDateTimeString(),
'full_name' => $payload['name'],
'avatar' => $payload['picture'],
'role' => $user->role,
'section' => isset($user->section)?$user->section->name:"",
'id' => $user->id
];
return $data;
} else {
return false;
}
}
I have tried replacing the google OAuth API in .env and change
$validator = Validator::make($payload, [
'email' => 'required|email|regex:/(.*)oldcompany.com$/i',
]);
to
$validator = Validator::make($payload, [
'email' => 'required|email|regex:/(.*)newcompany.com$/i',
]);
no avail as I think the google API outside of sending back auth token also send back something else but I'm not sure what it is.

Related

Google login integration not working, redirect to homepage without no profile

It was works fine. But problem arise after migrating domain & hosting. When I tried to login/signup with google login, it connect with Client ID & Secret correctly. But after, it redirect to homepage without any data or profile showing. On other side, same Client ID & Secret works fine in localhost.
Route::post('googlelogin', 'Api\Auth\LoginController#googlelogin');
#Controller
public function googlelogin(Request $request){
$this->validate($request, [
'email' => 'required',
'name' => 'required',
'uid' => 'required',
'password' => ''
]);
$authUser = User::where('email', $request->email)->first();
if($authUser){
$authUser->google_id = $request->uid;
$authUser->fname = $request->name;
$authUser->save();
if(isset($authUser) && $authUser->status == '0'){
return response()->json('Blocked User', 401);
}
else{
if (Hash::check('password', $authUser->password)) {
return $response = $this->issueToken($request,'password');
} else {
$response = ["message" => "Password mismatch"];
return response($response, 422);
}
}
}
else{
$verified = \Carbon\Carbon::now()->toDateTimeString();
$user = User::create([
'fname' => request('name'),
'email' => request('email'),
'password' => Hash::make($request->password !='' ? $request->password : 'password'),
'google_id' => request('uid'),
'status'=>'1',
'email_verified_at' => $verified
]);
return $response = $this->issueToken($request, 'password');
}
}

How to login user with lat & long and find the location based on current position in Laravel?

In my login API I have "email" and "password" for login and now I want to pass lat and long in my login API and my new body request will look like this:
{
"email":"john-smith#ovadamd.com",
"password": "admin123",
"lat": "12",
"long": "22"
}
I want to show this user belong to which facility and I have facility location table where I am storing lat and long and I want to login user with lat and long.
This is my login API:
public function fdLogin(Request $request)
{
$credentials = $request->only('email', 'password');
$rules = [
'email' => 'required|email',
'password' => 'required',
];
$validator = Validator::make($credentials, $rules);
if ($validator->fails()) {
return response()->json([
'status' => false,
'message' => __('messages.validation_errors'),
'errors' => $validator->messages()
]);
}
try {
$is_already_loggedIn = $this->user->where('email', $request->input('email'))->value('is_loggedIn');
if ($is_already_loggedIn) {
return response()->json([
'status' => false,
'message' => 'You are already logged In on some module'
], 500);
}
$customClaims = ['exp' => Carbon::now()->addYear()->timestamp];
// Attempt to verify the credentials and create a token for the user
if (!$token = JWTAuth::attempt($credentials, $customClaims)) {
return response()->json([
'status' => false,
'message' => 'We can`t find an account with this credentials.'
], 401);
}
} catch (JWTException $e) {
// Something went wrong with JWT Auth.
return response()->json([
'status' => false,
'message' => 'Failed to login, please try again.'
], 500);
}
$currentUser = Auth::user();
$currentUser->basicInfo = $this->userBasicInfo->where('user_id', $currentUser->id)->first();
$access_module = $this->userAccessModule->where('user_id', $currentUser->id)->first();
$is_super_admin = DB::table('users')->select('users.is_super_admin')->where('id',$currentUser->id)->first();
$specialitiesAndRoles = DB::table('roles')
->join('user_facility', 'roles.id', 'user_facility.role_id')
->where('user_facility.user_id', Auth::user()->id)
->select('user_facility.facility_id','user_facility.speciality_id','user_facility.is_facility_supervisor','user_facility.priv_key','roles.name','user_facility.role_id')
->get();
$superadmin = $is_super_admin->is_super_admin;
$specialities = (object) $specialitiesAndRoles;
$response = ['is_super_admin' => $superadmin, 'facilities' => $specialities];
$userRoles = DB::table('roles')
->join('user_facility', 'roles.id', 'user_facility.role_id')
->where('user_facility.user_id', Auth::user()->id)
->value('roles.name');
if ($access_module) {
$module = $this->modules->find($access_module->module_id);
$user = DB::table('verify_users')->where('user_id', $currentUser->id)->first();
if ($user) {
DB::table('verify_users')->where('id', $user->id)->update([
'token' => $token,
]);
DB::table('verify_users')->insert([
'token' => $token,
'user_id' => $currentUser->id,
'role' => $userRoles
]);
} else {
DB::table('verify_users')->insert([
'token' => $token,
'user_id' => $currentUser->id,
'role' => $userRoles
]);
}
if ($module->slug == 'medical-doctors') {
$md_db = DB::connection('doctorDB');
$user = $md_db->table('auth_token')->where('user_id', $currentUser->id)->first();
$md_db = DB::connection('doctorDB');
$user = $md_db->table('auth_token')->where('user_id', $currentUser->id)->first();
if ($user) {
$md_db->table('auth_token')->where('id', $user->id)->update([
'token' => $token,
'isValid' => 1,
]);
} else {
$md_db->table('auth_token')->insert([
'token' => $token,
'isValid' => 1,
'user_id' => $currentUser->id
]);
}
}
} else {
$module = NULL;
}
$user_data = $this->GetUserInfo();
return response()->json([
'status' => true,
'message' => 'Login successfully',
'data' => [
'token' => $token,
'userData' => $currentUser,
'userInfo' => $user_data,
'privileges' => $response,
'module' => $module
]
]);
I am handling multiple scenarios in my login API that's why it looks large and now I want to login user with lat and long from my current position around 800m nearest location.
How can I achieve this functionality?

laravel register user if the call to an api is returns a valid access token

I want to register a new user : the procedure is to call an api with a client id and a client secret and if everything is ok I save the user. If not I redirect with an error message.
But when I try to redirect to the register route inside my validator I got this error Call to a member function validate() on string.
protected function validator(array $data)
{
$messages = [
'client_secret.size' => 'Secret Id must be exactly 36 characters',
];
$client_id = $data['client_id'];
$client_secret = $data['client_secret'];
$access = $this->getAccessToken($client_id, $client_secret);
if($access == false){
return route('register');
}
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'role' => 'required|string',
'country' => 'required|string',
'client_id' => 'required|string',
'client_secret' => 'required|string|size:36'
], $messages);
}
I did that before seeing your answer. I think it's similar.
protected function validator(array $data)
{
$messages = [
'client_secret.size' => 'Secret Id must be exactly 36 characters',
'access_token.required' => 'We could not get an access token, make sure that the client id and the client secret are correct'
];
$input = [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'role' => 'required|string',
'country' => 'required|string',
'client_id' => 'required|string',
'client_secret' => 'required|string|size:36',
'access_token' => 'required|string|min:10'
];
$client_id = $data['client_id'];
$client_secret = $data['client_secret'];
$access = $this->getAccessToken($client_id, $client_secret);
if($access == false){
$data['access_token'] = 'false';
}else{
$data['access_token'] = $access ;
}
return Validator::make($data, $input, $messages);
}
This is a wrong implementation. The validator function returns route('register') on failing to get access token this a string returned. But at the same time if the access token is fetched, you return a validator instance. The code that calls this will try to run the validate method which would fail in the first scenario. And the way this function is coded, you can't redirect from within it. If you really need to then you could do something like this
Validator method
if($access == false) {
throw new \Exception('Failed to get access token');
}
Calling logic
try {
$validator = $this->validator($data);
} catch (\Exception $e) {
return redirect()->route('register');
}
if ($validator->fails()) {
// handle
}
OR
Validator method
if($access == false) {
return null;
}
Calling logic
$validator = $this->validator($data);
if ($validator === null) {
return redirect()->route('register');
}
if ($validator->fails()) {
// handle
}

Laravel Passport password grant returns Invalid Credentials Exception

I am trying to setup a SPA that consumes a Laravel API protected with Passport.
I started by creating a new Laravel app specifically for this and I then followed the instructions for setting up passport and set up a password grant client.
I can successfully create a new user, save the user to the database, and log the user in. After that, I try to use the newly created user's information along with the password grant clients id and secret to create an access token. At this point I receive the exception.
I read through the log and I saw where the exception was being thrown. Inside League\OAuth2\Server\Grant\PasswordGrant the validateUser method has the following:
if ($user instanceof UserEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidCredentials();
}
Seeing this I implemented the UserEntityInterface on my user model and implemented the getIdentifier method but I still receive the Exception. I'm really not too sure where to go from here, any help would be greatly appreciated. Below is some of my code.
Here is my Registration controller:
class RegisterController extends Controller
{
private $tokenService;
public function __construct(AccessTokenService $tokenService)
{
//$this->middleware('guest');
$this->tokenService = $tokenService;
}
public function register(Request $request)
{
$this->validateWith($this->validator($request->all()));
Log::debug('Validated');
$user = $this->create($request->all());
$this->guard()->login($user);
$this->tokenService->boot(Auth::user());
return response()->json($this->tokenService->getNewAccessToken(), 200);
}
protected function guard()
{
return Auth::guard();
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
'password_confirmation' => 'required'
]);
}
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}
And these are the relevant portions of AccessTokenService:
public function getNewAccessToken() {
$http = new Client();
$client = \Laravel\Passport\Client::where('id', 6)->first();
Log::debug($client->getAttribute('secret'));
Log::debug($this->user->getAttribute('email'));
Log::debug($this->user->getAuthPassword());
$response = $http->post('homestead.app/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 6,
'client_secret' => $client->getAttribute('secret'),
'username' => $this->user->getAttribute('email'),
'password' => $this->user->getAuthPassword(),
'scope' => '*'
]]);
unset($client);
$status = $response->getStatusCode();
$body = $response->getBody();
Log::debug($body->getContents());
Log::debug($status);
switch($status)
{
case 200:case 201:
case 202:
$tokens = array(
"user_id" => $this->user->getAttribute('id'),
"access_token" => $body['access_token'],
"refresh_token" => $body['refresh_token']
);
$output = ["access_token" => $this->storeTokens($tokens), 'status_code' => $status];
break;
default:
$output = ["access_token" => '', 'status_code' => $status];
break;
}
return $output;
}
private function storeTokens(array $tokens) {
UserToken::create([
"user_id" => $tokens['user_id'],
"access_token" => bcrypt($tokens['access_token']),
"refresh_token" => bcrypt($tokens['refresh_token'])
]);
return $tokens['access_token'];
}
So I figured out the issue. When I was requesting the access token I was passing in the user's email and password but I was passing the hashed password when I needed to pass in the unhashed password.
My request for an access token looked like this:
$response = $http->post('homestead.app/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 6,
'client_secret' => $client->getAttribute('secret'),
'username' => $this->user->getAttribute('email'),
'password' => $this->user->getAuthPassword(), //Here is the problem
'scope' => '*'
]]);
By passing the Request to the function using the unhashed password like this solved the problem:
$response = $http->post('homestead.app/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 6,
'client_secret' => $client->getAttribute('secret'),
'username' => $request['email'],
'password' => $request['password'],
'scope' => '*'
]]);
In my case it was magic
when i changed username from email format to simple (alphanumeric only) format it works.
please tell the reason if anyone have for my case.
Thanks

An active access token must be used to query information about the current user in laravel

I am trying to login with facebook using angularjs with laravel. But I am stuck with this error:
{"error":{"message":"An active access token must be used to query
information about the current user.","type":"OAuthExce (truncated...)
Here is my Controller:
public function facebookLogin(Request $request){
$client = new GuzzleHttp\Client();
$params = [
'code' => $request->input('code'),
'client_id' => $request->input('clientId'),
'redirect_uri' => $request->input('redirectUri'),
'client_secret' => Config::get('app.facebook_secret'),
'grant_type'=>'client_credentials'
];
// Step 1. Exchange authorization code for access token.
$accessTokenResponse = $client->request('GET', 'https://graph.facebook.com/v2.5/oauth/access_token', [
'query' => $params
]);
$accessToken = json_decode($accessTokenResponse->getBody(), true);
// Step 2. Retrieve profile information about the current user.
$fields = 'id,email,first_name,last_name,link,name,picture';
/**** problem counted with this request ************/
$profileResponse = $client->request('GET', 'https://graph.facebook.com/v2.5/me', [
'query' => [
'access_token' => $accessToken['access_token'],
'fields' => $fields
]
]);
$profile = json_decode($profileResponse->getBody(), true);
$user = User::where('email', '=', $profile['email'])->first();
if($user) {
Auth::loginUsingId($user->id);
$user_info = Auth::user();
$profile_seen = $user_info->profile_seen;
User::where('id', '=', $user_info->id)->update(array('profile_seen' => 1));
return Response::json(['login' => Auth::check(),'profile_seen' => $profile_seen ]);
}else{
$user = User::create(array(
'username' => $profile['name'],
'email' => $profile['email'],
'first_name' => $profile['first_name'],
'last_name' => $profile['last_name'],
'facebook_id'=> $profile['id']
));
Auth::loginUsingId($user->id,1);
$user_info = Auth::user();
$profile_seen = $user_info->profile_seen;
User::where('id', '=', $user_info->id)->update(array('profile_seen' => 1));
return Response::json(['login' => Auth::check(),'profile_seen' => $profile_seen ]);
}
}
I have encountered this problem. You need to run the composer update. Then run the command composer dump-autoload. This problem has been fixed in version Socialite v2.0.21.

Categories