mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 17:37:23 +00:00
docs(examples): symfony php guide (#7171)
* docs(examples): symfony php guide * hopefully fix vercel * complete guide * add guide to navigation Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
This commit is contained in:
parent
29b386005d
commit
0a65e20507
@ -108,9 +108,9 @@ Our examples cover a range of programming languages and frameworks, so no matter
|
||||
<td width="100px">
|
||||
<img src="/docs/img/tech/php.svg" alt="php"/>
|
||||
</td>
|
||||
<td>PHP Web</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Symfony PHP Framework</td>
|
||||
<td><a href="https://github.com/zitadel/example-symfony-oidc" target="_blank"><i class="lab la-github"></i></a></td>
|
||||
<td><a href="/examples/login/symfony">Guide</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -161,7 +161,7 @@ This line automatically refreshes a token before it expires.
|
||||
|
||||
Congratulations! You have successfully integrated your Angular application with ZITADEL!
|
||||
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/zitadel-angular) application. This application includes all the funcationalities mentioned in this quickstart. You can start by cloning the repository and replacing the _AuthConfig_ in the _AppModule_ with your own configuration. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/zitadel).
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/zitadel-angular) application. This application includes all the functionalities mentioned in this quick-start. You can start by cloning the repository and replacing the _AuthConfig_ in the _AppModule_ with your own configuration. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/zitadel).
|
||||
|
||||

