how to make frontend api authentication in laravel - php

I have created an API Authentication system in Laravel using passport package. when a user log in every time create a personal access token and when logout token is revoked. I have tested it in Postman. but when I try to this from frontend I can't manage the personal access token for every request and response. now, I want to know How can i manage the Personal Access Token from frontend and add the token for every request an upcoming request.
Here is my code sample.
public $successStatus = 200;
public function login()
{
if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){
$user = Auth::user();
$success['token'] = $user->createToken('Personal Access Token')->accessToken;
return response()->json(['success' => $success], $this->successStatus);
}
else{
return response()->json(['error'=>'Unauthorised'], 401);
}
}

You have to add below headers for every request
[
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
]
For more information, refer here

Related

Laravel Set Session or Token for External User Login Successfully - No User Database Only Api user

I am pulling User Information from an external site with external API. I have completed the user login route on the Laravel and I get the data from the controller file. There is no problem in terms of pulling and displaying data from an external user API link.
How to do token and session operation like regular Laravel user to the user logged in with external API without the database. Note that I can use the same token part of the user API token available
In addition, I don't want to transfer the information by assigning session between the controller each time the user was login. How do I assign tokens in all transactions after user login?
It comes to these controls via post method from login screen
public function loginData(Request $request)
{
$password = $request->password;
$email = $request->email;
$apiman = "Bearer {$this->accesstokenApi()}";
$client = new Client();
$response = $client->post('https://testapi.com/api/v3/Profile', [
'headers' =>
[
'cache-control' => 'no-cache',
'authorization' => $apiman,
'content-type' => 'application/json'
],
'json' =>
[
'Email' => $email,
'Password' => $password
],
]);
$data = json_decode((string) $response->getBody(), true);
if ($data['ResponseType']=="Ok") {
session()->put('token', $data);
return redirect('/user-detail');
} else {
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], 401);
}
}
User logged in OK . After that, what token should the machine give, or where can the session be given to that user in one place? Besides, if the user is logged in, how do I get him to see the home page instead of showing the login form again, just like in Laravel login processes ?
Maybe you can create new middleware that will check if there is a token in the session
Here is the example that you can use and adapt it based on your needs.
namespace App\Http\Middleware;
use Closure;
class Myauth
{
public function handle($request, Closure $next, $guard = null)
{
if(session()->has('token')) {
return $next($request);
} else {
return response('Unauthorized.', 401);
//OR return redirect()->guest('/');
}
}
}

Passing response from social provider back to API endpoint

I am trying to add social authentication to a laravel 5.8 API application using socialite. Following the documentation here https://laravel.com/docs/5.8/socialite#routing I created a SocialAuthController that wiill redirect the user to the provider auth page and handle the callback like this
...
use Socialite;
...
public function redirectToProvider($provider)
{
return Socialite::driver($provider)->redirect();
}
public function handleProviderCallback($provider)
{
// retrieve social user info
$socialUser = Socialite::driver($provider)->stateless()->user();
// check if social user provider record is stored
$userSocialAccount = SocialAccount::where('provider_id', $socialUser->id)->where('provider_name', $provider)->first();
if ($userSocialAccount) {
// retrieve the user from users store
$user = User::find($userSocialAccount->user_id);
// assign access token to user
$token = $user->createToken('string')->accessToken;
// return access token & user data
return response()->json([
'token' => $token,
'user' => (new UserResource($user))
]);
} else {
// store the new user record
$user = User::create([...]);
// store user social provider info
if ($user) {
SocialAccount::create([...]);
}
// assign passport token to user
$token = $user->createToken('string')->accessToken;
$newUser = new UserResource($user);
$responseMessage = 'Successfully Registered.';
$responseStatus = 201;
// return response
return response()->json([
'responseMessage' => $responseMessage,
'responseStatus' => $responseStatus,
'token' => $token,
'user' => $newUser
]);
}
}
Added the routes to web.php
Route::get('/auth/{provider}', 'SocialAuthController#redirectToProvider');
Route::get('/auth/{provider}/callback', 'SocialAuthController#handleProviderCallback');
Then I set the GOOGLE_CALLBACK_URL=http://localhost:8000/api/v1/user in my env file.
When a user is successfully authenticated using email/password, they will be redirected to a dashboard that will consume the endpoint http://localhost:8000/api/v1/user. So in the google app, I set the URI that users will be redirected to after they are successfully authenticated to the same endpoint http://localhost:8000/api/v1/user
Now when a user tries to login with google, the app throws a 401 unauthenticated error.
// 20190803205528
// http://localhost:8000/api/v1/user?state=lCZ52RKuBQJX8EGhz1kiMWTUzB5yx4IZY2dYmHyJ&code=4/lgFLWpfJsUC51a9yQRh6mKjQhcM7eMoYbINluA58mYjs5NUm-yLLQARTDtfBn4fXgQx9MvOIlclrCeARG0NC7L8&scope=email+profile+openid+https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email&authuser=0&session_state=359516252b9d6dadaae740d0d704580aa1940f1d..10ea&prompt=none
{
"responseMessage": "Unauthenticated",
"responseStatus": 401
}
If I change the URI where google authenticated users should be redirect to like this GOOGLE_CALLBACK_URL=http://localhost:8000/auth/google/callback the social user information is returned.
So how should I be doing it. I have been on this for a couple of days now.
That is because you haven't put authorization in your header with your request.
you don't need to redirect user if you are working with token, your app should be a spa project, so you will redirect him from your side using js frameworks.
You need to send Authorization in your headers plus you need to specify it with your token which you returned it in your response like this:
jQuery.ajaxSetup({
headers: {
'Authorization': 'Bearer '+token
}
});
or if you are using axios
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;

