Laravel Socialite Google login only with one domain - laravel

I have a Google+ login on my app with Laravel Socialite. When the login is done I have a callback to connect the user (I create her in database if necessary).
But I want to restrain the connection to only the company (email like "example#company.com", so only the email with "company.com").
Can I do it with Laravel Socialite ? I can make the verification manually in my callback but if Socialite can do it, it's better.
Thank you
My callback :
public function handleProviderCallback($provider){
$user = Socialite::driver($provider)->user();
if ($user) {
$local_user = User::whereEmail($user->getEmail())->first();
// If we don't have a user create a new user
if (!$local_user) {
$fragment = explode(' ', $user->getName());
$local_user = User::create([
'first_name' => isset($fragment[0]) ? $fragment[0] : '',
'last_name' => isset($fragment[1]) ? $fragment[1] : '',
'email' => $user->getEmail(),
'last_seen' => Carbon::now(),
'password' => ''
]);
$local_user->roles()->attach(Role::whereName('User')->first());
}
auth()->login($local_user);
}
return redirect($this->redirectTo);
}

You have a step by step guide for domain restriction.
In controller you need to specifiy these actions:
public function handleProviderCallback()
{
try {
$user = Socialite::driver('google')->user();
} catch (\Exception $e) {
return redirect('/login');
}
// only allow people with #company.com to login
if(explode("#", $user->email)[1] !== 'company.com'){
return redirect()->to('/');
}
// check if they're an existing user
$existingUser = User::where('email', $user->email)->first();
if($existingUser){
// log them in
auth()->login($existingUser, true);
} else {
// create a new user
$newUser = new User;
$newUser->name = $user->name;
$newUser->email = $user->email;
$newUser->google_id = $user->id;
$newUser->avatar = $user->avatar;
$newUser->avatar_original = $user->avatar_original;
$newUser->save();
auth()->login($newUser, true);
}
return redirect()->to('/home');
}

No, you can’t do it in Socialite itself because Socialite is just a mechanism of retrieving tokens from OAuth-compliant servers.
If you only want to accept users with a particular email suffix, then that’s business logic so something you should handle in your callback:
public function handleProviderCallback()
{
$user = Socialite::driver('google')->user();
if (Str::endsWith($user->getEmail(), '#example.com')) {
// Look up user and authenticate them
}
abort(400, 'User does not belong to organization');
}

Related

Auth system laravel just with phone number and verification sms code

my web app is laravel and my users do not have email and password and they register and login with phone number and verification sms code.
My db is Mongodb.
How to I change Auth system laravel?
you will need to implement your own Auth system .First you will need to send SMS I recommend using Twilio https://www.twilio.com/blog/create-sms-portal-laravel-php-twilio
Here is some functions I made before
public function sendVerificationCode(VerificationCodeRequest $request)
{
$twilioService = new TwilioService() ;
$otp = random_int(1000, 9999);
$result = $twilioService->sendVerificationCode(request('mobile'), $otp );
if (!$result) {
return response()->json(["message"=>__('messages.wrong_number')],422);
}
}
$user = User::updateOrCreate(
['mobile' => request('mobile')],
['verification_code' => $otp]
);
return response()->json(["message"=>__('messages.otp_sent')],200);
}
public function login(MobileLoginRequest $request)
{
$user = User::where("mobile",request('mobile'))->firstOrFail();
if($user->verification_code==$otp){
if ( !$userToken=JWTAuth::fromUser($user)) {
return response()->json(['message' => __('messages.Unauth')], 401);
}
}else{
return response()->json(['message' => __('messages.invalid_otp')], 401);
}
$user->update(["verified"=>1,"login_type"=>"mobile"]);
return $this->respondWithToken($userToken,$user);
}
protected function respondWithToken($userToken,$user)
{
return response()->json([
'token' => $userToken,
'token_type' => 'bearer',
'expires_in' => JWTAuth::factory()->getTTL() * 60,
'profile' => $user,
], 200);
}
the twilio service file
<?php
namespace App\Http\Services;
use Illuminate\Support\Facades\Log;
use Twilio\Rest\Client;
class TwilioService
{
public function sendVerificationCode($number,$otp){
return $this->sendMessage("your Verification Code is : $otp ",$number);
}
public function sendNotification($recipient,$body,$title){
return $this->sendMessage($body,$recipient,$title."\n");
}
private function sendMessage($message, $recipient,$title="")
{
try {
$account_sid = getenv("TWILIO_SID");
$auth_token = getenv("TWILIO_AUTH_TOKEN");
$twilio_number = getenv("TWILIO_NUMBER");
$client = new Client($account_sid, $auth_token);
$client->messages->create("$recipient",
['from' => $twilio_number, 'body' => $title.$message] );
return true;
} catch (\Throwable $th) {
Log::error("$th");
Log::info("-------unable to send SMS to phone $recipient -------------");
return false;
}
}

give only authenticated user ability to fetch his own data with Laravel API and Sanctum

i have this function for get orders for only authenticated user:
function show($uid) {
try {
$user = User::findOrFail($uid);
$orders = $user->orders;
return $orders;
}catch (\Exception $e) {
return response()->json(['messsage' => "cannot show order for this user"]);
}
}
it is a end point for API in this route:
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::get('/order/{id}', [OrdersController::class, 'show']);
});
but now if anyone just add any uid, he can display all orders...
my question is how can i protect this function so just auth user can fetch data: and i have used Sanctum in my project
in laravel with blade i just do like this:
function show() {
$uid = auth()->id();
try {
$user = User::findOrFail($uid);
$orders = $user->orders;
return $orders;
}catch (\Exception $e) {
return response()->json(['messsage' => "cannot show order for this user"]);
}
}
Thank you all...... I have found the solution, i could find the id of Authenticated user simply by this since i use the guard (sanctum):
auth('sanctum')->user()->id
this will give me the id for auth user depending on the token.
and the solution will be like this:
function show(Request $request) {
try {
$uid = auth('sanctum')->user()->id;
$user = User::findOrFail($uid);
$orders = $user->orders;
return $orders;
}catch (\Exception $e) {
return response()->json(['messsage' => "cannot show order for this user"]);
}
}