|
||||
|
||||
|
408
docs/docs/examples/login/symfony.md
Normal file
408
docs/docs/examples/login/symfony.md
Normal file
@ -0,0 +1,408 @@
|
||||
---
|
||||
title: ZITADEL with Symfony PHP
|
||||
sidebar_label: Symfony
|
||||
---
|
||||
|
||||
This integration guide demonstrates the recommended way to incorporate ZITADEL into your Symfony PHP application.
|
||||
It explains how to enable user login in your application and how to fetch data from the user info endpoint.
|
||||
|
||||
By the end of this guide, your application will have login functionality with basic role mapping, access the current user's profile and a user list accessible by admins.
|
||||
|
||||
:::info
|
||||
This documentation references our [example](https://github.com/zitadel/example-symfony-oidc) on GitHub.
|
||||
:::
|
||||
|
||||
## ZITADEL setup
|
||||
|
||||
Before we can start building our application, we have to do a few configuration steps in ZITADEL Console.
|
||||
|
||||
### Project roles
|
||||
|
||||
The Example expects [user roles](guides/integrate/retrieve-user-roles) to be returned after login.
|
||||
Symfony uses `ROLE_USER` format.
|
||||
The application will take care of upper-casing and prefixing for us.
|
||||
Inside ZITADEL, you can use regular lower-case role names without prefixes, if you prefer.
|
||||
|
||||
> Symfony automatically assigns `ROLE_USER` to any authenticated user.
|
||||
|
||||
In your project settings make sure the "Assert Roles On Authentication" is enabled.
|
||||
|
||||

|
||||
|
||||
In the project Role tab, add 2 special roles:
|
||||
|
||||
- `admin`: Assigned to users that need access to the user list.
|
||||
- `foo`: Random role for display purposes
|
||||
|
||||
A `user` role is not required. This role is assumed by default for any authenticated user in Symfony.
|
||||
|
||||

|
||||
|
||||
Finally, we can assign the roles to users in the project's authorizations tab.
|
||||
|
||||

|
||||
|
||||
### Set up application and obtain secrets
|
||||
|
||||
Next you will need to provide some information about your app.
|
||||
|
||||
In your Project, add a new application at the top of the page.
|
||||
Select Web application type and continue.
|
||||
We use [Authorization Code](/apis/openidoauth/grant-types#authorization-code)for our Symfony application.
|
||||
|
||||

|
||||
|
||||
Select `CODE` in the next step. This makes sure you still get a secret. Note that the secret never gets exposed on the browser and is therefore kept in a confidential environment. Safe the generated
|
||||
|
||||

|
||||
|
||||
With the Redirect URIs field, you tell ZITADEL where it is allowed to redirect users to after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
|
||||
|
||||
For the example application we are writing use:
|
||||
|
||||
- `http://localhost:8000/login_check` as Redirect URI
|
||||
- `http://localhost:8000/logout` as post-logout URI.
|
||||
|
||||

|
||||
|
||||
After the final step you are presented with a client ID and secret.
|
||||
Copy and paste them to a safe location for later use by the application.
|
||||
The secret will not be displayed again, but you can regenerate one if you loose it.
|
||||
|
||||
## Setup new Symfony application
|
||||
|
||||
Now that you have configured your web application on the ZITADEL side, you can proceed with the integration of your Symfony client.
|
||||
The example is build on a [generated Symfony web app](https://symfony.com/doc/current/setup.html#creating-symfony-applications), using the following command:
|
||||
|
||||
:::info
|
||||
Skip this step if you are connecting ZITADEL to an existing application.
|
||||
:::
|
||||
|
||||
```bash
|
||||
symfony new my_project_directory --version="7.0.*" --webapp
|
||||
cd my_project_directory
|
||||
```
|
||||
|
||||
:::info
|
||||
The remainder of this guide assumes a Symfony project which already includes all web app bundles, such as security, routing and ORM.
|
||||
If you are using this guide against an existing project you must make sure the required bundles are installed using the `composer require` command.
|
||||
:::
|
||||
|
||||
### Install Symfony dependencies
|
||||
|
||||
To connect with ZITADEL through OpenID connect, you need to install the [Symfony OIDC bundle](https://github.com/Drenso/symfony-oidc). Run the following command:
|
||||
|
||||
```bash
|
||||
composer require drenso/symfony-oidc-bundle
|
||||
```
|
||||
|
||||
## Define the Symfony app
|
||||
|
||||
### Create a User class
|
||||
|
||||
First, we need to create a User class for the database, so we can persist user info between requests. In this case you don't need password authentication.
|
||||
Email addresses are not unique for ZITADEL users. There can be multiple user accounts with the same email address.
|
||||
See [User Constraints](https://zitadel.com/docs/concepts/structure/users#constraints) for more details.
|
||||
We will use the User Info `sub` claim as unique "display" name for the user. `sub` equals the unique User ID from ZITADEL.
|
||||
This creates a User Repository and Entity that implements the `UserInterface`:
|
||||
|
||||
:::info
|
||||
You can skip this step, if you already have an existing User object in your project.
|
||||
:::
|
||||
|
||||
```bash
|
||||
php bin/console make:user
|
||||
|
||||
The name of the security user class (e.g. User) [User]:
|
||||
> User
|
||||
|
||||
Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]:
|
||||
> yes
|
||||
|
||||
Enter a property name that will be the unique "display" name for the user (e.g. email, username, uuid) [email]:
|
||||
> sub
|
||||
|
||||
Will this app need to hash/check user passwords? Choose No if passwords are not needed or will be checked/hashed by some other system (e.g. a single sign-on server).
|
||||
|
||||
Does this app need to hash/check user passwords? (yes/no) [yes]:
|
||||
> no
|
||||
```
|
||||
|
||||
Next, extend the User Entity with properties that we will obtain from ZITADEL and use in the application later.
|
||||
|
||||
> None of the following properties are required for authentication, but show how we can map User Info to a Symfony User Entity later. You can adjust the properties how you wish for your application.
|
||||
|
||||
```bash
|
||||
php bin/console make:entity
|
||||
|
||||
Class name of the entity to create or update (e.g. GrumpyElephant):
|
||||
> User
|
||||
|
||||
Your entity already exists! So let's add some new fields!
|
||||
|
||||
New property name (press <return> to stop adding fields):
|
||||
> display_name
|
||||
|
||||
Field type (enter ? to see all types) [string]:
|
||||
> string
|
||||
|
||||
Field length [255]:
|
||||
> 255
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> yes
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> full_name
|
||||
|
||||
Field type (enter ? to see all types) [string]:
|
||||
> string
|
||||
|
||||
Field length [255]:
|
||||
>
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> yes
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> email
|
||||
|
||||
Field type (enter ? to see all types) [string]:
|
||||
> string
|
||||
|
||||
Field length [255]:
|
||||
> 255
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> yes
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> email_verified
|
||||
|
||||
Field type (enter ? to see all types) [string]:
|
||||
> boolean
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> yes
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> created_at
|
||||
|
||||
Field type (enter ? to see all types) [datetime_immutable]:
|
||||
> datetime_immutable
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> no
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
> updated_at
|
||||
|
||||
Field type (enter ? to see all types) [datetime_immutable]:
|
||||
> datetime_immutable
|
||||
|
||||
Can this field be null in the database (nullable) (yes/no) [no]:
|
||||
> no
|
||||
|
||||
updated: src/Entity/User.php
|
||||
|
||||
Add another property? Enter the property name (or press <return> to stop adding fields):
|
||||
>
|
||||
|
||||
Success!
|
||||
```
|
||||
|
||||
Now edit `src/Entity/User.php` to add some methods to pretty-print user data later in this example. Add import near the top of the file:
|
||||
|
||||
```php
|
||||
use DateTimeInterface;
|
||||
```
|
||||
|
||||
And extend the User class with this methods:
|
||||
|
||||
```php
|
||||
class User implements UserInterface
|
||||
{
|
||||
...
|
||||
|
||||
public function implodeRoles(): string
|
||||
{
|
||||
return implode(', ', $this->getRoles());
|
||||
}
|
||||
|
||||
public function formatCreatedAt(): string
|
||||
{
|
||||
return $this->created_at->format(DateTimeInterface::W3C);
|
||||
}
|
||||
|
||||
public function formatUpdatedAt(): string
|
||||
{
|
||||
return $this->updated_at->format(DateTimeInterface::W3C);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When you are done, the User Entity should look something like:
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Entity/User.php
|
||||
```
|
||||
|
||||
Edit the User Repository to have a `findOneBySub` method, used later for OIDC User Info updates.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Repository/UserRepository.php
|
||||
```
|
||||
|
||||
### Create a Security Provider
|
||||
|
||||
Next you will need to create a Security Provider that integrates the OIDC flow between Symfony and ZITADEL.
|
||||
Create a `ZitadelUserProvider` which implements `UserProviderInterface`, `OidcUserProviderInterface` and `LoggerAwareInterface`.
|
||||
`LoggerAwareInterface` is optional if you want debug logging.
|
||||
|
||||
> We called this a `ZitadelUserProvider` because it carries a custom scope and claim mapping from ZITADEL roles to the Symfony role system.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Security/ZitadelUserProvider.php
|
||||
```
|
||||
|
||||
You can customize the User Info that is obtained and stored by adjusting the `SCOPES` constant, the `updateUserEntity` method and the User Entity.
|
||||
|
||||
### Controllers and templates
|
||||
|
||||
We need to create couple of Controllers and templates to define the app.
|
||||
|
||||
#### Index
|
||||
|
||||
The index controller serves a public page on the `/` route and provides some basic links to the authenticated sections of the app.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Controller/IndexController.php
|
||||
```
|
||||
|
||||
The index template:
|
||||
|
||||
```twig reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/templates/index.html.twig
|
||||
```
|
||||
|
||||
#### Login
|
||||
|
||||
The login controller initiates the OIDC login flow by creating a Auth request and redirecting the user to ZITADEL.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Controller/LoginController.php
|
||||
```
|
||||
|
||||
#### Profile
|
||||
|
||||
The profile controller displays User Info of the currently authenticated user.
|
||||
Any authenticated user will have access to this page.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Controller/ProfileController.php
|
||||
```
|
||||
|
||||
The profile template maps the User Entity to a HTML page.
|
||||
|
||||
```twig reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/templates/profile.html.twig
|
||||
```
|
||||
|
||||
#### User list
|
||||
|
||||
The user list controller displays all users from the database, that were created during OIDC login.
|
||||
Only users with an admin role will have access to this page.
|
||||
|
||||
```php reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/src/Controller/UserListController.php
|
||||
```
|
||||
|
||||
```twig reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/templates/user_list.html.twig
|
||||
```
|
||||
|
||||
## Configure and run the application
|
||||
|
||||
:::warning
|
||||
Never store and commit secrets in a `.env` file. Use a `env.local` file instead and make sure the file is in `.gitignore`.
|
||||
:::
|
||||
|
||||
### Database
|
||||
|
||||
Make sure you have a database configured in `.env` or `.env.local`. This example uses a local sqlite file to simplify setup:
|
||||
|
||||
```sh
|
||||
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
|
||||
```
|
||||
|
||||
Create and run migrations:
|
||||
|
||||
```bash
|
||||
php bin/console make:migration
|
||||
php bin/console doctrine:migrations:migrate
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
A firewall needs to be defined along with roles based access control rules.
|
||||
In the following example we define the `zitadel_user_provider` as the security class we wrote earlier. We configure the main firewall to use the `zitadel_user_provider` and listen for logout requests on the `/logout` path. We tell the oidc module to enable End Session support.
|
||||
|
||||
In the `access_control` section we protect the `/users` and `/profile` routes based on roles. Roles are mapped from ZITADEL to Symfony in the `ZitadelUserProvider` we wrote earlier.
|
||||
|
||||
```yaml reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/config/packages/security.yaml
|
||||
```
|
||||
|
||||
### OIDC
|
||||
|
||||
The generated [`dresno_oidc.yaml`](https://github.com/zitadel/example-symfony-oidc/blob/main/config/packages/drenso_oidc.yaml) file can be edited to customize behavior of the OIDC bundle. For this example we stick with the default and use environment variables to connect to ZITADEL.
|
||||
|
||||
Edit `.env.local` to contain the details from the [Application setup section](#set-up-application-and-obtain-keys).
|
||||
|
||||
```sh
|
||||
OIDC_WELL_KNOWN_URL="https://tims-zitadel-instance-oj7iry.zitadel.cloud/.well-known/openid-configuration"
|
||||
OIDC_CLIENT_ID="248680248240075805@dev"
|
||||
OIDC_CLIENT_SECRET="BJPhEJULSUXseC4geqg5Yg4wWMoy7RgZKar86mbIpt8ZekC5kixMzYGcXLDeeJv7"
|
||||
```
|
||||
|
||||
> The well-known URL needs to be adjusted to your own instance domain.
|
||||
|
||||
Activate the route that is used as callback by the OIDC bundle:
|
||||
|
||||
```yaml reference
|
||||
https://github.com/zitadel/example-symfony-oidc/blob/main/config/routes.yaml#L6-L7
|
||||
```
|
||||
|
||||
### Run
|
||||
|
||||
You can use a local Symfony server to test the application.
|
||||
|
||||
```bash
|
||||
symfony server:start --no-tls
|
||||
```
|
||||
|
||||
Visit http://localhost:8000 and click around.
|
||||
When you go to profile you will be redirected to login your user on ZITADEL.
|
||||
After login you should see some profile data of the current user.
|
||||
Upon clicking logout you are redirected to the homepage.
|
||||
Now you can click "users" and login with an account that has the admin role.
|
||||
|
||||
## Completion
|
||||
|
||||
Congratulations! You have successfully integrated your Symfony application with ZITADEL!
|
||||
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/example-symfony-oidc) application. This application includes all the functionalities mentioned in this quick-start. You can start by cloning the repository and defining a `.env.local` with your settings. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/example-symfony-oidc/issues).
|
||||
|
||||
### What's next?
|
||||
|
||||
Now that you have enabled authentication, it's time for you to add more authorizations to your application using ZITADEL APIs. To do this, you can refer to the [docs](/apis/introduction) or check out the ZITADEL Console code on [GitHub](https://github.com/zitadel/zitadel) which uses gRPC and OpenAPI to access data.
|
@ -16,6 +16,7 @@ module.exports = {
|
||||
"examples/login/flutter",
|
||||
"examples/login/nextjs",
|
||||
"examples/login/go",
|
||||
"examples/login/symfony"
|
||||
],
|
||||
collapsed: true,
|
||||
},
|
||||
|
BIN
docs/static/img/symfony/app-auth-method.png
vendored
Normal file
BIN
docs/static/img/symfony/app-auth-method.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 212 KiB |
BIN
docs/static/img/symfony/app-create.png
vendored
Normal file
BIN
docs/static/img/symfony/app-create.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 212 KiB |
BIN
docs/static/img/symfony/app-redirects.png
vendored
Normal file
BIN
docs/static/img/symfony/app-redirects.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 133 KiB |
BIN
docs/static/img/symfony/project-authorizations.png
vendored
Normal file
BIN
docs/static/img/symfony/project-authorizations.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
BIN
docs/static/img/symfony/project-roles.png
vendored
Normal file
BIN
docs/static/img/symfony/project-roles.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
BIN
docs/static/img/symfony/project-settings.png
vendored
Normal file
BIN
docs/static/img/symfony/project-settings.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
Loading…
x
Reference in New Issue
Block a user