I made a google login through socialite in laravel
public function redirectToProvider($provider)
{
$url = Socialite::driver($provider)->stateless()->redirect()->getTargetUrl();
return $url;
//return response()->json(['url' => $url], 200);
}
public function handleProviderCallback($provider)
{
$user = null;
if (Helper::validateProvider($provider) === false) {
return response()->json(['message' => 'The provider is not accepted temporally'], 422);
}
try {
$userProvider = Socialite::driver($provider)->stateless()->user();
} catch(\Exception $e) {
\Log::error($e->getMessage());
return response()->json(["message" => "An error occured while trying to login with {$provider}"], 422);
}
if (empty($userProvider)) {
return response()->json(["message" => "Invalid user provider"], 422);
}
if (empty($userProvider->id)) {
return response()->json(["message" => "Invalid provider id"], 422);
}
if (empty($userProvider->name)) {
return response()->json(["message" => "Invalid provider name"], 422);
}
if (empty($userProvider->email)) {
return response()->json(["message" => "Invalid provider email"], 422);
}
DB::transaction(function () use ($userProvider, $provider, &$user) {
$user = User::firstOrCreate([
'provider_id' => $userProvider->id,
'provider_name' => $provider,
], [
'email' => $userProvider->email,
'email_verified_at' => now(),
]);
});
if (! $user) {
return response()->json(["message" => "Cannot create an account"]);
}
$token = $user->createToken('token')->plainTextToken;
$response = [
'user' => $user,
'token' => $token,
'isAdmin' => $isAdmin
];
return response($response);
}
But now I do not know how I could proceed with these two api and take the data properly in my application de vue
I use vue3 and there I don't have much advantage of books already written
Is there a way I can get data from google?
For example, if I open the 2 apies in the browser, I can log in and my token will be returned
But in view, if I made a call to callback it would be a matter of course because I would send something to google
How can I proceed /
Related
I am trying to use Socialite in Laravel to login with Google accounts and Facebook accounts
I installed Socilaite package and added 'google' driver to services.php and made all the necessary configurations in the database and the providers and I made the facebook login and it works well, but google is not working well
The functions
public function redirectToGoogle()
{
return Socialite::driver('google')->redirect();
}
public function handleGoogleCallback()
{
try {
$user = Socialite::driver('google')->user();
$finduser = User::where('social_id', $user->id)->first();
if($finduser){
Auth::login($finduser);
return redirect(route('home'));
} else {
$newUser = User::create([
'name' => $user->name,
'email' => $user->email,
'social_id'=> $user->id,
'social_type'=> 'google',
'password' => encrypt('my-google')
]);
Auth::login($newUser);
return redirect(route('home'));
}
} catch (Exception $e) {
dd($e->getMessage());
}
}
And this is what I get
I'm using stateless fromUserToken
and this is the error I'm getting:
"errors": {
"error": "Client error: `GET https://www.googleapis.com/oauth2/v3/userinfo?prettyPrint=false` resulted in a `401 Unauthorized` response:\n{\n \"error\": \"invalid_request\",\n \"error_description\": \"Invalid Credentials\"\n}\n",
"code": 401
}
this is my endpoint that I use, it worked with all the sections I have in
public function authenticate (Request $request, $provider) {
//Validate provider
// Authenticate
$userSocial = null;
try {
if ($provider == 'twitter') {
$userSocial = Socialite::driver('twitter')->userFromTokenAndSecret($request->token, $request->token_secret);
} else {
$accessToken = $request->token;
$userSocial = Socialite::driver($provider)->stateless()->userFromToken($accessToken);
}
} catch (\Exception $e) {
return $this->respondError('Login error',[
'error' => $e->getMessage(),
'code' => $e->getCode()
],401);
}
$user = User::where([
'provider' => $provider,
'provider_id' => $userSocial->id
])->first();
if($user){
$token = $user->createToken('api')->plainTextToken;
return $this->respondWithToken($token, 'Logged in successfully', false);
} else {
$user = User::create([
'name' => $userSocial->getName() ?: 'Apple User',
'email' => $userSocial->getEmail(),
'image' => $userSocial->getAvatar(),
'provider_id' => $userSocial->getId(),
'provider' => $provider,
]);
$token = $user->createToken('api');
return $this->respondWithToken($token, 'Registered successfully', true);
}
}
Any Idea how to solve it?
and this is the code I used
The token that I was getting was jwt token, not access token. so It had problems with decoding it with stateless socialite function.
when requesting for authorization, you should set the response_type and scope url parameter like below:
scope = profile email
response_type = token
I am creating an API for my application using JWT. It is for different table not for users table. How can I authenticate login user with another table for exapmle students table and create jwt token.
For the User table user authentication function which is working, & its is as below:
$credentials = $request->only(['email', 'password']);
try {
$token = Auth::guard()->attempt($credentials);
if(!$token) {
return response()->json([
'message' => "Email and password do not match",
'status_code' => 204,
]);
}
$user = Auth::user();
if($user->status == "Inactive") {
return response()->json([
'message' => "User ID is disabled",
'status_code' => 403,
]);
}
$user->last_login = Carbon::now();
$user->save();
$user = Auth::user();
$user->UserDeviceData()->firstOrCreate([
'device_id' => $request->device_id,
'device_type' => $request->device_type ? $request->device_type : "ios",
]);
return (new UserTransformer)->transform($user,[
'request_type' => 'login',
'token' => $token
]);
} catch (JWTException $e) {
return response()->json([
'message' => "Internal server error",
'status_code' => 500,
]);
}
And here is the OTP verification function and its code look like :
public function verify(Request $request)
{
try
{
$token = config('app.TWILIO_AUTH_TOKEN');
$twilio_sid = config('app.TWILIO_SID');
$twilio_verify_sid = config('app.TWILIO_VERIFY_SID');
$twilio = new Client($twilio_sid, $token);
$phoneNumber = $request->get('phone_number');
$verification = $twilio->verify->v2->services($twilio_verify_sid)->verificationChecks->create($request->get('verification_code'), array('to' => $request->get('phone_number')));
if ($verification->valid) {
// Updating table student table that the number is verified & want to return JWT token for authenticate user
return response()->json([
"status_code" => 200,
"message" => "Phone number verified."
]);
}
return response()->json([
"status_code" => 200,
"message" => "Verification failed."
]);
}catch (Exception $e){
return response()->json([
'response' => [
'code' => 401,
'message' => "Unable to verify OTP.Please try again.",
],
]);
}
}
How can I authenticate the verified user which is on another table.
I'm working on an api in Laravel and want to edit the login procedure a bit.
Users log in with a username and a password but as a third parameter I want to add an app_id.
This is because usernames can be double in the database when the app_id is different. This is my current login code. It's using JWT as a driver.
$credentials = request(['username', 'password']);
if(!$token = auth()->attempt($credentials)) {
return response()->json([
'error' => ['code' => 1],
'status' => 'error',
], 401);
}
How can I accomplish this?
Kind regards,
Kevin Walter
Edit: My entire AuthController
class AuthController extends Controller
{
public function __construct()
{
$this->middleware('jwt.verify', ['except' => ['login', 'refresh']]);
}
/**
* Login to get JWT credentials
*/
public function login() {
//TODO: LOCKOUT AFTER X AMOUNT OF TRIES
if(!$token = auth()->attempt($this->credentials())) {
return response()->json([
'error' => ['code' => 1],
'status' => 'error',
], 401);
}
return $this->me(true, $token);
}
public function checkPin() {
$username = request('username');
$pincode = request('pincode');
$user = auth()->user();
if($user && $user->username && $user->pincode && $username == $user->username && $pincode == $user->pincode) {
return $this->outputJson(0, 'auth', 'checkPin',[
"firebase_key" => $this->create_custom_token($user->uid, true),
"pin_ok" => 1,
]);
} else {
return $this->outputJson(0, 'auth', 'checkPin', ["pin_ok" => 0]);
}
}
public function me($withToken = false, $token = "") {
$user = auth()->user();
$output = $user;
$output->groups = $user->groups;
$output->categories = $user->categories;
$output->hasPin = $user->hasPin();
$headers = array();
if($withToken) {
$headers["X-TOKEN-RETURN"] = $token;
}
return $this->outputJson('0', 'auth', 'me', $output, $headers);
}
public function logout() {
auth()->logout();
return response()->json(['message' => 'Successfully logged out']);
}
}
It was just as simple as merging the app_id in the credentials. This is the working example!
//Add app ID into the mix of credentials
protected function credentials()
{
return array_merge(request(['username', 'password']), ['app_id' => \request()->header('X-APP-ID')]);
}
/**
* Login to get JWT credentials
*/
public function login() {
//TODO: LOCKOUT AFTER X AMOUNT OF TRIES
if(!$token = auth()->attempt($this->credentials())) {
return response()->json([
'error' => ['code' => 1],
'status' => 'error',
], 401);
}
return $this->me(true, $token);
}
So I am trying to return User data with login request. I am using guzzle and I do not know how to attach data to response.
Here is the login method
public function login(Request $request)
{
$http = new \GuzzleHttp\Client;
try {
$response = $http->post(config('services.passport.login_endpoint'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => config('services.passport.client_id'),
'client_secret' => config('services.passport.client_secret'),
'username' => $request->username,
'password' => $request->password,
]
]);
return $response->getBody();
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
if ($e->getCode() === 400) {
return response()->json('Invalid Request. Please enter a username or a password.', $e->getCode());
} else if ($e->getCode() === 401) {
return response()->json('Your credentials are incorrect. Please try again', $e->getCode());
}
return response()->json('Something went wrong on the server.', $e->getCode());
}
}
I would like to do something like this
$user = User::where('email', $request->username)->get();
$token = $response->getBody();
return response()->json($token, $user);
However when I try this I get error. Any help would be greatly appreciated. Currently I am having to make separate request after access token to return the user data thus I would like for it to happen at the same time....
The first argument of json method can be an array:
return response()->json(['token' => $token, 'user' => $user ]);
I was recommended the following discussion and it solved my issue. here is the final code
public function login(Request $request)
{
$http = new \GuzzleHttp\Client;
try {
$response = $http->post(config('services.passport.login_endpoint'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => config('services.passport.client_id'),
'client_secret' => config('services.passport.client_secret'),
'username' => $request->username,
'password' => $request->password,
]
]);
$token = $response->getBody();
$data = json_decode($token, true);
$user = User::where('email', $request->username)->with('role.rules')->get();
$rules = $user->pluck('role')->collapse()->pluck('rules');
$rules->put('access_token', $data['access_token']);
return response()->json($rules);
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
if ($e->getCode() === 400) {
return response()->json('Invalid Request. Please enter a username or a password.', $e->getCode());
} else if ($e->getCode() === 401) {
return response()->json('Your credentials are incorrect. Please try again', $e->getCode());
}
return response()->json('Something went wrong on the server.', $e->getCode());
}
}