ArgumentCountError in Laravel 5.8

I am trying to add social authentication to a Laravel 5.8 API project using socialite.
When trying to handle a social provide callback, the ArgumentCountError is thrown here
Too few arguments to function App\Http\Controllers\SocialAuthController::handleProviderCallback(), 0 passed and exactly 1 expected
The error is referring to the very first line of this code block
public function handleProviderCallback($provider)
{
// retrieve social user info
$socialUser = Socialite::driver($provider)->stateless()->user();
// check if social user provider record is stored
$userSocialAccount = SocialAccount::where('provider_id', $socialUser->id)->where('provider_name', $provider)->first();
if ($userSocialAccount) {
// retrieve the user from users store
$user = User::find($userSocialAccount->user_id);
// assign access token to user
$token = $user->createToken('Pramopro')->accessToken;
// return access token & user data
return response()->json([
'token' => $token,
'user' => (new UserResource($user))
]);
} else {
// store the new user record
$user = User::create([
'name' => $socialUser->name,
'username' => $socialUser->email,
'email_verified_at' => now()
]);
...
// assign passport token to user
$token = $user->createToken('******')->accessToken;
// return response
return response()->json(['token' => $token]);
}
}
Below is how I have set up other code. Frist in env I added
GOOGLE_CLIENT_ID=******
GOOGLE_CLIENT_SECRET=*******
GOOGLE_CALLBACK_URL=https://staging.appdomain.com/api/v1/user
Then modified web.php
Auth::routes(['verify' => true]);
Route::get('/auth/{provider}', 'SocialAuthController#redirectToProvider');
Route::get('/auth/{provider}/callback', 'SocialAuthController#handleProviderCallback');
Lastly in the google app, I added the uri path where users will be redirected to after successful authentication
https://staging.appdomain.com/api/v1/user
How do I fix this?
The callback uri that user should be redirected to after successful authentication was apparently not being cached. So running php artisan route:cache fixed it.

How to get the id_token from Socialite and Google API Client in laravel

I am using socialite to get the user access_token and use that token to get connect to the Google API Client in laravel. Everything is working fine. But I need to get the access token. But it is failed to get in the response. Let me know how to get the id_token from Google API client.
Here is my code
public function callback()
{
$user = \Socialite::driver('google')->user();
$idToken = $this->getIdToken($user);
var_dump($idToken);
}
public function getIdToken($user){
$google_client_token = [
'access_token' => $user->token,
'refresh_token' => $user->refreshToken,
'expires_in' => $user->expiresIn
];
$client = new Google_Client();
$client->setAccessToken(json_encode($google_client_token));
$oauth = new Google_Service_Oauth2($client);
$client->authenticate($_GET['code']); //exchange 'code' with access token, refresh token and id token
$accessToken = $client->getAccessToken();
$userData = $oauth->userinfo->get();
return $userData;
}
This worked for me, using the methods from Laravel's socialite documentation:
config/services add this to the array (with your own keys)
'google' => [
'client_id' => env('GOOGLE_API_ID'),
'client_secret' => env('GOOGLE_API_SECRET'),
'redirect' => env('APP_URL').'/auth/adwords/callback'
],
Set up your routes as per the docs, and then add these to your class and it will dump out the token and expires_in
public function redirectToProvider() {
return Socialite::with('google')->redirect();
}
public function handleProviderCallback(Request $request) {
$adwords_api_response = Socialite::with('google')->getAccessTokenResponse($request->code);
dd($adwords_api_response);
}
I had a similar issue where coming from an Android device I didn't have access to the access_token so I had to pass an auth_token instead. On the server side here's how I handled it to retrieve an access_token.
$driver = Socialite::driver('google');
//In some cases coming from android an auth token may be required to get an access token
$access_token = $driver->getAccessTokenResponse($input['auth_token'])['access_token'];
$googleUser = $driver->userFromToken($access_token);

register new user from api route using laravel passport

I have installed laravel 5.3 and passport pakage.
I followed the documentaition step by step
I can use the following route POST /oauth/token with the following parameters
username
password
client_secret
grant_type
client_id
and I get the following response
{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "access token here",
"refresh_token": "refresh token here"
}
then I request GET /api/user
with the following header
Authorization = "Bearer access token here"
accept = application/json (optional)
and this is work fine and so all apis.
the problem I have is the user who I authinticated and entered his username and password in the first request and return me back the access token is a user I have created from laravel web view /register
How can I create new user or register new user from the api route file
like POST /api/register
the user at first time need to register to be authinticated after that.
Should I create this route without oauth to register then if success the registration he request POST /oauth/token to be authinticated or what?
Am I missing something ??
update
the clent_secret is it right to be constant in all users requests or each user should have diffrent clent_secret, and if it is how to create aclent secret if it neaded to authinticate user ?
The fastest way to do this is adding an exception to your verifyCsrfToken.php class
protected $except = [
'register'
];
Then you can post to your register model, and afterwards accessing this account with oauth/token.
If i understand your question correctly, you want to register new user and get token after registration from /oauth/token. For this you can use a proxy. I have used something similar and i followed the following steps. This works for both Login and Register
Register the user and send a HTTP request to /oauth/token endpoint from your register method
public function register(RegisterRequest $request)
{
$user = User::create($request->all());
$response = $this->authenticationProxy->attemptLogin($request->email, $request->password);
return response()->json(compact('response', 'user'), 201);
}
Then in your proxy class, call the /oauth/token
public function attemptLogin($email, $password)
{
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => env('CLIENT_ID'),
'client_secret' => env('CLIENT_SECRET'),
'username' => $email,
'password' => $password,
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
Hope this helps. You can use similar approach for login as well.

Categories