You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As William Durand was recently explaining in his SOS, he "didn't see any other interesting blog post about REST with Symfony recently unfortunately". After spending some long hours to implement an API strongly secured with oAuth, I thought it was time for me to purpose my simple explanation of how to do it.
Ok, you know the bundles
You might have already seen some good explanation of how to easily create a REST API with Symfony2.
There are famous really good bundles a.k.a. :
This Gist was made at my previous job working on a private repo, and I'm finally reusing this Gist for an open source project: the goal is to provide an API to get the church next to you. And there is also a React Native app in preparation.
So, here you are for the example. At the time I'm writing the oAuth2 implementation is still in the pull request, but will soon be merged. You'll have a working example to copy and test (I'll just have to improve the project Readme). And I'll also add the front views to create an account and ask for an API key.
and one front who consume the API (HWIOAuthBundle, no database), that one day will be replace by a JS implementation.
As our users will try to connect to our front, we want a login process à la Facebook, which you will see, is the oAuth grant_typeauthorization_code process.
The front is an oauth_client who try to connect to the back.
This oauth_client is created with a command line on the back. You then retrieve an id and a secret.
Warning If you look into the database to get the id, it's the concatenation of the oauth_client.id and oauth_client.random_id, separated with an underscore. Something looking like 1_kj2gjhlice8wkoxwggpok80hk0wcewkwfkk4c4wocawwgc0ko.
You need to learn a bit of oAuth2
You need to understand that there are different "ways" to "connect" with oAuth2 and retrieve an access_token that you will use to hit your API. They are well explained in this Tankist blog post (read them all, they are just great).
Whatever the way you use to retrieve the access_token, you want to get something like this :
These ways are defined by a grant_type that you set to an oauth_client (multiple grant_type is possible) (it might be specific to FOSOAuthServerBundle, but I presume you will not use something else) :
grant_type=authorization_code
The "usual" process you have with Facebook : login, authorize app, redirection. So the user want to connect to your front. Simplified, here is what's happening :
The front try to get the login form from the back, with its oauth_clientid.
The user put its credentials in the form, and if it's valid, can allow the "app" (which is the oauth_client, i.e. the front) to access the back.
The user is then redirected to the front, with a nice cookie (access_token) that allow the front to request the back API.
No example here, we will come back on that process later.
grant_type=password
You still want an access_token but you get it in one request, by sending everything you have : oauth_clientid and secret, and user credentials.
The process is of course simpler, but your front is storing the oauth_clientsecret. It might be ok because our front is in PHP, but if it's one day in Javascript, it might not be good. Also the process is not as cool as the real "Facebook/Google/GitHub" one :)
grant_type=client_credentials
Simplest request, no user credential, you only send oauth_clientid and secret :
The authorization code is obtained by using an authorization server as an intermediary between the client and resource owner. Instead of requesting authorization directly from the resource owner, the client directs the resource owner to an authorization server, which in turn directs the resource owner back to the client with the authorization code.
Before directing the resource owner back to the client with the authorization code, the authorization server authenticates the resource owner and obtains authorization. Because the resource owner only authenticates with the authorization server, the resource owner's credentials are never shared with the client.
The authorization code provides a few important security benefits, such as the ability to authenticate the client, as well as the transmission of the access token directly to the client without passing it through the resource owner's user-agent and potentially exposing it to others, including the resource owner.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ClientCreateCommand extends Command
{
protected function configure()
{
$this
->setName('vp:oauth-server:client-create')
->setDescription('Create a new client')
->addArgument('name', InputArgument::REQUIRED, 'Sets the client name', null)
->addOption('redirect-uri', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets redirect uri for client. Use this option multiple times to set multiple redirect URIs.', null)
->addOption('grant-type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets allowed grant type for client. Use this option multiple times to set multiple grant types.', null)
;
}
protected function execute(InputInterface $input, OutputInterface $output)