How to add custom data in Laravel Passport token? - php

I am using Laravel Passport to Auth user in my Laravel API. I would like to know if it is possible to add custom data to the token generated by Passport:
// /login endpoint
Auth::attempt($credentials);
$user = $request->user();
$token = $user->createToken('ACCESS_TOKEN')->accessToken;
return response()->json(['token' => $token]);
// /me endpoint
$user = $request()->user();
return response()->json(['user_data' => $user]);
This is how I'm actually using it, however, I'm just able to retrieve User Model information. I would like to add custom information to the JWT token and be able to retrieve that information in all endpoints, like /me, something like that:
// /login
... login logic
$token->customKey = 'custom value';
$token->foo = 'bar';
// /me
$user = $request->user();
$token = $user->token(); // returns the token
$customKey = $token->customKey; // this don't work
$foo = $token->foo; // this don't work
Is there any way to achieve this?
I'm using Laravel 8.0 and Laravel Passport 10.0.

Related

Laravel makes API get data from database using authurization token

I am trying to make an API that will fetch a paticual users all data when token is passed in headers as authorization token.
I am new to Laravel and back-end I have generated token using Laravel passport.
api.php
Route::get('/{user}', [userData::class, 'get_all']);
userData.php
what I have tried is passing the id but I don't want that
public function get_all(User $user)
{
dd($user);
$user = User::where('id', $user)->first();
return response()->json([
'user' => $user,
]);
}
}

Google one tap login with laravel 8

in one of my projects i want to add a google one tap login for that i followed instructions as mentioned.
The front end is working fine but there is issue with the backend.
Here is my code.
I have added this script to the header.
and this code after body open
<div id="g_id_onload"
data-client_id="#####################.googleusercontent.com"
data-login_uri="/login/google/oneTap"
data-_token="{{csrf_token()}}"
data-method="post"
data-ux_mode="redirect"
data-auto_prompt="true">
</div>
This is the route
Route::get('/login/google/oneTap', [App\Http\Controllers\SocialLoginController::class, 'oneTap']);
In an article regarding one, tap login author told that it requires a post method but there is clarification on how to add a post method.
This is the article.
https://www.teachnep.com/blog/how-to-add-one-tap-login-to-laravel-project#
My backend code.
public function oneTap(REQUEST $request)
{
$token = $request->credential;
$tokenParts = explode('.', $token);
$tokenHeader = base64_decode($tokenParts[0]);
$tokenPayload = base64_decode($tokenParts[1]);
$jwtHeader = json_decode($tokenHeader);
$jwtPayload = json_decode($tokenPayload);
$user = $jwtPayload;
return $user;
}
It returns null;
Any help would be appreciated.
You must define your route using the POST verb instead of GET.
For example:
Route::post('/login/google', [GoogleSignInController::class, 'login'])
->name('login.google');
Even though you can verify the "ID Token" (this is how Google refers to the credential param) by yourself, it is recommended to use the official Google API Client Library.
You can add it to your project using Composer:
composer require google/apiclient
In addition to validate the credential field, you should validate the CSRF token provided in the g_csrf_token field.
To summarize:
/**
* Validate the "ID Token" using the Google API Client Library.
* https://developers.google.com/identity/gsi/web/guides/verify-google-id-token
*/
public function login(Request $request)
{
if ($_COOKIE['g_csrf_token'] !== $request->input('g_csrf_token')) {
// Invalid CSRF token
return back();
}
$idToken = $request->input('credential');
$client = new Google_Client([
'client_id' => env('GOOGLE_CLIENT_ID')
]);
$payload = $client->verifyIdToken($idToken);
if (!$payload) {
// Invalid ID token
return back();
}
dd($payload);
}
Note that I printed the $payload at the end:
You may want to use the $payload['sub'] that represents the user id to register / authenticate this user in your application, as well as its name and picture.

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 do I integrate OAuth client authentication alongside Laravel standard authentication?

I've been Googling for quite some time now for some ideas or a guide on how to integrate OAuth (v1.0 & v2.0) alongside the standard Laravel 4 Eloquent authentication driver.
Essentially, I'd like to be able for site visitors to create an account via their existing Google, Facebook, or Twitter accounts, or via the standard email/password authentication. Certain user information such as email, first and last names, and avatar are important for me to have stored in a unified users table.
So far the projects I've looked at seem to support only OAuth and do away with the standard method. These projects include: eloquent-oauth, and oauth-4-laravel.
At this point, I might just roll my own solution, but I'm hoping some of you guys might have better advice for me!
TL;DR: I'm stuck at trying to find a simple and secure way to allow OAuth and standard Eloquent user authentication in Laravel. Halp.
I think the easiest way would be to use this service provider that you mention "artdarek/oauth-4-laravel" and then store the values as usual and log them in.
/**
* Login user with facebook
*
* #return void
*/
public function loginWithFacebook() {
// get data from input
$code = Input::get( 'code' );
// get fb service
$fb = OAuth::consumer( 'Facebook' );
// check if code is valid
// if code is provided get user data and sign in
if ( !empty( $code ) ) {
// This was a callback request from facebook, get the token
$token = $fb->requestAccessToken( $code );
// Send a request with it
$result = json_decode( $fb->request( '/me' ), true );
// store new user or login if user exists
$validator = Validator::make($result, array(
'email'=>'required|email|unique:users'
));
if ($validator->passes()) {
# Save user in DB
$user = new User;
$user->username = $result['name'];
$user->email = $result['email'];
$user->save();
}else {
$user = User::findByUsernameOrFail($result['name']);
}
Auth::login($user);
}
// if not ask for permission first
else {
// get fb authorization
$url = $fb->getAuthorizationUri();
// return to facebook login url
return Redirect::to( (string)$url );
}
}

Categories