I want to use an external OAuth2 server under my control to authenticate users for my Laravel 5.2 application. As client library I want to use the package league/oauth2-client
As far as I understood need to implement a custom user provider but I'm uncertain about the big picture of all required steps.
The idea is that the user provides the credentials to my Laravel application, with other words the client credentials
method is used. Then the bearer-token and the refresh-token is stored on the client side. Every time a client makes a request, the token must be validated by the OAuth server. The OAuth server also provides some basic user information like email and name. So in my application there must be some kind of link between the local user and the OAuth user. This is accomplished with a simple table like
+-------------------+
| Users |
+-------------------+
| id | int(10) |
| oauthId | int(10) |
+---------+---------+
First I followed this guide at laravel.io to create a basic provider skeleton. But at this point I have several questions:
Is the method retrieveById
supposed to return any user from the OAuth service or only the users which is the issuer of the request allowed to see?
My OAuth server already has permission checking for each user. If retrieveById
is supposed to return any existing user, is my permission check on the OAuth server worthless? This would be a flaw in my architecture.
Some methods must return an implementation of the \Illuminate\Contracts\Auth\Authenticatable
interface. Where do I have to implement this? Is this supposed to be the representation of the user which is trying to authenticate? If this should represent a user in my model I have the problem that I don't know the return value for getAuthPassword
since this information is on my OAuth server. How can I solve this?
As you can see I have problems to understand how things working together in the whole authentication process. Your help is very appreciated.
The idea is that the user provides the credentials to my Laravel application, with other words the client credentials method is used.
You should forward the user to your oauth server using authorization code grant
So
retrieveById
callI used a custom laravel/socialite provider to help with client routing and stuff. The league/oauth2-client
should be pretty similar.
The first login redirect looks like
class LoginController extends Controller
{
public function login(Request $request)
{
return Socialite::driver('custom-oauth')
->scopes(['read-permissions read-name read-email etc'])
->redirect();
}
}
I changed the User model getAuthIdentifier()
to be the access_token
returned from the authorization code grant. For example
class User implements Authenticatable
{
public function getAuthIdentifier()
{
return $this->token;
}
}
My login callback looks like this sort of.
class LoginController extends Controller
{
public function callback(Request $request)
{
/** @var \App\User $user */
$user = Socialite::driver('custom-oauth')->user();
Auth::login($user, true);
return redirect()->home();
}
}
Laravel's SessionGuard
will store that access_token
and your custom user provider should retrieveById
back to the oauth server using the access_token
to get the user information
And then my custom user provider's retrieveById
looks like. Which basically hits the oauth server and requests for the current users information. $identifier
= access_token
class CustomUserProvider implements UserProvider
{
public function retrieveById($identifier)
{
try {
return Socialite::driver('custom-oauth')->userFromToken($identifier);
} catch (AuthenticationException $e) {
return null;
}
}
}
I hope that helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With