How to access laravel API with VUE JS?

so i want to use mylogin api but its not working,it keep push the route to dashboard even the email and the password incorrect
here is my code
export default {
data(){
return{
form: {
email: null,
password: null
},
user: {},
error: false
}
},
methods: {
login() {
this.user.append("email", this.form.email);
this.user.append("password", this.form.password);
this.axios.post('http://127.0.0.1:8000/api/login', this.user).then(response => {
localStorage.setItem("Name", response.data.first_name);
this.$router.push('/userDashboard/Dashboard')
});
},
register() {
this.$router.push('/RegisterPage')
}
},}
my laravel route api
Route::post('/login', 'UserController#login');
Login function
public function login(Request $request, User $user)
{
$email = $request->input('email');
$password = $request->input('password');
$user = User::where('email', '=', $email)->first();
if (!$user) {
return response()->json(['success'=>false, 'message' => 'Login Fail, please check email']);
}
if (!Hash::check($password, $user->password)) {
return response()->json(['success'=>false, 'message' => 'Login Fail, pls check password']);
}
return response()->json(['success'=>true,'message'=>'success', 'data' => $user]);
}
sorry for my english
This is because your laravel app always return 200 HTTP responses and this causes the .then( ... ) in the frontend to always be executed.
Either in the .then( ... ) your check the success value on the response that your Laravel has set, like this:
this.user.append("email", this.form.email);
this.user.append("password", this.form.password);
this.axios.post('http://127.0.0.1:8000/api/login', this.user).then(response => {
if (response.data.success === false) {
// handle the error and stop the code with a return
this.handleError();
return;
}
localStorage.setItem("Name", response.data.first_name);
this.$router.push('/userDashboard/Dashboard')
});
OR, you can also in Laravel throw a 401 or 400 response to say the login failed which will throw an exeception in the frontend, that you can catch with .then( ... ).catch( ... ).
That is the most clean way, because no need to send 'success' => true true anymore, since the HTTP code will be the source of truth with what happend.
public function login(Request $request, User $user)
{
$email = $request->input('email');
$password = $request->input('password');
$user = User::where('email', '=', $email)->first();
if (!$user || !Hash::check($password, $user->password)) {
// never tell the person if it's email or password, always say it's one of both for security reasons
return response(401)->json(['message' => 'Login Fail, please check email or password']);
}
return response()->json(['data' => $user]);
}
Last thing, I don't understand how this.user.append("email", this.form.email); works, because this.user seems to just be a simple object, so there isn't any append method on it.
So unless I'm missing something here, the best thing should just be to do:
const user = {
email: this.form.email,
password: this.form.password
}
// OR, make a copy
const user = { ...this.form }
// then send the user var to axios
this.axios.post('your url', user).then( ... )

How To Get Auth ID form user table and grab it for store to other table on database

