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
Related
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 /
public function productData(Request $request)
{
$product_no = $request->product_no;
$response = array();
if($request->product_no)
{
try
{
$header = $request->header();
$Authorization = $request->header('Authorization');
dd($Authorization);
if (empty($Authorization))
{
$data = "Authorization key invalid";
return $data;
}
else
{
$sp_token = str_replace("Bearer ", "", $Authorization);
$varify_token = 'ZQWmRjUyNDJDQUFGRjBBOUMzMUZGQUVEOTA4QkYzOEU2RENBNEQ4OTIwMzRGQzY1NDA0QzIyMjk3RkJENkRzdsg=====';
if($sp_token == $varify_token)
{
$response = array(
'status' => 200,
'message' => 'success',
);
}
else
{
$response = array(
'status' => 300,
'message' => 'Invalid Bearer Token',
);
}
}
}
catch (\Exception $e)
{
$response = array(
'status' => 500,
'message' => 'Data Not Found',
'msgErr' => 'Something went wrong',
'result' => '0');
}
}
else
{
$response = array(
'status' => 0,
'message' => 'product Number Empty',
);
}
return response()->json($response);
}
Above code working in local server and when print $Authorization then it return Bearer Token but same code not working on production server when I hit API using production URL using postman then it return Authorization key invalid and when I print or dd $Authorization then it return null. I don't know why?. Please help me.
Thank you
The Authorization header might be stripped by your webserver or reverse proxy. Try renaming it to anything that isn't a default HTTP header. For example: Token.
Any route or url that uses Auth() must be encapsulated in the web middleware.
Let me explain using e.g
Route::group(['middleware' => '['web','auth']', function () {
Auth::user();
//Other auth routes
});
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.
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());
}
}
I am trying to generate a bearer token with access and refresh tokens after user authenticates with socialite.
public function handleProviderCallback($provider, EmailConfirmationMailer $mailer)
{
$user = Socialite::driver($provider)->user();
if(User::where('email', '=', $user->getEmail())->exists()){
$exist_user = User::where('email', '=', $user->getEmail())->first();
Auth::loginUsingId($exist_user->id);
$http = new GuzzleHttp\Client;
$response = $http->post('http://localhost:8000/oauth/token', [
'form_params' => [
'grant_type' => 'refresh_token',
'refresh_token' => 'the-refresh-token',
'client_id' => 1,
'client_secret' => 'c4ojSmOjl04QrshdSXlOmbKUOIxm6zqyhND34AT0',
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}else{
//create new user here
}
}
I got the error from vendor\laravel\socialite\src\Two\AbstractProvider.php
user function, message is "".
public function user()
{
if ($this->hasInvalidState()) {
throw new InvalidStateException;//here is the highlighted
}
$response = $this->getAccessTokenResponse($this->getCode());
$user = $this->mapUserToObject($this->getUserByToken(
$token = Arr::get($response, 'access_token')
));
return $user->setToken($token)
->setRefreshToken(Arr::get($response, 'refresh_token'))
->setExpiresIn(Arr::get($response, 'expires_in'));
}
What is the best practice for this situation? Any help is greatly appreciated.
resorted to generate accessToken with no refreshToken:
public function handleProviderCallback($provider)
{
$user = Socialite::driver($provider)->user();
if(User::where('email', '=', $user->getEmail())->exists()){
$existUser = User::where('email', '=', $user->getEmail())->first();
Auth::login($existUser,true);
//remove existing tokens from user
$tokenResult = $existUser->createToken('Personal Access Token');
return \response()->json([
'token_type' => 'Bearer',
'expires_in' => $tokenResult->token->expires_at->diffInSeconds(Carbon::now()),
'access_token' => $tokenResult->accessToken,
'info' => 'Existing user'
]);
}else{
//create new user entry
}
}