Disclaimer: Sorry for my english, not my mother tongue.. but i try my best.
Vacation after I managed to recover from Wacken 2017, the rest of the time is once again put into some fun with PHP and Laravel.
For a small project where a user administration is necessary, I was recently recommended by a colleague the service auth0.
What is auth0? It takes you all the effort to include various authentication providers such as Facebook, Google, Github, and so on. In the free version somewhat limited, but for a beginning more than sufficient (7000 User, 2 Provider).
Well now it was time to connect my Laravel application to auth0. The documentation is quite good (also related to the integration in Laravel) but when i tried to save the users into my own databases, the examples did not work. So if you have to accomplish the same task, or if i have to do it again.. here comes a small tutorial.
As a starting point, let’s assume:
- Laravel 5.4 application works, and the migrations for the users (are already there) were executed
- Auth0 account is set up
For the most times we will follow their documentation, with some small changes.
Integrate Auth0 in Laravel 5.4
In your project directory, we install us first the right package for Auth0
composer require auth0/login:"~5.0"
Now change your: /config/app.php
<?php
'providers' => array(
Auth0\Login\LoginServiceProvider::class,
);
'aliases'array(
'Auth0' => Auth0\Login\Facade\Auth0::class
);
Now we differ from the documentation, since we want to save our users in our databases. For this we build a UserRepository: /app/Repository/UserRepository.php with the following content:
<?php
namespace App\Repository;
use Auth0\Login\Contract\Auth0UserRepository as Auth0UserRepository;
use App\User as User;
class UserRepository implements Auth0UserRepository {
public function getUserByDecodedJWT($jwt)
{
$jwt->user_id = $jwt->sub;
return $this->upsertUser($jwt);
}
public function getUserByUserInfo($userInfo)
{
return $this->upsertUser((object) $userInfo['profile']);
}
/**
* Check if user is in database, if not create.
*
* @return User
*/
protected function upsertUser($profile) {
$user = User::where("auth0id", $profile->user_id)->first();
// create user if not in database
if ($user === null) {
$user = new User();
$user->email = $profile->email;
$user->auth0id = $profile->user_id;
$user->name = $profile->name;
// random password, we dont need it
$user->password = md5(time());
$user->save();
}
return $user;
}
public function getUserByIdentifier($identifier)
{
//Get the user info of the user logged in (probably in session)
$user = \App::make('auth0')->getUser();
if ($user === null) return null;
// build the user
$user = $this->getUserByUserInfo($user);
// it is not the same user as logged in, it is not valid
if ($user && $user->id == $identifier) {
return $user;
}
}
}
We do not set a password, the login is managed via auth0. What you still have to do is to insert the column auth0id in the user table, which of course, Laravel does not know before. The ID is used for the assignment.
The repository will now be registered in our AppServiceProvider: /app/Providers/AppServiceProvider.php
<?php
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(
Auth0UserRepositoryContract::class,
UserRepository::class // das unser Repository - in der Doku wird Auth0Repo.. genutzt
);
}
Now it goes to the configuration. For this, we create the necessary configuration files, and also set the necessary routes for the service.
php artisan vendor:publish
File: /routes/web.php
Route::get('/login', ['as' => 'login', 'uses' => 'IndexController@login']);
Route::get('/logout', ['as' => 'logout', 'uses' => 'IndexController@logout']);
Route::get('/callback', '\Auth0\Login\Auth0Controller@callback');
The functions in the IndexController are as follows:
<?php
public function index()
{
$isLoggedIn = \Auth::check();
return view('index')
->with('isLoggedIn', $isLoggedIn)
->with('user', \Auth::user());
}
public function login()
{
return \App::make('auth0')->login();
}
public function logout()
{
\Auth::logout();
return \Redirect::intended('/');
}
So it is already clear, how you later access the user data: \Auth::user(); Now we need to include auth0 as userprovider: /app/config/auth.php
'providers' => [
'users' => [
'driver' => 'auth0',
],
Settings for the application
To get the necessary parameters for our configuration, we visit the website of Auth0. You have to create a basic web application there, and set the following URLs.
-Callback: http://dein-server.de/callback
-Logout: http://dein-server.de/logout
The whole should also work with “localhost if you do not have a domain yet.
For the configuration of the applications we still need:
-Domain
-ClientID
-ClientSecret
In your /app/config/laravel-auth0.php you now either set directly the values or use your “.env file.
Testing auth0
If you now call http://dein-server.de/login, you should seea login and then in your user object the corresponding data as well as an entry in the Users database table.
What is missing in the documentation: How do I actually protect a route? Simply add the Auth-Middleware to your route.
# monitor (protected)
Route::get('/monitor/id/{id?}/{title?}', 'MonitorController@show')
->middleware('auth')
->name('monitor.show');
Route::get('/monitor/create', 'MonitorController@create')
->middleware('auth')
->name('monitor.create');
Thats it! — if you prefer a german version of this visit my GeekPub
Top comments (3)
It's implemented in the UserRepository:
same question, how you implemented recieving userinfo ?
in docs we see:
$user->email = $profile->email; // you should ask for the email scope
$user->auth0id = $profile->user_id;
$user->name = $profile->name; // you should ask for the name scope
auth0.com/docs/quickstart/backend/...
the problem is the fact that the profile array being return is always empty