I want to get Auth ID from user who has logged in and then use the Auth ID to store on other table
User_detail Controller
this is my store function
$data = new ModelUser();
$user= new user();
$data->fill(Auth::user());
$data->id_user = Auth::get('id');
$data->jenis_kelamin = $request->jenis_kelamin;
$data->no_tlp = $request->no_tlp;
$data->jurusan = $request->jurusan;
$data->wilayah = $request->wilayah;
$data->save();
return redirect()->route('surveylist');
and this is function Login
public function LoginPost(Request $request)
{
$email = $request->email;
$password = $request->password;
$data = user::where('email',$email)->first();
if($data) //check email apakah ada atau tidak
{
if(Hash::check($password,$data->password))
{
Session::put('id',$data->id);
Session::put('full_name',$data->full_name);
Session::put('email',$data->email);
Session::put('login',TRUE);
return redirect('userdt');
}
else
{
return redirect('index')->with('alert','Password atau Email yang anda masukan salah !!! ' );
}
}
}
this is the routes files
Route::get('/index','UserController#show')->name('surevey.index');
Route::get('/logout','UserController#Logout')->name('user.logout');
Route::post('/registerpost','UserController#RegisterPost')->name('user.register');
Route::post('/loginpost','UserController#LoginPost')->name('user.login');
//reward routes
Route::get('/reward','RewardController#index')->name('reward.list');
//profile
Route::put('/editprofile/edit/{id}','UserController#edit')->name('profile.edit');
Route::post('/editprofile/update','UserController#update')->name('profile.update');
Route::get('/userdt',['middleware'=>'auth','uses'=>'UserController#userdetail'])->name('userdt.show');
Route::post('/userdt/store','UserController#store')->name('userdt.store');
//Survei
Route::get('/createsurvey','SurveyController#show')->name('survey.create');
Route::get('/surveylist','SurveyController#index')->name('survey.list');
Auth::routes();
ModelUser
protected $fillable = [
'id_user',
'jenis_kelamin',
'no_tlp',
'jurusan',
'wilayah'
];
protected $table ='user_detail';
public function user()
{
return $this->belongsTo(user::class);
}
and I get error like this
Argument 1 passed to Illuminate\Database\Eloquent\Model::fill() must
be of the type array, null given, called in
E:\Laravel\surevey\app\Http\Controllers\UserController.php on line 110
You don't need to use $data->fill(Auth::user()); as you have only single user_id field need to set.
Also you can get the current logged in user's id using. \Auth::user()->id
So your code would be as follow:
$data = new ModelUser();
$data->id_user = \Auth::user()->id;
$data->jenis_kelamin = $request->jenis_kelamin;
$data->no_tlp = $request->no_tlp;
$data->jurusan = $request->jurusan;
$data->wilayah = $request->wilayah;
$data->save();
return redirect()->route('surveylist');
Note: Make sure you have included auth middleware with your route.
Like:
Route::get('profile', ['middleware' => 'auth', function() {
// Only authenticated users may enter...
}]);
And you have followed the authuntication process carefully.
https://laravel.com/docs/5.2/authentication
Edited:
Your loging should be changed as:
public function LoginPost(Request $request)
{
$email = $request->email;
$password = $request->password;
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
return redirect()->intended('userdt');
}
return redirect('index')->with('alert','Password atau Email yang anda masukan salah !!! ' );
}
If your reverse one-to-one relationship in the User Model looks like this:
public function detail()
{
return $this->hasOne(ModelUser::class);
}
And you are sure a user is logged in, you could simply do this
$data = Auth::user()->detail()->save($request->all());
return redirect()->route('surveylist');
Laravel's ORM takes care of the rest.
should be Auth::id() or Auth::user()->id but seems like your Auth::user() is returning a null.make sure you sessions, routes are set up properly.
use Auth::attempt()to login user

Socialite function getId() is working but id is not added in database phpmyadmin

I am using Laravel Socialite for google login all the scoialite functions are working fine and data is being added to the database(phpmyadmin) except for the provider_id which function is getId() which is also working fine but data is not inserted in Db.
public function handleProviderCallback()
{
try{
$socialUser = Socialite::driver('google')->user();
}catch(Exception $e){
redirect('/');
}
$socialProvider = SocialProvider::where('provider_id', $socialUser->getId())->first();
if(!$socialProvider){
//create new user
$user = User::firstOrCreate(
['email' => $socialUser->getEmail()],
['name' => $socialUser->getName()]
);
$user->socialProviders()->create(
['provider_id' => $socialUser->getId() , 'provider' => 'google']
);
}
else{
$user = $socialProvider->user;
}
auth()->login($user);
return redirect('/home');
//return $socialUser->getId();
}
'provider_id' must be the protected $fillable array on the SocialProvider model if you want to pass it in the array to SocialProvider->create(...).

Resources