2017 © Pedro Peláez
 

symfony-bundle sso-idp-bundle

Single-sign-on bundle for Symfony2. Identity Provider part.

image

korotovsky/sso-idp-bundle

Single-sign-on bundle for Symfony2. Identity Provider part.

  • Tuesday, May 15, 2018
  • by korotovsky
  • Repository
  • 8 Watchers
  • 38 Stars
  • 8,418 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 14 Forks
  • 3 Open issues
  • 13 Versions
  • 28 % Grown

The README.md

Single Sign On Identity Provider

Build Status Scrutinizer Code Quality Code Coverage SensioLabsInsight, (*1)

Disclaimer

I am by no means a security expert. I'm not bad at it either, but I cannot vouch for the security of this bundle. You can use this in production if you want, but please do so at your own risk. That said, if you'd like to contribute to make this bundle better/safer, you can always create an issue or send a pull request., (*2)

Description

This bundle provides an easy way to integrate a single-sign-on in your website. It uses an existing ('main') firewall for the actual authentication, and redirects all configured SSO-routes to authenticate via a one-time-password., (*3)

Installation

Installation is a 10 steps process:, (*4)

  1. Download SingleSignOnIdentityProviderBundle using composer
  2. Enable the bundle
  3. Create service provider(s)
  4. Configure SingleSignOnIdentityProviderBundle
  5. Enable the route to validate OTP
  6. Modify security settings
  7. Add / Modify login and logout success handlers
  8. Create OTP route
  9. Add redirect path to login form
  10. Update database schema

Step 1: Download SingleSignOnIdentityProviderBundle using composer

Tell composer to require the package:, (*5)

``` bash composer require korotovsky/sso-idp-bundle, (*6)


Composer will install the bundle to your project's `vendor/korotovsky` directory. ### Step 2: Enable the bundle ``` php

Step 3: Create service provider(s)

You have to create a ServiceProvider for each application that uses the SSO SP bundle., (*7)

Each ServiceProvider must implement Krtv\Bundle\SingleSignOnIdentityProviderBundle\Manager\ServiceProviderInterface., (*8)

``` php , (*9)


``` php

And define them as services., (*10)

``` yaml, (*11)

app/config/services.yml

services: acme_bundle.sso.consumer1: class: AcmeBundle\ServiceProviders\Consumer1 tags: - { name: sso.service_provider, service: consumer1 }, (*12)

acme_bundle.sso.consumer2:
    class: AcmeBundle\ServiceProviders\Consumer2
    tags:
        - { name: sso.service_provider, service: consumer2 }

### Step 4: Configure SingleSignOnIdentityProviderBundle The bundle relies on an existing firewall to provide the actual authentication. To do this, you have to configure the single-sign-on login path to be behind that firewall, and make sure you need to be authenticated to access that route. Add the following settings to your **config.yml**. ``` yaml # app/config/config.yml: krtv_single_sign_on_identity_provider: host: idp.example.com host_scheme: http login_path: /sso/login/ logout_path: /sso/logout services: - consumer1 - consumer2 otp_parameter: _otp secret_parameter: secret

Step 5: Enable route to validate OTP

``` yaml, (*13)

app/config/routing.yml

sso: resource: . type: sso, (*14)


### Step 6: Modify security settings ``` yaml # app/config/security.yml security: access_control: # We need to allow users to access the /sso/login route # without being logged in - { path: ^/sso/login, role: IS_AUTHENTICATED_ANONYMOUSLY }

Step 7: Add / Modify login and logout success handlers

Modify your existing constructor for login and logout success handlers to include the following service:, (*15)

sso_identity_provider.otp_manager

In your method used as for the succes handler, add near the end a call to the method clear() of that service., (*16)

In case you don't have a success handler for either login or logout, here's a sample implementation for it:, (*17)

