Last active
February 22, 2024 14:51
-
-
Save mirkorap/cd9f2933304eb868e489e7b6b573074c to your computer and use it in GitHub Desktop.
Revisions
-
mirkorap revised this gist
Nov 15, 2018 . 1 changed file with 7 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -75,7 +75,7 @@ In the `config/packages/jms_serializer.yaml` file insert these configuration opt Documentation: [https://jmsyst.com/bundles/JMSSerializerBundle](https://jmsyst.com/bundles/JMSSerializerBundle) ### NelmioApiDocBundle ### NelmioApiDocBundle is a Symfony's bundle that allows us to generate documentation for our APIs. In the `config/packages/nelmio_api_doc.yaml` file insert these configuration options: @@ -105,7 +105,7 @@ In the `config/routes.yaml` file insert this route option: Documentation: [https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html](https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html) ### FOSUserBundle ### FOSUserBundle allows us to manage users (store and load users, authenticate users, manage roles etc.) In the `config/packages/fos_user.yaml` file insert these configuration options (if the file doesn't exist, create it!): @@ -160,7 +160,7 @@ Now let's create our entity User class: Documentation: [https://symfony.com/doc/current/bundles/FOSUserBundle/index.html](https://symfony.com/doc/current/bundles/FOSUserBundle/index.html) ### FOSOAuthServerBundle ### FOSOAuthServerBundle is a Symfony's bundle that allows us to create our oauth2 server app. In this gist I will explain you how to use it with the main oauth2 code flows (Authorization code, Implicit, Password credentials). Let's take a look to the configuration options: In the `config/packages/fos_oauth_server.yaml` file insert these configuration options (if the file doesn't exist, create it!): @@ -499,7 +499,7 @@ Create an ApiController that will serve our resources. In this example we will c * @param Request $request * @return View */ public function getAllUsersAction(Request $request) { $offset = $request->query->get('offset', 0); $limit = $request->query->get('limit', 10); @@ -512,7 +512,7 @@ Create an ApiController that will serve our resources. In this example we will c } } In the `src/Repository/UserRepository` let's add the `getAllUsers` function: <?php @@ -719,7 +719,7 @@ Then to get a new `access_token` you need to call the route: `/oauth/v2/token` w Content-Type: application/json ## Implicit ## This flow is principally used in SPA. A difference from the previous flow is that we will receive an `access_token` immediately, so we don't need to exchange an authorization code for an `access_token`. You may think "Why I should use the Authorization code flow if the Implicit one is more simple?". The answer is easy, you MUST use the authorization code flow if you need to call APIs even when the user is offline. In fact with the Implicit flow you will not receive a `refresh_token` (for security reason), so when the `access_token` expires the user must authorize access again. For this reason this flow is more suitable in the SPA. Let's see how it works: Again we need to create a client, so open your terminal and run: @@ -795,7 +795,7 @@ With these data we can call the route to get the `access_token`, but this time w Connection: close Content-Type: application/json The username and password that you see above come from the user created by FOSUserBundle's command `php bin/console fos:user:create`. Now we can call our API http GET localhost:8000/api/users \ "Authorization:Bearer MmQ5MzRlOTRhNWUzMzY0ZGU1ZjMzMjkwY2I0YjlhN2NlOTBhZjg5NGJjMGM5Yzk2ZGFiYWI5YTBkYjBiMWIyNw" -
mirkorap revised this gist
Nov 15, 2018 . 1 changed file with 9 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -644,14 +644,14 @@ Then we need to create a `SecurityController` with two routes: `/oauth/v2/auth_l } } To complete the `SecurityController` we need to have a login page where the user will be redirect if he isn't already logged in. For simplicity let's copy the `FOSUserBundle` template files. You can find them inside the directory `vendor/friendsofsymfony/user-bundle/Resources/views`. From that directory you should copy the directory `Security` and the file `layout.html.twig` and put them inside the directory `templates/bundles/FOSUserBundle`. More information about the overriding of templates you can find here: [Symfony's bunde override](https://symfony.com/doc/current/bundles/override.html "Symfony's bunde override"). <br/> Now open the file `templates/bundles/FOSUserBundle/Security/login_content.html.twig` and in the action of form replace the path `fos_user_security_check` with `auth_login_check`. To verify that all works properly, we should call this route: `http://localhost:8000/oauth/v2/auth?client_id=1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck&redirect_uri=http://localhost:8000/redirect-uri-example&response_type=code` The `client_id` query parameter should be replaced by the `client_id` created previously. The response should be a page with two buttons: "allow" and "deny". After clicking in the "allow" button you will redirect to the `redirect_uri`. In the url you can notice a `code` query parameter, that is our authorization code! Now we need to exchange that code with an `access_token`. So let's create a POST request to `/oauth/v2/token`: http POST http://localhost:8000/oauth/v2/token \ grant_type=authorization_code \ @@ -674,7 +674,7 @@ The response should looks like this: "refresh_token": "NDFiNjY3MWU3YmZhMDkxNjI5NjBjZDhhNmYzNmJkYjI1NTIzMGJiZTQzYTA0NzlkYjU2OTgzYmM5MzZlODg2NQ" } Now we can finally call our APIs! Create a request to `localhost:8000/api/users` and pass in the header the `access_token`: http GET localhost:8000/api/users \ "Authorization:Bearer ZTFiZWIwMzI4ZTg4MmYzNTExNjkxMzYwODBlMzQ3NTgxNzM1ODMxYTQzNGZkZDI0ZjQ4MmRkN2ZjMDRhMWU2YQ" @@ -719,7 +719,7 @@ Then to get a new `access_token` you need to call the route: `/oauth/v2/token` w Content-Type: application/json ## Implicit ## This flow is principally used in SPA. A difference from the previous flow is that we will receive an access_token immediately, so we don't need to exchange an authorization code for an access_token. You may think "Why I should use the Authorization code flow if the Implicit one is more simple?". The answer is easy, you MUST use the authorization code flow if you need to call APIs even when the user is offline. In fact with the Implicit flow you will not receive a refresh_token (for security reason), so when the access_token expires the user must authorize access again. For this reason this flow is more suitable in the SPA. Let's see how it works: Again we need to create a client, so open your terminal and run: @@ -733,12 +733,12 @@ In my case the client created by the bundle has these data: | 2 | 2shspbzhca2ogw44kckw00s4s800g0s484004ccokcw8gogwks | 3fcdpac3iw6cw8k8gs48kwc8ows4s4wkcg8gwgsgck84g48k0s | +------------+---------------------------------------------------------+------------------------------------------------------+ client_id: `2_2shspbzhca2ogw44kckw00s4s800g0s484004ccokcw8gogwks` (id + random_id) <br/> secret: `3fcdpac3iw6cw8k8gs48kwc8ows4s4wkcg8gwgsgck84g48k0s` With these data we can call the route `http://localhost:8000/oauth/v2/auth?client_id=2_2shspbzhca2ogw44kckw00s4s800g0s484004ccokcw8gogwks&redirect_uri=http://localhost:8000/redirect-uri-example&response_type=token` The `client_id` query parameter should be replaced by the `client_id` created previously. The response should be a page with two buttons: "allow" and "deny". After clicking in the "allow" button you will redirect to the `redirect_uri`. In the url you can notice an hash with the `access_token`. Now we can call our API to get all users (remember to pass a Bearer header with the `access_token`): http GET localhost:8000/api/users \ "Authorization:Bearer NDYxMmUwZGI5OTQ4Y2UzNDQ5M2JhY2YwYmU3YmM2NDlkMDUyNTk4MjE2N2ZhNDU2OWQ2MTc4NjM1MmYxMDBmOQ" @@ -779,7 +779,7 @@ In my case the client created by the bundle has these data: | 3 | 492ohmxbo3k0gggwg08wso4cs0k4sswcwg8wo8so0cgo4cwo0s | 64jack8z62888k4sgcgssow080wcgsk04408wogkc4owgkgokc | +------------+---------------------------------------------------------+------------------------------------------------------+ client_id: `3_492ohmxbo3k0gggwg08wso4cs0k4sswcwg8wo8so0cgo4cwo0s` (id + random_id) <br/> secret: `64jack8z62888k4sgcgssow080wcgsk04408wogkc4owgkgokc` With these data we can call the route to get the `access_token`, but this time we should send also username and password! @@ -795,7 +795,7 @@ With these data we can call the route to get the `access_token`, but this time w Connection: close Content-Type: application/json The username and password that you see above come from the user created by FOSUserBundle's command `php bin/console fos:user:create`. Now we can call our APIs http GET localhost:8000/api/users \ "Authorization:Bearer MmQ5MzRlOTRhNWUzMzY0ZGU1ZjMzMjkwY2I0YjlhN2NlOTBhZjg5NGJjMGM5Yzk2ZGFiYWI5YTBkYjBiMWIyNw" -
mirkorap revised this gist
Nov 14, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -646,7 +646,7 @@ Then we need to create a `SecurityController` with two routes: `/oauth/v2/auth_l To complete the `SecurityController` we need to have a login page where the user will be redirect if he isn't already logged in. For simplicity let's copy the `FOSUserBundle` login template files. You can find them inside the directory `vendor/friendsofsymfony/user-bundle/Resources/views`. From that directory you should copy the directory `Security` and the file `layout.html.twig` and put them inside the directory `templates/bundles/FOSUserBundle`. More information about the overriding of templates you can find here: [Symfony's bunde override](https://symfony.com/doc/current/bundles/override.html "Symfony's bunde override"). <br/> Now open the file `templates/bundles/FOSUserBundle/Security/login_content.html.twig` and in the action of form replace the path `fos_user_security_check` with `auth_login_check`. To verify that all works properly, we should call this route: `http://localhost:8000/oauth/v2/auth?client_id=1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck&redirect_uri=http://localhost:8000/redirect-uri-example&response_type=code` -
mirkorap revised this gist
Nov 14, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -646,7 +646,7 @@ Then we need to create a `SecurityController` with two routes: `/oauth/v2/auth_l To complete the `SecurityController` we need to have a login page where the user will be redirect if he isn't already logged in. For simplicity let's copy the `FOSUserBundle` login template files. You can find them inside the directory `vendor/friendsofsymfony/user-bundle/Resources/views`. From that directory you should copy the directory `Security` and the file `layout.html.twig` and put them inside the directory `templates/bundles/FOSUserBundle`. More information about the overriding of templates you can find here: [https://symfony.com/doc/current/bundles/override.html](https://symfony.com/doc/current/bundles/override.html "Symfony's bunde override"). <br/> Now open the file `templates/bundles/FOSUserBundle/Security/login_content.html.twig` and in the action of form replace the path `fos_user_security_check` with `auth_login_check`. To verify that all works properly, we should call this route: `http://localhost:8000/oauth/v2/auth?client_id=1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck&redirect_uri=http://localhost:8000/redirect-uri-example&response_type=code` -
mirkorap revised this gist
Nov 14, 2018 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -644,7 +644,9 @@ Then we need to create a `SecurityController` with two routes: `/oauth/v2/auth_l } } To complete the `SecurityController` we need to have a login page where the user will be redirect if he isn't already logged in. For simplicity let's copy the `FOSUserBundle` login template files. You can find them inside the directory `vendor/friendsofsymfony/user-bundle/Resources/views`. From that directory you should copy the directory `Security` and the file `layout.html.twig` and put them inside the directory `templates/bundles/FOSUserBundle`. More information about the overriding of templates you can find here: [https://symfony.com/doc/current/bundles/override.html](https://symfony.com/doc/current/bundles/override.html). <br/> Now open the file `templates/bundles/FOSUserBundle/Security/login_content.html.twig` and in the action of form replace the path `fos_user_security_check` with `auth_login_check`. To verify that all works properly, we should call this route: `http://localhost:8000/oauth/v2/auth?client_id=1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck&redirect_uri=http://localhost:8000/redirect-uri-example&response_type=code` -
mirkorap revised this gist
Nov 14, 2018 . 1 changed file with 34 additions and 31 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -9,8 +9,8 @@ 3. [NelmioApiDocBundle](#nelmioapidocbundle "NelmioApiDocBundle") 4. [FOSUserBundle](#fosuserbundle "FOSUserBundle") 5. [FOSOAuthServerBundle](#fosoauthserverbundle "FOSOAuthServerBundle") 4. [Security](#security "Security") 5. [Make migrations](#make-migrations "Make migrations") 6. [Create an ApiController](#create-an-apicontroller "Create an ApiController") 7. [Authorization code](#authorization-code "Authorization code") 1. [Refresh token](#refresh-token "Refresh token") @@ -24,12 +24,12 @@ The flows that we implement will be: 2. Implicit 3. Password credentials I will separate the gist into two configuration parts. The first part is the common configuration that is equal for all Oauth2 code flows above. In the second part I will explain, for each flow, the basic configuration type that you need. So let's coding! ## Install bundles ## The first step is to download Symfony and the related bundles. composer create-project symfony/website-skeleton oauth2-server cd oauth2-server composer require friendsofsymfony/rest-bundle composer require jms/serializer-bundle @@ -42,7 +42,7 @@ Below I will explain for each bundle what they do and how to configure them. ## Configuration ## ### FOSRestBundle ### FOSRestBundle allow us to configure our APIs and serve resources in different format in an easy way. There are different configuration options that you can use, but in our example we will serve resources in json/xml format for all routes starting with `/api`, instead for all others we will serve simple html pages. In the `config/packages/fos_rest.yaml` file insert these configuration options: @@ -105,9 +105,9 @@ In the `config/routes.yaml` file insert this route option: Documentation: [https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html](https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html) ### FOSUserBundle ### FOSUserBundle allow us to manage users (store and load users, authenticate users, manage roles etc.) In the `config/packages/fos_user.yaml` file insert these configuration options (if the file doesn't exist, create it!): fos_user: db_driver: orm @@ -128,7 +128,7 @@ In the `config/packages/framework.yaml` file insert this line at the end of file templating: engines: twig Now let's create our entity User class: <?php @@ -160,9 +160,9 @@ Now let's to create our entity User class: Documentation: [https://symfony.com/doc/current/bundles/FOSUserBundle/index.html](https://symfony.com/doc/current/bundles/FOSUserBundle/index.html) ### FOSOAuthServerBundle ### FOSOAuthServerBundle is a Symfony's bundle that allow us to create our oauth2 server app. In this gist I will explain you how to use it with the main oauth2 code flows (Authorization code, Implicit, Password credentials). Let's take a look to the configuration options: In the `config/packages/fos_oauth_server.yaml` file insert these configuration options (if the file doesn't exist, create it!): fos_oauth_server: db_driver: orm @@ -178,7 +178,7 @@ In the `config/routes.yaml` file insert these route options: fos_oauth_server_token: resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml" # Add this route option only if you are going to use the Authorization code flow fos_oauth_server_authorize: resource: "@FOSOAuthServerBundle/Resources/config/routing/authorize.xml" @@ -364,23 +364,6 @@ Above you can see the annotation `@ORM\AttributeOverrides`. This is required to Documentation: [https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/blob/master/Resources/doc/index.md](https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/blob/master/Resources/doc/index.md) ## Security ## In the `config/packages/security.yaml` file insert these configuration options: @@ -443,8 +426,25 @@ In the `config/packages/security.yaml` file insert these configuration options: - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } ## Make migrations ## We have finally finished to configure our bundles. Now we can start to see oauth2 code flows, but first we need to create migrations! So let's open your terminal and run: php bin/console make:migration php bin/console doctrine:migration:migrate Then we need to create a user, so again open your terminal and run: php bin/console fos:user:create Please choose a username:admin Please choose an email:admin@example.com Please choose a password:admin Created user admin ## Create an ApiController ## Create an ApiController that will serve our resources. In this example we will create a simple API that returns all users. <?php @@ -460,7 +460,7 @@ Create an ApiController that will serve our resouces. In this example we will cr use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use FOS\RestBundle\Controller\FOSRestController; use Swagger\Annotations as SWG; class ApiController extends FOSRestController { @@ -566,7 +566,7 @@ In my case the client created by the bundle has these data: | 1 | 3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck | 4t1922al57ack8wckcgoc84ko4oogogcoso40kwwkc4csw4cwk | +------------+---------------------------------------------------------+------------------------------------------------------+ client_id: `1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck` (id + random_id) <br/> secret: `4t1922al57ack8wckcgoc84ko4oogogcoso40kwwkc4csw4cwk` Then we need to create a `SecurityController` with two routes: `/oauth/v2/auth_login` and `/oauth/v2/auth_login_check`. These are the routes that we have specified above in the `oauth_authorize` firewall inside the `security.yaml` file. @@ -644,6 +644,9 @@ Then we need to create a `SecurityController` with two routes: `/oauth/v2/auth_l } } To complete the `SecurityController` we need to have a login page where the user will be redirect if he isn't already logged in. For simplicity let's copy the `FOSUserBundle` login template files. You can find them inside the directory `vendor/friendsofsymfony/user-bundle/Resources/views`. From that directory you should copy the directory `Security` and the file `layout.html.twig` and put them inside the directory `templates/bundles/FOSUserBundle`. More information about the overriding of templates you can find here: [https://symfony.com/doc/current/bundles/override.html](https://symfony.com/doc/current/bundles/override.html) Now open the file `templates/bundles/FOSUserBundle/Security/login_content.html.twig` and in the action of form replace the path `fos_user_security_check` with `auth_login_check`. To verify that all works properly, we should call this route: `http://localhost:8000/oauth/v2/auth?client_id=1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck&redirect_uri=http://localhost:8000/redirect-uri-example&response_type=code` The client_id query parameter should be replaced by the client_id created previously. The response should be a page with two buttons: "allow" and "deny". After clicking in the "allow" button you will redirect to the `redirect_uri`. In the url you can notice a code query parameter, that is our authorization code! Now we need to exchange that code with an `access_token`. So let's create a request to our `/oauth/v2/token` route: -
mirkorap revised this gist
Nov 13, 2018 . No changes.There are no files selected for viewing
-
mirkorap revised this gist
Nov 13, 2018 . 1 changed file with 15 additions and 15 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,21 +1,21 @@ # How to implement a REST APIs with Symfony 4 + FOSRestBundle + FOSUserBundle + FOSOauthServerBundle using main Oauth2 code flows # ## Table of contents ## 1. [Introduction](#introduction "Introduction") 2. [Install bundles](#install-bundles "Install bundles") 3. [Configuration](#configuration "Configuration") 1. [FOSRestBundle](#fosrestbundle "FOSRestBundle") 2. [JMSSerializerBundle](#jmsserializerbundle "JMSSerializerBundle") 3. [NelmioApiDocBundle](#nelmioapidocbundle "NelmioApiDocBundle") 4. [FOSUserBundle](#fosuserbundle "FOSUserBundle") 5. [FOSOAuthServerBundle](#fosoauthserverbundle "FOSOAuthServerBundle") 4. [Make migrations](#make-migrations "Make migrations") 5. [Security](#security "Security") 6. [Create an ApiController](#create-an-apicontroller "Create an ApiController") 7. [Authorization code](#authorization-code "Authorization code") 1. [Refresh token](#refresh-token "Refresh token") 8. [Implicit](#implicit "Implicit") 9. [Password credentials](#password-credentials "Password credentials") ## Introduction ## In this gist I will explain you how to create a basic REST APIs system with Symfony 4 and FOSOauthServerBundle using main Oauth2 code flows. -
mirkorap revised this gist
Nov 13, 2018 . 1 changed file with 15 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,21 @@ # How to implement a REST APIs with Symfony 4 + FOSRestBundle + FOSUserBundle + FOSOauthServerBundle using main Oauth2 code flows # ## Table of contents ## 1. [introduction](#introduction "Introduction") 2. [install-bundles](#install-bundles "Install bundles") 3. [configuration](#configuration "Configuration") 1. [fosrestbundle](#fosrestbundle "FOSRestBundle") 2. [jmsserializerbundle](#jmsserializerbundle "JMSSerializerBundle") 3. [nelmioapidocbundle](#nelmioapidocbundle "NelmioApiDocBundle") 4. [fosuserbundle](#fosuserbundle "FOSUserBundle") 5. [fosoauthserverbundle](#fosoauthserverbundle "FOSOAuthServerBundle") 4. [make-migrations](#make-migrations "Make migrations") 5. [security](#security "Security") 6. [create-an-apicontroller](#create-an-apicontroller "Create an ApiController") 7. [authorization-code](#authorization-code "Authorization code") 1. [refresh-token](#refresh-token "Refresh token") 8. [implicit](#implicit "Implicit") 9. [password-credentials](#password-credentials "Password credentials") ## Introduction ## In this gist I will explain you how to create a basic REST APIs system with Symfony 4 and FOSOauthServerBundle using main Oauth2 code flows. -
mirkorap revised this gist
Nov 13, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,7 @@ # How to implement a REST APIs with Symfony 4 + FOSRestBundle + FOSUserBundle + FOSOauthServerBundle using main Oauth2 code flows # ## Table of contents ## 1. [Introduction](#Introduction "Introduction") ## Introduction ## In this gist I will explain you how to create a basic REST APIs system with Symfony 4 and FOSOauthServerBundle using main Oauth2 code flows. -
mirkorap revised this gist
Nov 13, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,7 @@ # How to implement a REST APIs with Symfony 4 + FOSRestBundle + FOSUserBundle + FOSOauthServerBundle using main Oauth2 code flows # ## Table of contents ## 1. [#Introduction](Introduction "Introduction") ## Introduction ## In this gist I will explain you how to create a basic REST APIs system with Symfony 4 and FOSOauthServerBundle using main Oauth2 code flows. -
mirkorap revised this gist
Nov 13, 2018 . 1 changed file with 3 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,8 @@ # How to implement a REST APIs with Symfony 4 + FOSRestBundle + FOSUserBundle + FOSOauthServerBundle using main Oauth2 code flows # ## Table of contents ## 1. [Introduction](Introduction "Introduction") ## Introduction ## In this gist I will explain you how to create a basic REST APIs system with Symfony 4 and FOSOauthServerBundle using main Oauth2 code flows. The flows that we implement will be: -
mirkorap revised this gist
Nov 13, 2018 . 1 changed file with 381 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -161,11 +161,11 @@ In the `config/routes.yaml` file insert these route options: fos_oauth_server_token: resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml" # Add this route only if you are going to use the Authorization code flow fos_oauth_server_authorize: resource: "@FOSOAuthServerBundle/Resources/config/routing/authorize.xml" Now we need to create the entities that we have just specified in the `fos_oauth_server.yaml` file: #### App\Entity\Client #### @@ -294,7 +294,6 @@ Now we need to create the entities that we have just specified in the `fos_oauth } } #### App\Entity\AuthCode #### <?php @@ -346,24 +345,26 @@ Now we need to create the entities that we have just specified in the `fos_oauth Above you can see the annotation `@ORM\AttributeOverrides`. This is required to solve the error: `SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes` during migrations. Documentation: [https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/blob/master/Resources/doc/index.md](https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/blob/master/Resources/doc/index.md) ## Make migrations ## We have finally finished to configure our bundles. Now we can start to see oauth2 code flows, but first we need to create migrations! So let's open your terminal and run: php bin/console make:migrations php bin/console doctrine:migration:migrate Then we need to create a user, so again open your terminal and run: php bin/console fos:user:create Please choose a username:admin Please choose an email:admin@example.com Please choose a password:admin Created user admin ## Security ## In the `config/packages/security.yaml` file insert these configuration options: security: @@ -424,3 +425,376 @@ In the `config/packages/security.yaml` file insert these configuration options: - { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } ## Create an ApiController ## Create an ApiController that will serve our resouces. In this example we will create a simple API that returns all users. <?php namespace App\Controller; use App\Entity\User; use App\Repository\UserRepository; use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\View\View; use Nelmio\ApiDocBundle\Annotation\Model; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use FOS\RestBundle\Controller\FOSRestController; use Swagger\Annotations\Swagger as SWG; class ApiController extends FOSRestController { /** * List all users * @SWG\Parameter( * in="query", * type="number", * minimum="0", * name="offset", * description="Offset from which to start listing users.", * default="0" * ) * @SWG\Parameter( * in="query", * type="integer", * name="limit", * description="How many users to return.", * default="10" * ) * @SWG\Response( * response="200", * description="Success", * @SWG\Schema( * type="array", * @Model(type=User::class) * ) * ) * @SWG\Response( * response="401", * description="Unauthorized" * ) * @Rest\Get("/api/users") * * @param Request $request * @return View */ public function index(Request $request) { $offset = $request->query->get('offset', 0); $limit = $request->query->get('limit', 10); /* @var UserRepository $userRepository */ $userRepository = $this->getDoctrine()->getRepository(User::class); $users = $userRepository->getAllUsers($offset, $limit); return $this->view($users); } } In the `src/Repository/UserRepository` let's add a `getAllUsers` function: <?php namespace App\Repository; use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Symfony\Bridge\Doctrine\RegistryInterface; /** * @method User|null find($id, $lockMode = null, $lockVersion = null) * @method User|null findOneBy(array $criteria, array $orderBy = null) * @method User[] findAll() * @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class UserRepository extends ServiceEntityRepository { public function __construct(RegistryInterface $registry) { parent::__construct($registry, User::class); } /** * @param int $offset * @param int $limit * @return mixed */ public function getAllUsers(int $offset = 0, int $limit = 10) { return $this->createQueryBuilder('u') ->setMaxResults($limit) ->setFirstResult($offset) ->getQuery() ->getResult(); } } ## Authorization code ## Finally (after a lot of configuration) we can start to see the integration of oauth2 code flows with Symfony! Let's start with the Authorization code flow. First of all we need to create a client, so open your terminal and run: `php bin/console fos:oauth-server:create-client --redirect-uri="http://localhost:8000/redirect-uri-example" --grant-type="authorization_code"` In my case the client created by the bundle has these data: +------------+---------------------------------------------------------+------------------------------------------------------+ | id | random_id | secret | +------------+---------------------------------------------------------+------------------------------------------------------+ | 1 | 3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck | 4t1922al57ack8wckcgoc84ko4oogogcoso40kwwkc4csw4cwk | +------------+---------------------------------------------------------+------------------------------------------------------+ client_id: `1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck` (id + random_id) secret: `4t1922al57ack8wckcgoc84ko4oogogcoso40kwwkc4csw4cwk` Then we need to create a `SecurityController` with two routes: `/oauth/v2/auth_login` and `/oauth/v2/auth_login_check`. These are the routes that we have specified above in the `oauth_authorize` firewall inside the `security.yaml` file. <?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; class SecurityController extends AbstractController { private $tokenManager; public function __construct(CsrfTokenManagerInterface $tokenManager = null) { $this->tokenManager = $tokenManager; } /** * @Route("/oauth/v2/auth_login", name="auth_login") * @param Request $request * @return Response */ public function loginAction(Request $request) { /** @var $session Session */ $session = $request->getSession(); $authErrorKey = Security::AUTHENTICATION_ERROR; $lastUsernameKey = Security::LAST_USERNAME; if ($request->attributes->has($authErrorKey)) { $error = $request->attributes->get($authErrorKey); } elseif (null !== $session && $session->has($authErrorKey)) { $error = $session->get($authErrorKey); $session->remove($authErrorKey); } else { $error = null; } if (!$error instanceof AuthenticationException) { $error = null; } $lastUsername = (null === $session) ? '' : $session->get($lastUsernameKey); $csrfToken = $this->tokenManager ? $this->tokenManager->getToken('authenticate')->getValue() : null; $securityCheckPath = $this->generateUrl('auth_login_check'); return $this->render('@FOSUser/Security/login.html.twig', array( 'last_username' => $lastUsername, 'error' => $error, 'csrf_token' => $csrfToken, 'security_check_path' => $securityCheckPath, )); } /** * @Route("/oauth/v2/auth_login_check", name="auth_login_check") * @param Request $request */ public function loginCheckAction(Request $request) { } } To verify that all works properly, we should call this route: `http://localhost:8000/oauth/v2/auth?client_id=1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck&redirect_uri=http://localhost:8000/redirect-uri-example&response_type=code` The client_id query parameter should be replaced by the client_id created previously. The response should be a page with two buttons: "allow" and "deny". After clicking in the "allow" button you will redirect to the `redirect_uri`. In the url you can notice a code query parameter, that is our authorization code! Now we need to exchange that code with an `access_token`. So let's create a request to our `/oauth/v2/token` route: http POST http://localhost:8000/oauth/v2/token \ grant_type=authorization_code \ client_id=1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck \ client_secret=4t1922al57ack8wckcgoc84ko4oogogcoso40kwwkc4csw4cwk \ code=NWVmMDY4NjE3OWUwOTI4MmZkN2FiNmI4NTgwMGNhNzg3ZTRjYmMzZmI5MmUzMWFiYzk0YWJjMmZiM2MxNmExZQ \ redirect_uri=http://localhost:8000/redirect-uri-example \ HTTP/1.1 200 OK Cache-Control: no-store, private Connection: close Content-Type: application/json The response should looks like this: { "access_token": "ZTFiZWIwMzI4ZTg4MmYzNTExNjkxMzYwODBlMzQ3NTgxNzM1ODMxYTQzNGZkZDI0ZjQ4MmRkN2ZjMDRhMWU2YQ", "expires_in": 3600, "token_type": "bearer", "scope": null, "refresh_token": "NDFiNjY3MWU3YmZhMDkxNjI5NjBjZDhhNmYzNmJkYjI1NTIzMGJiZTQzYTA0NzlkYjU2OTgzYmM5MzZlODg2NQ" } Now we can finally call our APIs! Create a request to the route: `localhost:8000/api/users` and pass in the header the `access_token`: http GET localhost:8000/api/users \ "Authorization:Bearer ZTFiZWIwMzI4ZTg4MmYzNTExNjkxMzYwODBlMzQ3NTgxNzM1ODMxYTQzNGZkZDI0ZjQ4MmRkN2ZjMDRhMWU2YQ" HTTP/1.1 200 OK Cache-Control: no-cache Connection: close Content-Type: application/json The response should looks like this: [ { "id": 1, "username": "admin", "username_canonical": "admin", "email": "admin@example.com", "email_canonical": "admin@example.com", "enabled": true, "password": "$2y$13$HMApz6BLBHXbsLx2GZWJcOTxx3bqv2yKWg7vst5c7C10SXpNgVlE.", "last_login": "2018-11-11T20:40:54+01:00", "groups": [], "roles": [] } ] ### Refresh token ### In the authorization code flow (and in the password credentials flow too) you gain another important token, the `refresh_token`! This token help you to refresh the `access_token` when expires, without having to ask the user to re-grant access to his data to the application he is using. To use the `refresh_token` you need to add it as `grant_type` during the creation of client: `php bin/console fos:oauth-server:create-client --redirect-uri="http://localhost:8000/redirect-uri-example" --grant-type="authorization_code" --grant-type="refresh_token"` Then to get a new `access_token` you need to call the route: `/oauth/v2/token` with the `refresh_token` in the body of request: http POST http://localhost:8000/oauth/v2/token \ grant_type=refresh_token \ client_id=1_3pwul4sg6ge8s444og4wk4g88480cosowosg0k080owo0o0wck \ client_secret=4t1922al57ack8wckcgoc84ko4oogogcoso40kwwkc4csw4cwk \ refresh_token=YzFlMjQ3ZjRkZTVmZTA5ODZhZmI0YzA4Y2Y5YzY4ZmEwYjNhNTNhNWY0YTVkYmRiZjUxZjBlZTQ1NWNlZjY4OQ \ redirect_uri=http://localhost:8000/redirect-uri-example \ HTTP/1.1 200 OK Cache-Control: no-store, private Connection: close Content-Type: application/json ## Implicit ## This flow is principally used in SPA. A difference from the previous flow is that we will receive an access_token immediately, so we don't need to exchange an authorization code for an access_token. You may think "Why I should use the Authorization code flow if the Implicit one is more simple?". The answer is easy, you MUST use the authorization code flow if you need to call API even when the user is offline. In fact with the Implicit flow you will not receive a refresh_token (for security reason), so when the access_token expire the user must authorize access again. For this reason this flow is more suitable in the SPA. Let's see how it works: Again we need to create a client, so open your terminal and run: `php bin/console fos:oauth-server:create-client --redirect-uri="http://localhost:8000/redirect-uri-example" --grant-type="implicit"` In my case the client created by the bundle has these data: +------------+---------------------------------------------------------+------------------------------------------------------+ | id | random_id | secret | +------------+---------------------------------------------------------+------------------------------------------------------+ | 2 | 2shspbzhca2ogw44kckw00s4s800g0s484004ccokcw8gogwks | 3fcdpac3iw6cw8k8gs48kwc8ows4s4wkcg8gwgsgck84g48k0s | +------------+---------------------------------------------------------+------------------------------------------------------+ client_id: `2_2shspbzhca2ogw44kckw00s4s800g0s484004ccokcw8gogwks` (id + random_id) secret: `3fcdpac3iw6cw8k8gs48kwc8ows4s4wkcg8gwgsgck84g48k0s` With these data we can call immediately the route `http://localhost:8000/oauth/v2/auth?client_id=2_2shspbzhca2ogw44kckw00s4s800g0s484004ccokcw8gogwks&redirect_uri=http://localhost:8000/redirect-uri-example&response_type=token` The client_id query parameter should be replaced by the client_id created previously. The response should be a page with two buttons: "allow" and "deny". After clicking in the "allow" button you will redirect to the `redirect_uri`. In the url you can notice an hash with the access_token. Now we can call our API to get all users (remember to pass a Bearer header with the access_token): http GET localhost:8000/api/users \ "Authorization:Bearer NDYxMmUwZGI5OTQ4Y2UzNDQ5M2JhY2YwYmU3YmM2NDlkMDUyNTk4MjE2N2ZhNDU2OWQ2MTc4NjM1MmYxMDBmOQ" HTTP/1.1 200 OK Cache-Control: no-cache Connection: close Content-Type: application/json The response should looks like this: [ { "id": 1, "username": "admin", "username_canonical": "admin", "email": "admin@example.com", "email_canonical": "admin@example.com", "enabled": true, "password": "$2y$13$HMApz6BLBHXbsLx2GZWJcOTxx3bqv2yKWg7vst5c7C10SXpNgVlE.", "last_login": "2018-11-11T20:40:54+01:00", "groups": [], "roles": [] } ] ## Password credentials ## This flow is used when we need to serve resources to a trusted application. Normally is used when the application that will use our APIs is our application itself. During the request to retrieve the `access_token`, the external application must send the username and password too. Let's start to see how it works: Again we need to create a client, so open your terminal and run: `php bin/console fos:oauth-server:create-client --redirect-uri="http://localhost:8000/redirect-uri-example" --grant-type="password"` In my case the client created by the bundle has these data: +------------+---------------------------------------------------------+------------------------------------------------------+ | id | random_id | secret | +------------+---------------------------------------------------------+------------------------------------------------------+ | 3 | 492ohmxbo3k0gggwg08wso4cs0k4sswcwg8wo8so0cgo4cwo0s | 64jack8z62888k4sgcgssow080wcgsk04408wogkc4owgkgokc | +------------+---------------------------------------------------------+------------------------------------------------------+ client_id: `3_492ohmxbo3k0gggwg08wso4cs0k4sswcwg8wo8so0cgo4cwo0s` (id + random_id) secret: `64jack8z62888k4sgcgssow080wcgsk04408wogkc4owgkgokc` With these data we can call the route to get the `access_token`, but this time we should send also username and password! http POST http://localhost:8000/oauth/v2/token \ grant_type=password \ client_id=3_492ohmxbo3k0gggwg08wso4cs0k4sswcwg8wo8so0cgo4cwo0s \ client_secret=64jack8z62888k4sgcgssow080wcgsk04408wogkc4owgkgokc \ username=admin \ password=admin HTTP/1.1 200 OK Cache-Control: no-store, private Connection: close Content-Type: application/json The username and password that you see above come from the user created by FOSUserBundle command `php bin/console fos:user:create`. Now we can call our APIs http GET localhost:8000/api/users \ "Authorization:Bearer MmQ5MzRlOTRhNWUzMzY0ZGU1ZjMzMjkwY2I0YjlhN2NlOTBhZjg5NGJjMGM5Yzk2ZGFiYWI5YTBkYjBiMWIyNw" HTTP/1.1 200 OK Cache-Control: no-cache Connection: close Content-Type: application/json The response should looks like this: [ { "id": 1, "username": "admin", "username_canonical": "admin", "email": "admin@example.com", "email_canonical": "admin@example.com", "enabled": true, "password": "$2y$13$HMApz6BLBHXbsLx2GZWJcOTxx3bqv2yKWg7vst5c7C10SXpNgVlE.", "last_login": "2018-11-11T20:40:54+01:00", "groups": [], "roles": [] } ] -
mirkorap revised this gist
Nov 10, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -418,7 +418,7 @@ In the `config/packages/security.yaml` file insert these configuration options: anonymous: true access_control: - { path: ^/oauth/v2/auth_login$, role: IS_AUTHENTICATED_ANONYMOUSLY } # Add this only in the Authorization code flow - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/api, roles: IS_AUTHENTICATED_FULLY } - { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY } -
mirkorap revised this gist
Nov 10, 2018 . 1 changed file with 294 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -25,6 +25,8 @@ Below I will explain for each bundle what they do and how to configure them. ## Configuration ## ### FOSRestBundle ### FOSRestBundle allow us to configure our APIs and serve resources in different format in an easy way. There a different configuration options that you can use, but in our example we need to serve resources in json/xml format for all routes starting with `/api`, instead for all others we will serve simple html pages. In the `config/packages/fos_rest.yaml` file insert these configuration options: fos_rest: @@ -41,29 +43,29 @@ In the `config/packages/fos_rest.yaml` file insert these configuration options: view: view_response_listener: true Documentation: [https://symfony.com/doc/master/bundles/FOSRestBundle/index.html](https://symfony.com/doc/master/bundles/FOSRestBundle/index.html) ### JMSSerializerBundle ### JMSSerializerBundle allows you to serialize your data into a requested output format such as JSON, XML, or YAML. In the `config/packages/jms_serializer.yaml` file insert these configuration options: jms_serializer: visitors: xml: format_output: '%kernel.debug%' Documentation: [https://jmsyst.com/bundles/JMSSerializerBundle](https://jmsyst.com/bundles/JMSSerializerBundle) ### NelmioApiDocBundle ### NelmioApiDocBundle is a Symfony's bundle that allow us to generate documentation for our APIs. In the `config/packages/nelmio_api_doc.yaml` file insert these configuration options: nelmio_api_doc: documentation: info: title: Oauth2 Server App description: This is my oauth2 server app version: 1.0.0 @@ -83,11 +85,11 @@ In the `config/routes.yaml` file insert this route option: resource: "@NelmioApiDocBundle/Resources/config/routing/swaggerui.xml" prefix: /api/doc Documentation: [https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html](https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html) ### FOSUserBundle ### FOSUserBundle allow us to manage users (store and load users, register and authenticate users etc.) In the `config/packages/fos_user.yaml` file insert these configuration options: fos_user: @@ -137,3 +139,288 @@ Now let's to create our entity User class: return $this->id; } } Documentation: [https://symfony.com/doc/current/bundles/FOSUserBundle/index.html](https://symfony.com/doc/current/bundles/FOSUserBundle/index.html) ### FOSOAuthServerBundle ### FOSOAuthServerBundle is a Symfony bundle that allow us to create our oauth2 server app. In this gist I will exaplain you how to use it with the main oauth2 code flows (Authorization code, Implicit, Password credentials). Let's take a look to the configuration options: In the `config/packages/fos_oauth_server.yaml` file insert these configuration options: fos_oauth_server: db_driver: orm client_class: App\Entity\Client access_token_class: App\Entity\AccessToken refresh_token_class: App\Entity\RefreshToken auth_code_class: App\Entity\AuthCode service: user_provider: fos_user.user_provider.username In the `config/routes.yaml` file insert these route options: fos_oauth_server_token: resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml" # Add this route only if you are using the Authorization code flow fos_oauth_server_authorize: resource: "@FOSOAuthServerBundle/Resources/config/routing/authorize.xml" Now we need to create the entities that we have just specified in the `fos_oauth_server.yaml` configuration file: #### App\Entity\Client #### <?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use FOS\OAuthServerBundle\Entity\Client as BaseClient; /** * @ORM\Table("oauth2_clients") * @ORM\Entity(repositoryClass="App\Repository\ClientRepository") */ class Client extends BaseClient { /** * @ORM\Id() * @ORM\GeneratedValue(strategy="AUTO") * @ORM\Column(type="integer") */ protected $id; public function getId(): ?int { return $this->id; } } #### App\Entity\AccessToken #### <?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use FOS\OAuthServerBundle\Entity\AccessToken as BaseAccessToken; /** * @ORM\Table("oauth2_access_tokens") * @ORM\Entity(repositoryClass="App\Repository\AccessTokenRepository") * @ORM\AttributeOverrides({ * @ORM\AttributeOverride(name="token", * column=@ORM\Column( * name = "token", * type = "string", * length = 128 * ) * ) * }) */ class AccessToken extends BaseAccessToken { /** * @ORM\Id() * @ORM\GeneratedValue(strategy="AUTO") * @ORM\Column(type="integer") */ protected $id; /** * @ORM\ManyToOne(targetEntity="App\Entity\Client") * @ORM\JoinColumn(nullable=false) */ protected $client; /** * @ORM\ManyToOne(targetEntity="App\Entity\User") */ protected $user; public function getId(): ?int { return $this->id; } } #### App\Entity\RefreshToken #### <?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use FOS\OAuthServerBundle\Entity\RefreshToken as BaseRefreshToken; /** * @ORM\Table("oauth2_refresh_tokens") * @ORM\Entity(repositoryClass="App\Repository\RefreshTokenRepository") * @ORM\AttributeOverrides({ * @ORM\AttributeOverride(name="token", * column=@ORM\Column( * name = "token", * type = "string", * length = 128 * ) * ) * }) */ class RefreshToken extends BaseRefreshToken { /** * @ORM\Id() * @ORM\GeneratedValue(strategy="AUTO") * @ORM\Column(type="integer") */ protected $id; /** * @ORM\ManyToOne(targetEntity="App\Entity\Client") * @ORM\JoinColumn(nullable=false) */ protected $client; /** * @ORM\ManyToOne(targetEntity="App\Entity\User") */ protected $user; public function getId(): ?int { return $this->id; } } #### App\Entity\AuthCode #### <?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use FOS\OAuthServerBundle\Entity\AuthCode as BaseAuthCode; /** * @ORM\Table("oauth2_auth_codes") * @ORM\Entity(repositoryClass="App\Repository\AuthCodeRepository") * @ORM\AttributeOverrides({ * @ORM\AttributeOverride(name="token", * column=@ORM\Column( * name = "token", * type = "string", * length = 128 * ) * ) * }) */ class AuthCode extends BaseAuthCode { /** * @ORM\Id() * @ORM\GeneratedValue(strategy="AUTO") * @ORM\Column(type="integer") */ protected $id; /** * @ORM\ManyToOne(targetEntity="App\Entity\Client") * @ORM\JoinColumn(nullable=false) */ protected $client; /** * @ORM\ManyToOne(targetEntity="App\Entity\User") */ protected $user; public function getId(): ?int { return $this->id; } } Above you can see the annotation `@ORM\AttributeOverrides`. This is required to solve the error: `SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes` during migrations. ### Make migrations ### Now that we have finally finished to configure our bundles we can start to see oauth2 code flows, but first we need to create migrations! So let's open your terminal and run: php bin/console make:migrations php bin/console doctrine:migration:migrate Now we need to create our user, so again open your terminal and run: php bin/console fos:user:create Please choose a username:admin Please choose an email:admin@example.com Please choose a password:admin Created user admin ### Security ### In the `config/packages/security.yaml` file insert these configuration options: security: encoders: FOS\UserBundle\Model\UserInterface: bcrypt role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: ROLE_ADMIN providers: fos_userbundle: id: fos_user.user_provider.username firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false oauth_token: pattern: ^/oauth/v2/token security: false # Add this firewall only in the Authorization code flow oauth_authorize: pattern: ^/oauth/v2/auth form_login: provider: fos_userbundle check_path: /oauth/v2/auth_login_check login_path: /oauth/v2/auth_login anonymous: true api_doc: pattern: ^/api/doc fos_oauth: false stateless: true anonymous: true api: pattern: ^/api fos_oauth: true stateless: true anonymous: false main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager logout: true fos_oauth: false anonymous: true access_control: - { path: ^/oauth/v2/auth_login$, role: IS_AUTHENTICATED_ANONYMOUSLY } # This control is necessary only in the Authorization code flow - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/api, roles: IS_AUTHENTICATED_FULLY } - { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } -
mirkorap revised this gist
Nov 6, 2018 . 1 changed file with 139 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1 +1,139 @@ # How to implement a REST APIs with Symfony 4 + FOSRestBundle + FOSUserBundle + FOSOauthServerBundle using main Oauth2 code flows # ## Introduction ## In this gist I will explain you how to create a basic REST APIs system with Symfony 4 and FOSOauthServerBundle using main Oauth2 code flows. The flows that we implement will be: 1. Authorization code 2. Implicit 3. Password credentials I will separate the gist into two configuration parts. The first part is the common configuration that is equal for all Oauth2 code flows above. In the second part I will explain, for each code flows above, the basic configuration type that you need. So let's coding! ## Install bundles ## The first step is to download Symfony and the related bundles. composer create-project symfony/skeleton oauth2-server cd oauth2-server composer require friendsofsymfony/rest-bundle composer require jms/serializer-bundle composer require nelmio/api-doc-bundle composer require friendsofsymfony/user-bundle "~2.0@dev" composer require friendsofsymfony/oauth-server-bundle Below I will explain for each bundle what they do and how to configure them. ## Configuration ## ### FOSRestBundle ### In the `config/packages/fos_rest.yaml` file insert these configuration options: fos_rest: routing_loader: default_format: html include_format: true format_listener: enabled: true rules: - { path: '^/api', priorities: ['json', 'xml'], fallback_format: json, prefer_extension: false } - { path: '^/', priorities: ['html'], fallback_format: html, prefer_extension: false } view: view_response_listener: true With the rules above our application will serve for the routes starting with /api only resources formatted in json/xml, instead for all remaining routes it will render simple html pages. The configuration option `view_response_listener` makes it possible to simply return a `View` instance from action controllers. Documentation: [https://symfony.com/doc/master/bundles/FOSRestBundle/index.html](https://symfony.com/doc/master/bundles/FOSRestBundle/index.html) ### JMSSerializerBundle ### In the `config/packages/jms_serializer.yaml` file insert these configuration options: jms_serializer: visitors: xml: format_output: '%kernel.debug%' JMSSerializerBundle allows you to serialize your data into a requested output format such as JSON, XML, or YAML. Documentation: [https://jmsyst.com/bundles/JMSSerializerBundle](https://jmsyst.com/bundles/JMSSerializerBundle) ### NelmioApiDocBundle ### In the `config/packages/nelmio_api_doc.yaml` file insert these configuration options: nelmio_api_doc: documentation: info: title: Oauth Server App description: This is my oauth2 server app version: 1.0.0 securityDefinitions: Bearer: type: apiKey description: 'Value: Bearer {access_token}' name: Authorization in: header areas: path_patterns: - ^/api(?!/doc$) In the `config/routes.yaml` file insert this route option: NelmioApiDocBundle: resource: "@NelmioApiDocBundle/Resources/config/routing/swaggerui.xml" prefix: /api/doc NelmioApiDocBundle is a Symfony's bundle that allow us to generate documentation for our APIs. Documentation: [https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html](https://symfony.com/doc/current/bundles/NelmioApiDocBundle/index.html) ### FOSUserBundle ### In the `config/packages/fos_user.yaml` file insert these configuration options: fos_user: db_driver: orm user_class: App\Entity\User firewall_name: main from_email: address: john@example.com sender_name: john@example.com In the `config/routes.yaml` file insert this route option: fos_user: resource: "@FOSUserBundle/Resources/config/routing/all.xml" In the `config/packages/framework.yaml` file insert this line at the end of file: templating: engines: twig Now let's to create our entity User class: <?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use FOS\UserBundle\Model\User as BaseUser; /** * @ORM\Table("users") * @ORM\Entity(repositoryClass="App\Repository\UserRepository") */ class User extends BaseUser { /** * @ORM\Id() * @ORM\GeneratedValue(strategy="AUTO") * @ORM\Column(type="integer") */ protected $id; public function getId(): ?int { return $this->id; } } -
mirkorap created this gist
Nov 5, 2018 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ TODO