I'm using Laravel 5.7 and Laravel/Socialite 3.1.
I want to login using a Facebook app I just configured for this project.
These are the main files I have configured for this:
/.env
...
FACEBOOK_CLIENT_ID=***
FACEBOOK_CLIENT_SECRET=***
FACEBOOK_CALLBACK_URL=http://localhost:8000/auth/facebook/callback
/config/services.php
<?php
return [
...
'facebook' => [
'client_id' => env('FACEBOOK_CLIENT_ID'),
'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
'redirect' => env('FACEBOOK_CALLBACK_URL'),
],
];
/routes/api.php
<?php
use Illuminate\Http\Request;
...
Route::get('auth/facebook', 'SocialiteController#redirectToProviderFacebook');
Route::get('auth/facebook/callback', 'SocialiteController#handleProviderCallbackFacebook');
/app/Http/Controllers/SocialiteController.php
<?php
namespace App\Http\Controllers;
use Socialite;
class SocialiteController extends Controller
{
public function redirectToProviderFacebook()
{
return Socialite::driver('facebook')->redirect();
}
public function handleProviderCallbackFacebook()
{
$user = Socialite::driver('facebook')->user();
print_r($user->token);
}
}
My problem is that for some reason I get the error:
RuntimeException
Session store not set on request.
as you can see on the following image:
I don't want to use sessions on this project at all. I just want to get the token from Facebook on the callback inside: function handleProviderCallbackFacebook().
Any idea on how to solve this issue?
Thanks!
From the Socialite documentation
The stateless method may be used to disable session state verification. This is useful when adding social authentication to an API:
return Socialite::driver('google')->stateless()->user();
Related
I'm trying to use the laravel passport to authenticate users. I followed every step in laravel passport documentation. But it shows error when I access a route that is protected by 'auth:api' middleware. I've searched over the internet but any of the answers are not working so far. Please see the code, and what I've tried so far below.
Tech used
Laravel 6
Laravel Passport
Vue 2
Axios
Tried so far:
Changed Passport::routes(); to Passport::routes(null, ['prefix' => 'api/oauth', 'middleware' => ['auth:api', 'web', 'auth']]); in AuthServiceProvider. Also tried Passport::routes(null, ['prefix' => 'api/oauth');
Tried to run php artisan cache:clear
routes/api.php
Route::middleware('auth:api')->group(function() {
Route::get('user', function() {
return request()->user();
});
Route::get('posts', 'PostController#index')->name('posts');
Route::post('posts/store', 'PostController#store')->name('posts.store');
Route::get('posts/{id}/show')->name('posts.show');
Route::get('users/{id}/show')->name('users.show');
});
Axios
mounted() {
axios.get('/api/posts')
.then(res => this.posts = res.data).catch(error => console.log('Unable to fetch posts.'))
}
Error
Headers:
Please let me know if you need some details that is not indicated on my post yet.
Setup
Run composer require laravel/passport:9 for the installation.
Run php artisan migrate for the tables.
Run php artisan passport:install to generate the encryption keys.
Added Laravel\Passport\HasApiTokens trait in User model.
Added Passport::routes(); in AuthServiceProvider.
Changed guard's api driver to passport in config/auth.php.
Full source code:
Click this link
I think you should review your code with the following steps.
Step 1: User model has to use HasApiTokens
...
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
}
Step 2: Passport::routes method within the boot method of your AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
...
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
}
Step 3: In your config/auth.php configuration file, you should set the driver option of the api authentication guard to passport
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Step 4 (Optional):
If you want to consume your API from your JavaScript application, you need to manually send an access token to the application and pass it with each request to your application. However, Passport includes a middleware that can handle this for you. All you need to do is add the CreateFreshApiToken middleware to your web middleware group in your app/Http/Kernel.php file:
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
! You should ensure that the CreateFreshApiToken middleware is the last middleware listed in your middleware stack.
Edit (2021/10/17):
You should try to add the auth middleware to $middlewareGroups of your Kernel.php
protected $middlewareGroups = [
...
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'auth:api', //Need to add
],
];
Edit (2021/10/25):
I downloaded your code and debug it. When you debug it, you will get the following result:
Header JWT is not valid for JSON structure. There seems to be an incompatibility between the Laravel Passport library and your system. You should check your system version (PHP, Laravel, etc). I will continue to investigate. If you have any new information, please let me know
Edit (2021/11/02):
Update your laravel/framework dependency to ^6.0 in your composer.json file. If installed, update your laravel/passport dependency to ^9.3.2 in your composer.json file.
https://laravel.com/docs/6.x/upgrade#updating-dependencies
According to Laravel 6.x documentation, the version of Laravel Passport is from 9.3.2. Please try this version.
If you are using Api/oauth prefix AND add the auth:api middleware than you need to authenticate via Bearer tokens.
So it may be you have csrf token related issue so try below to disable it.
Passport::ignoreCsrfToken(true);
You should add token bearer into your ajax requests. You can get it after successful login.
// laravel
use Illuminate\Support\Facades\Auth;
use App\Models\User;
public function login()
{
$credentials = request(['email', 'password']);
$user = User::where('email', $credentials['email'])->first();
if (!$user || !$token = Auth::attempt($credentials)) {
return response()->json(['success'=> false, 'error' => 'неверный логин или пароль', 'cr' => $credentials], 422);
}
return $this->respondWithToken($token);
}
// vue login
async function login(email, password) {
try {
const response = await axios.post('/auth/login', {email, password});
const token = response.data.token;
// some func to store token, I am using vuex mutations for this
storeToken(token);
}
catch(error) {
console.error(error);
}
};
// vue regular function
async function changePassword(newPassword) {
// get token from global storage, with vuex it will be like store.state.auth.token
const token = getToken();
await axios.post('/user/changePassword', {newPassword}, headers: { Authorization: `Bearer ${token}`});
}
You've forgotten to run php artisan passport:keys ...so there may be no RSA key-pair available, which is crucial. Clients usually can be added with: php artisan passport:client. And generally speaking, there is no default recipe for debugging Laravel middleware ...there only is xdebug.
I'm using Laravel 8 to develop my project and I would like to use Google authentication system for my users to login.
So I downloaded package via composer require laravel/socialite command and added my information on .env:
GOOGLE_CLIENT_ID=example
GOOGLE_SECRET_KEY=example
GOOGLE_CALLBACK_URL=http://localhost:8000/auth/google/callback
And then I defined them on config/services.php:
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_SECRET_KEY'),
'redirect' => 'GOOGLE_CALLBACK_URL',
],
After that I created a controller on my auth/ directory which is called GoogleAuthController and goes like this:
use Laravel\Socialite\Facades\Socialite;
class GoogleAuthController extends Controller
{
public function redirect()
{
return Socialite::driver('google')->redirect();
}
}
And finally at my login blade:
Login with Google
But the problem with this is that it, whenever I test this, it says:
Error 400: invalid_request
Invalid parameter value for redirect_uri: Missing scheme: GOOGLE_CALLBACK_URL
So why am I receiving this error ? How to fix it ?
I really appreciate any idea or suggestion from you guys...
Thanks in advance.
Also if you want to take a look at my routes, here it is:
Route::get('/auth/google', [App\Http\Controllers\Auth\GoogleAuthController::class, 'redirect'])->name('auth.google');
Your config is wrong:
'redirect' => 'GOOGLE_CALLBACK_URL',
Should be
'redirect' => env('GOOGLE_CALLBACK_URL'),
And of course this redirect should point to Google, not your localhost.
"laravel/framework": "5.7.*"
"tymon/jwt-auth": "dev-develop"
I am trying to create a JWT token with added custom claims, without auth (which means that I am not looking to create a token from credentials.) This is for the purpose of creating tokens that do not require logins, such as forgot/reset-password, etc.
using Tymon/JWTAuth (https://github.com/tymondesigns/jwt-auth)
Since there was an issue with Latest Laravel, it was recommended to load the latest dev ( 1.0.x-dev ).
I have tried the following code without avail:
class OTL extends Model implements JWTSubject
use JWTAuth;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Tymon\JWTAuth\Facades\JWTFactory;
public static function getJwtToken($customerId, $action, $token){
$customClaims = ['action' => $action, 'customer-id' => $customerId, 'token' => $token];
$factory = JWTFactory::customClaims($customClaims);
$payload = $factory->make();
$token = JWTAuth::encode($payload);
return $token;
I am receiving an error: JWT payload does not contain the required claims.
I am expecting to receive the token that holds the payload above.
I solved this problem by commenting out 'exp' in required_claims in the config/jwt.php:
.....
'required_claims' => [
'iss',
'iat',
//'exp',
.....
],
I just encountered the same error and was able to solve it by updating the list of required claims in the generated configuration file config/jwt.php.
...
'required_claims' => [
'exp',
'sub',
...
],
...
Also make sure you have run php artisan jwt:secret or otherwise provided a secret key for signing.
I try to use the package Laravel\Socialite in my system in Lumen (5.1)
I added this in the config\services.php file :
<?php
//Socialite
'facebook' => [
'client_id' => '##################',
'client_secret' => '##################',
'redirect' => 'http://local.dev/admin/facebook/callback',
],
In bootstrap\app.php file :
class_alias(Laravel\Socialite\Facades\Socialite::class, 'Socialite');
$app->register(Laravel\Socialite\SocialiteServiceProvider::class);
Then I created a controller for the facebook authentication :
<?php
namespace App\Http\Controllers\Facebook;
use App\Http\Controllers\Controller;
use Laravel\Socialite\Contracts\Factory as Socialite;
class FacebookController extends Controller
{
public function redirectToProviderAdmin()
{
return Socialite::driver('facebook')->scopes(['manage_pages', 'publish_actions'])->redirect();
}
public function handleProviderCallbackAdmin()
{
$user = Socialite::driver('facebook')->user();
}
}
And in the routes.php :
$app->get('/admin/facebook/login', 'App\Http\Controllers\Facebook\FacebookController#redirectToProviderAdmin');
$app->get('/admin/facebook/callback', 'App\Http\Controllers\Facebook\FacebookController#handleProviderCallbackAdmin');
I just followed the documentation, changing according to my needs. When I go to page http://local.dev/admin/facebook/login, I get the following error :
Non-static method Laravel\Socialite\Contracts\Factory::driver() cannot be called statically, assuming $this from incompatible context
Indeed, according to the code, driver function must be instanciate.
EDIT : And if I try to instanciate this class, I get the following error :
Cannot instantiate interface Laravel\Socialite\Contracts\Factory
How do you make this module to work?
here's how that works in my case
in services.php file
'facebook' => [
'client_id' => '***************',
'client_secret' => '***************',
'redirect' => ""
],
i left redirect empty cause my site is multilingual (so, it fills in a bit later with sessions). if you use only one language, put there your callback absolute path. for example
"http://example.com:8000/my-callback/";
also check your config/app.php. in providers array
Laravel\Socialite\SocialiteServiceProvider::class,
in aliases array
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
my routes look like this
Route::get('facebook', 'Auth\AuthController#redirectToProvider');
Route::get('callback', 'Auth\AuthController#handleProviderCallback');
here's auth controllers methods. put in top
use Socialite;
//იობანი როტ
public function redirectToProvider(Request $request)
{
return Socialite::with('facebook')->redirect();
}
public function handleProviderCallback(Request $request)
{
//here you hadle input user data
$user = Socialite::with('facebook')->user();
}
my facebook app
giga.com:8000 is my localhost (so its the same localhost:8000)
as you can see in Valid OAuth redirect URI, you should put there your callback. in my case i use three urls cause i have three languages. in your case it should be just
http://your-domain-name.com:8000/callback
if you work on localhost, you should name your domain in config/services.php
mine look like this
'domain' => "your-domain.com",
after everything run these commands
php artisan cache:clear
php artisan view:clear
composer dump-autoload
restart your server, clear your browser cookies. hope it helps
So I've realized that Laravel 5.1 can't use sessions to store the CSRF token required by the Dropbox SDK when authenticating a user via OAuth2. To get around this, I've followed this great post to use this provider and Laravel Socialite to make the OAuth2 calls for me but, even after following that doc to the letter, I'm still getting the following error:
ErrorException in SocialiteManager.php line 91: Undefined index: client_id
I can't find where client_id would even be an index in the flow so I'm thoroughly confused on this one. Any help would be great appreciated.
Here are the methods that are being fired to evoke the Socialite/Dropbox service provider:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
// other Classes
use App\User;
use Hash;
use Input;
use Auth;
use DB;
use Socialize;
class UserController extends Controller
{
public function showDropbox()
{
return Socialize::driver('dropbox')->redirect();
}
}
It was something very simple and a complete oversight on my part... I had the wrong indices in the config/services.php file that the tutorial required.
I had...
'dropbox' => [
'redirect' => env('DROPBOX_REDIRECT_URI'),
'key' => env('DROPBOX_KEY'),
'secret' => env('DROPBOX_SECRET'),
],
...when I should've had:
'dropbox' => [
'redirect' => env('DROPBOX_REDIRECT_URI'),
'client_id' => env('DROPBOX_KEY'),
'client_secret' => env('DROPBOX_SECRET'),
],
Hope that helps someone!