``` php serviceManager = $serviceManager; $this->uriSigner = $uriSigner; $this->session = $session; $this->router = $router; } /** * @param Request $request * @param TokenInterface $token * * @return RedirectResponse */ public function onAuthenticationSuccess(Request $request, TokenInterface $token) { $redirectUrl = $this->session->get('_security.main.target_path', '/'); if ($request->query->has('_target_path')) { if ($this->uriSigner->check($request->query->get('_target_path'))) { $redirectUrl = $request->query->get('_target_path'); } } if (strpos($redirectUrl, '/sso/login') === false) { $targetService = $this->serviceManager->getSessionService(); if ($targetService != null) { $redirectUrl = $this->getSsoWrappedUrl($token, $targetService, $redirectUrl); } else { $redirectUrl = $this->router->generate('_passport_dashboard_index'); } } $this->serviceManager->clear(); if ($request->isXmlHttpRequest()) { return new JsonResponse([ 'status' => true, 'location' => $redirectUrl, ]); } return new RedirectResponse($redirectUrl); } /** * @param TokenInterface $token * @param string $targetService * @param string $redirectUrl * * @return string */ protected function getSsoWrappedUrl(TokenInterface $token, $targetService, $redirectUrl) { /** @var $serviceManager ServiceProviderInterface */ $serviceManager = $this->serviceManager->getServiceManager($targetService); $owner = $token->getUser(); $wrappedSsoUrl = $this->router->generate('sso_login_path', [ '_target_path' => $serviceManager->getOTPValidationUrl([ '_target_path' => $redirectUrl, ]), 'service' => $targetService, ], Router::ABSOLUTE_URL); return $this->uriSigner->sign($wrappedSsoUrl); } } ?>, (*18)


``` php serviceManager = $serviceManager; $this->uriSigner = $uriSigner; $this->session = $session; $this->router = $router; } /** * Logout success handler * * @param Request $request * * @return RedirectResponse|JsonResponse */ public function onLogoutSuccess(Request $request) { $redirectUrl = $this->session->get('_security.main.target_path', '/'); if ($request->query->has('_target_path')) { if ($this->uriSigner->check($request->query->get('_target_path'))) { $redirectUrl = $request->query->get('_target_path'); } } $this->serviceManager->clear(); if ($request->isXmlHttpRequest()) { return new JsonResponse([ 'status' => true, 'location' => $redirectUrl, ]); } return new RedirectResponse($redirectUrl); } } ?>

Define them as services, (*19)

``` yaml, (*20)

app/config/services.yml

services: acme_bundle.security.login_success_handler: class: AcmeBundle\Handler\LoginSuccessHandler arguments: - "@sso_identity_provider.service_manager" - "@sso_identity_provider.uri_signer" - "@session" - "@router", (*21)

acme_bundle.security.logout_success_handler:
    class: AcmeBundle\Handler\LogoutSuccessHandler
    arguments:
        - "@sso_identity_provider.service_manager"
        - "@sso_identity_provider.uri_signer"
        - "@session"
        - "@router"

And then finally, set the services as handlers in your firewall definition ``` yaml # app/config/security.yml security: firewall: main: # ... form_login: # ... success_handler: acme_bundle.security.login_success_handler logout: # ... success_handler: acme_bundle.security.logout_success_handler

Step 8: Create OTP route

In order to validate the OTP and authenticate the user, you must create a route that can retrieve the OTP details from the database and that can verify if it is valid., (*22)

The route path doesn't really matter, but take note of it. It will be used in the SP bundle. In our example, the route is /internal/v1/sso., (*23)

``` php get('sso_identity_provider.otp_manager'); $pass = str_replace(' ', '+', $request->query->get('_otp')); /** @var \Krtv\SingleSignOn\Model\OneTimePasswordInterface */ $otp = $otpManager->get($pass); if (!($otp instanceof OneTimePassword) || $otp->getUsed() === true) { throw new BadRequestHttpException('Invalid OTP password'); } $response = [ 'data' => [ 'created_at' => $otp->getCreated()->format('r'), 'hash' => $otp->getHash(), 'password' => $otp->getPassword(), 'is_used' => $otp->getUsed(), ], ]; $otpManager->invalidate($otp); return new JsonResponse($response); } } ?>, (*24)


### Step 9: Add redirect path to login form In your login form, add a hidden input with the name `_target_path` and the value `{{ app.session.get('_security.main.target_path') }}` like so: ``` twig <input type="hidden" name="_target_path" value="{{ app.session.get('_security.main.target_path') }}" />

This will be used to redirect the user after login to the OTP validation route., (*25)

Step 10: Update database schema

To be able to store the OTPs, you must run the command:, (*26)

bash php bin/console doctrine:schema:update --force, (*27)

Public API of this bundle

This bundle registers several services into service container. These services will help you customize SSO flow in the your application:, (*28)

That's it for Identity Provider. Now you can continue configure ServiceProvider part, (*29)

The Versions

15/05 2018

0.3.x-dev

0.3.9999999.9999999-dev

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

15/05 2018

0.3.3

0.3.3.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

07/06 2017

0.3.2

0.3.2.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

24/06 2016

0.3.1

0.3.1.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

11/12 2015

0.3.0

0.3.0.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

03/08 2015

0.2.x-dev

0.2.9999999.9999999-dev

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

03/08 2015

0.2.3

0.2.3.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

27/04 2015

0.1.x-dev

0.1.9999999.9999999-dev

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

28/01 2015

0.2.2

0.2.2.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

12/12 2014

0.2.1

0.2.1.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

12/12 2014

0.1.1

0.1.1.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

08/12 2014

0.2.0

0.2.0.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Dmitry Korotovsky

login sso otp single-sign-on

24/11 2014

0.1.0

0.1.0.0

Single-sign-on bundle for Symfony2. Identity Provider part.

  Sources   Download

MIT

The Requires

 

by Dmitry Korotovsky

login sso otp single-sign-on