https://github.com/itk-dev/openid-connect-bundle
Symfony bundle for open-id connect
https://github.com/itk-dev/openid-connect-bundle
azureb2c openid-connect symfony
Last synced: 5 months ago
JSON representation
Symfony bundle for open-id connect
- Host: GitHub
- URL: https://github.com/itk-dev/openid-connect-bundle
- Owner: itk-dev
- License: mit
- Created: 2021-03-15T09:50:57.000Z (about 5 years ago)
- Default Branch: develop
- Last Pushed: 2025-01-16T21:14:06.000Z (about 1 year ago)
- Last Synced: 2025-02-13T20:51:47.073Z (about 1 year ago)
- Topics: azureb2c, openid-connect, symfony
- Language: PHP
- Homepage:
- Size: 156 KB
- Stars: 1
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
# OpenId Connect Bundle
[](https://github.com/itk-dev/openid-connect-bundle)
[](https://packagist.org/packages/itk-dev/openid-connect-bundle)
[](https://www.php.net/downloads)
[](https://github.com/itk-dev/openid-connect-bundle/actions?query=workflow%3A%22Test+%26+Code+Style+Review%22)
[](https://codecov.io/gh/itk-dev/openid-connect-bundle)
[](https://github.com/itk-dev/openid-connect-bundle/blob/master/LICENSE.md)
[](https://packagist.org/packages/itk-dev/openid-connect-bundle/stats)
Symfony bundle for authorization via OpenID Connect.
> [!NOTE]
> ### Symfony Native OIDC Support
>
> Since this bundle was created Symfony has added [support for OpenID Connect](https://symfony.com/blog/new-in-symfony-6-3-openid-connect-token-handler)
> as documented in ["Using OpenID Connect (OIDC)"](https://symfony.com/doc/current/security/access_token.html#using-openid-connect-oidc)
>
> As of Symfony 7.2 (jan. 2025) it seems this is still a work in progress:
> * [OIDC discovery](https://github.com/symfony/symfony/pull/54932) is not yet implemented making config a bit cumbersome.
> * It's not obvious how to implement support for multiple providers, although it may be possible using [Multiple Authenticators](https://symfony.com/doc/current/security/> entry_point.html#multiple-authenticators-with-separate-entry-points)
>
> Until these issues are resolved this bundle cannot be fully replaced by the native features.
## Installation
To install run
```shell
composer require itk-dev/openid-connect-bundle
```
## Usage
Before being able to use the bundle, you must have your own User entity and
database setup.
Once you have this, you need to
* Configure variables for OpenId Connect
* Create an Authenticator class that extends the bundle authenticator,
`OpenIdLoginAuthenticator`
* Configure `LoginTokenAuthenticator` in order to use CLI login.
### Variable configuration
In `/config/packages/` you need the following `itkdev_openid_connect.yaml` file
for configuring OpenId Connect variables
```yaml
itkdev_openid_connect:
cache_options:
cache_pool: 'cache.app' # Cache item pool for caching discovery document and CLI login tokens
cli_login_options:
route: '%env(string:OIDC_CLI_LOGIN_ROUTE)%' # Redirect route for CLI login
user_provider: ~ #
openid_providers:
# Define one or more providers
# [providerKey]:
# options:
# metadata_url: …
# …
admin:
options:
metadata_url: '%env(string:ADMIN_OIDC_METADATA_URL)%'
client_id: '%env(string:ADMIN_OIDC_CLIENT_ID)%'
client_secret: '%env(string:ADMIN_OIDC_CLIENT_SECRET)%'
# Specify redirect URI
redirect_uri: '%env(string:ADMIN_OIDC_REDIRECT_URI)%'
# Optional: Specify leeway (seconds) to account for clock skew between provider and hosting
# Defaults to 10
leeway: '%env(int:ADMIN_OIDC_LEEWAY)%'
# Optional: Allow (non-secure) http requests (used for mocking a IdP). NOT RECOMMENDED FOR PRODUCTION.
# Defaults to false
allow_http: '%env(bool:ADMIN_OIDC_ALLOW_HTTP)%'
user:
options:
metadata_url: '%env(string:USER_OIDC_METADATA_URL)%'
client_id: '%env(string:USER_OIDC_CLIENT_ID)%'
client_secret: '%env(string:USER_OIDC_CLIENT_SECRET)%'
# As an alternative to using (a more or less) hardcoded redirect uri,
# a Symfony route can be used as redirect URI
redirect_route: 'default'
# Define any params for the redirect_route
# redirect_route_parameters: { type: user }
```
With the following `.env` environment variables
```text
###> itk-dev/openid-connect-bundle ###
# "admin" open id connect configuration variables (values provided by the OIDC IdP)
ADMIN_OIDC_METADATA_URL=ADMIN_APP_METADATA_URL
ADMIN_OIDC_CLIENT_ID=ADMIN_APP_CLIENT_ID
ADMIN_OIDC_CLIENT_SECRET=ADMIN_APP_CLIENT_SECRET
ADMIN_OIDC_REDIRECT_URI=ADMIN_APP_REDIRECT_URI
ADMIN_OIDC_LEEWAY=30
ADMIN_OIDC_ALLOW_HTTP=false
# "user" open id connect configuration variables
USER_OIDC_METADATA_URL=USER_APP_METADATA_URL
USER_OIDC_CLIENT_ID=USER_APP_CLIENT_ID
USER_OIDC_CLIENT_SECRET=USER_APP_CLIENT_SECRET
# cli redirect url
OIDC_CLI_LOGIN_ROUTE=OIDC_CLI_LOGIN_ROUTE
###< itk-dev/openid-connect-bundle ###
```
Set the actual values your `env.local` file to ensure they are not committed to Git.
In `/config/routes/` you need a similar `itkdev_openid_connect.yaml` file for
configuring the routing
```yaml
itkdev_openid_connect:
resource: "@ItkDevOpenIdConnectBundle/src/Resources/config/routes.yaml"
prefix: "/openidconnect" # Prefix for bundle routes
```
It is not necessary to add a prefix to the bundle routes, but in case you want
i.e. another `/login` route, it makes distinguishing between them easier.
When invoking the login controller action (route `itkdev_openid_connect_login`)
the key of a provider must be set in the `provider` parameter, e.g.
```twig
{{ 'Sign in'|trans }}
```
```php
$router->generate('itkdev_openid_connect_login', ['provider => 'user']);
```
Make sure to allow anonymous access to the login controller route, i.e.
something along the lines of
```yaml
# config/packages/security.yaml
security:
# …
access_control:
# …
- { path: ^/openidconnect/login(/.+)?$, role: IS_AUTHENTICATED_ANONYMOUSLY }
```
### CLI login
In order to use the CLI login feature the following environment variable must be
set in order for Symfony to be able to generate URLs in commands:
```shell
DEFAULT_URI=
```
See [Symfony documentation: Generating URLs in Commands](https://symfony.com/doc/current/routing.html#generating-urls-in-commands)
for more information.
You must also add the bundles `CliLoginTokenAuthenticator` to the `security.yaml`
file:
```yaml
security:
firewalls:
main:
custom_authenticators:
- ItkDev\OpenIdConnectBundle\Security\CliLoginTokenAuthenticator
```
Finally, configure the Symfony route to use for login links: `cli_login_options:
route`. If yoy have multiple firewalls that are active for different url patterns
you need to make sure you add `LoginTokenAuthenticator` to the firewall active
for the route specified here.
### Creating the Authenticator
The bundle can help you get the claims received from the authorizer – the only
functions that need to be implemented are `authenticate()`,
`onAuthenticationSuccess()` and `start()`.
```php
validateClaims($request);
// Authentication success
// TODO: Implement authenticate() method.
} catch (ItkOpenIdConnectException $exception) {
// Authentication failed
throw new CustomUserMessageAuthenticationException($exception->getMessage());
}
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
// TODO: Implement onAuthenticationSuccess() method.
}
public function start(Request $request, AuthenticationException $authException = null)
{
// TODO: Implement start() method.
}
}
```
See below for [a full authenticator example](#example-authenticator-functions).
Make sure to add your authenticator to the `security.yaml` file - and if you
have more than one to add an entry point.
```yaml
security:
firewalls:
main:
custom_authenticators:
- App\Security\ExampleAuthenticator
- ItkDev\OpenIdConnectBundle\Security\LoginTokenAuthenticator
entry_point: App\Security\ExampleAuthenticator
```
#### Example authenticator functions
Here is an example using a `User` with a name and email property. First we
extract data from the claims, then check if this user already exists and finally
update/create it based on whether it existed or not.
```php
validateClaims($request);
// Extract properties from claims
$name = $claims['name'];
$email = $claims['upn'];
// Check if user exists already - if not create a user
$user = $this->entityManager->getRepository(User::class)
->findOneBy(['email'=> $email]);
if (null === $user) {
// Create the new user and persist it
$user = new User();
$this->entityManager->persist($user);
}
// Update/set user properties
$user->setName($name);
$user->setEmail($email);
$this->entityManager->flush();
return new SelfValidatingPassport(new UserBadge($user->getUserIdentifier()));
} catch (ItkOpenIdConnectException|InvalidProviderException $exception) {
throw new CustomUserMessageAuthenticationException($exception->getMessage());
}
}
/** @inheritDoc */
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return new RedirectResponse($this->router->generate('homepage_authenticated'));
}
/** @inheritDoc */
public function start(Request $request, AuthenticationException $authException = null): Response
{
return new RedirectResponse($this->router->generate('itkdev_openid_connect_login', [
'provider' => 'user',
]));
}
}
```
## Sign in from command line
Rather than signing in via OpenId Connect, you can get a sign in url from the
command line by providing a username. Make sure to configure
`OIDC_CLI_REDIRECT_URL`. Run
```shell
bin/console itk-dev:openid-connect:login
```
or
```shell
bin/console itk-dev:openid-connect:login --help
```
for details.
Be aware that a login token only can be used once before it is removed, and if
you used email as your user provider property the email goes into the `username`
argument.
## Development Setup
A [`docker-compose.yml`](docker-compose.yml) file with a PHP 8.1 image is
included in this project. To install the dependencies you can run
```shell
docker compose up -d
docker compose exec phpfpm composer install
```
### Unit Testing
A PhpUnit setup is included in this library. To run the unit tests:
```shell
docker compose exec phpfpm composer install
docker compose exec phpfpm ./vendor/bin/phpunit
```
### Psalm static analysis
We’re using [Psalm](https://psalm.dev/) for static analysis. To run psalm do
```shell
docker compose exec phpfpm composer install
docker compose exec phpfpm ./vendor/bin/psalm
```
### Check Coding Standard
The following command let you test that the code follows the coding standard for
the project.
* PHP files (PHP-CS-Fixer)
```shell
docker compose exec phpfpm composer coding-standards-check
```
* Markdown files (markdownlint standard rules)
```shell
docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app node:18 yarn install
docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app node:18 yarn coding-standards-check
```
### Apply Coding Standards
To attempt to automatically fix coding style
* PHP files (PHP-CS-Fixer)
```sh
docker compose exec phpfpm composer coding-standards-apply
```
* Markdown files (markdownlint standard rules)
```shell
docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app node:18 yarn install
docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app node:18 yarn coding-standards-apply
```
## CI
GitHub Actions are used to run the test suite and code style checks on all PRs.
If you wish to test against the jobs locally you can install
[act](https://github.com/nektos/act). Then do:
```shell
act -P ubuntu-latest=shivammathur/node:latest pull_request
```
## Versioning
We use [SemVer](http://semver.org/) for versioning. For the versions available,
see the [tags on this
repository](https://github.com/itk-dev/openid-connect/tags).
## License
This project is licensed under the MIT License - see the
[LICENSE.md](LICENSE.md) file for details