Git Product home page Git Product logo

oneloginsamlbundle's Introduction

OneloginSamlBundle

OneLogin SAML Bundle for Symfony. (https://github.com/onelogin/php-saml)

Latest Stable Version Latest Unstable Version Total Downloads License

Build Status Coverage Status

SensioLabsInsight

"Buy Me A Coffee"

Installation

Install with composer

"require": {
    "hslavich/oneloginsaml-bundle": "^2.0"
}

Using of dev-master version deprecated, use a specific version instead (i.e. 2.0).
In the future master branch will be removed (approximately in the fall '21).

Run composer update

composer update hslavich/oneloginsaml-bundle

Enable the bundle in app/AppKernel.php

$bundles = array(
    // ...
    new Hslavich\OneloginSamlBundle\HslavichOneloginSamlBundle(),
)

Configuration

Configure SAML metadata in app/config/config.yml. Check https://github.com/onelogin/php-saml#settings for more info.

hslavich_onelogin_saml:
    # Basic settings
    idp:
        entityId: 'http://id.example.com/saml2/idp/metadata.php'
        singleSignOnService:
            url: 'http://id.example.com/saml2/idp/SSOService.php'
            binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
        singleLogoutService:
            url: 'http://id.example.com/saml2/idp/SingleLogoutService.php'
            binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
        x509cert: ''
    sp:
        entityId: 'http://myapp.com/app_dev.php/saml/metadata'
        assertionConsumerService:
            url: 'http://myapp.com/app_dev.php/saml/acs'
            binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
        singleLogoutService:
            url: 'http://myapp.com/app_dev.php/saml/logout'
            binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
        privateKey: ''    
    # Optional settings
    baseurl: 'http://myapp.com'
    strict: true
    debug: true    
    security:
        nameIdEncrypted:       false
        authnRequestsSigned:   false
        logoutRequestSigned:   false
        logoutResponseSigned:  false
        wantMessagesSigned:    false
        wantAssertionsSigned:  false
        wantNameIdEncrypted:   false
        requestedAuthnContext: true
        signMetadata: false
        wantXMLValidation: true
        signatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
        digestAlgorithm: 'http://www.w3.org/2001/04/xmlenc#sha256'
    contactPerson:
        technical:
            givenName: 'Tech User'
            emailAddress: '[email protected]'
        support:
            givenName: 'Support User'
            emailAddress: '[email protected]'
    organization:
        en:
            name: 'Example'
            displayname: 'Example'
            url: 'http://example.com'

If you don't want to set contactPerson or organization, don't add those parameters instead of leaving them blank.

Configure firewall and user provider in app/config/security.yml

security:
    # ...

    providers:
        saml_provider:
            # Basic provider instantiates a user with default roles
            saml:
                user_class: 'AppBundle\Entity\User'
                default_roles: ['ROLE_USER']

    firewalls:
        app:
            pattern:    ^/
            saml:
                # Match SAML attribute 'uid' with username.
                # Uses getNameId() method by default.
                username_attribute: uid
                # Use the attribute's friendlyName instead of the name 
                use_attribute_friendly_name: true
                check_path: saml_acs
                login_path: saml_login
            logout:
                path: saml_logout

    access_control:
        - { path: ^/saml/login, roles: PUBLIC_ACCESS }
        - { path: ^/saml/metadata, roles: PUBLIC_ACCESS }
        - { path: ^/, roles: ROLE_USER }

Edit your app/config/routing or app/config/routes.yaml depending on your Symfony version.

hslavich_saml_sp:
    resource: "@HslavichOneloginSamlBundle/Resources/config/routing.yml"

Inject SAML attributes into User object (Optional)

Your user class must implement SamlUserInterface

<?php

namespace AppBundle\Entity;

use Hslavich\OneloginSamlBundle\Security\User\SamlUserInterface;

class User implements SamlUserInterface
{
    protected $username;
    protected $email;

    // ...

    public function setSamlAttributes(array $attributes)
    {
        $this->email = $attributes['mail'][0];
    }
}

Then you can get attributes from user object

$email = $this->getUser()->getEmail();

Integration with classic login form

You can integrate SAML authentication with traditional login form by editing your security.yml:

security:
    enable_authenticator_manager: true

    providers:
        user_provider:
            # Loads user from user repository
            entity:
                class: AppBundle:User
                property: username

    firewalls:
        default:
            saml:
                username_attribute: uid
                check_path: saml_acs
                login_path: saml_login
                failure_path: saml_login
                always_use_default_target_path: true

            # Traditional login form
            form_login:
                login_path: /login
                check_path: /login_check
                always_use_default_target_path: true

            logout:
                path: saml_logout

Then you can add a link to route saml_login in your login page in order to start SAML sign on.

    <a href="{{ path('saml_login') }}">SAML Login</a>

Just-in-time user provisioning (optional)

It's possible to have a new user provisioned based off the received SAML attributes when the user provider cannot find a user.

Edit firewall settings in security.yml:

security:
    # ...

    providers:
        saml_provider:
            # Loads user from user repository
            entity:
                class: AppBundle\Entity\User
                property: username

    firewalls:
        enable_authenticator_manager: true
    
        default:
            provider: saml_provider
            saml:
                username_attribute: uid
                # User factory service
                user_factory: my_user_factory
                # Persist new user. Doctrine is required.
                persist_user: true
            logout:
            path: saml_logout

In order for the user to be persisted, you must use a user provider that throws UsernameNotFoundException (e.g. EntityUserProvider as used in the example above). The SamlUserProvider does not throw this exception which will cause an empty user to be returned when a matching user cannot be found.

Create the user factory service editing services.yml:

services:
    my_user_factory:
        class: Hslavich\OneloginSamlBundle\Security\User\SamlUserFactory
        arguments:
            # User class
            - AppBundle\Entity\User
            # Attribute mapping.
            - password: 'notused'
              email: $mail
              name: $cn
              lastname: $sn
              roles: ['ROLE_USER']

Fields with '$' references to SAML attribute value.

Or you can create your own User Factory that implements SamlUserFactoryInterface

<?php

namespace AppBundle\Security;

use AppBundle\Entity\User;
use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlTokenInterface;
use Hslavich\OneloginSamlBundle\Security\User\SamlUserFactoryInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class UserFactory implements SamlUserFactoryInterface
{
    public function createUser(SamlTokenInterface $token): UserInterface
    {
        $attributes = $token->getAttributes();
        $user = new User();
        $user->setRoles(['ROLE_USER']);
        $user->setUsername($token->getUsername());
        $user->setPassword('notused');
        $user->setEmail($attributes['mail'][0]);
        $user->setName($attributes['cn'][0]);

        return $user;
    }
}
services:
    my_user_factory:
        class: AppBundle\Security\UserFactory

oneloginsamlbundle's People

Contributors

a-menshchikov avatar cdaguerre avatar crbanman avatar dyachenko avatar gordon81 avatar hslavich avatar htuscher avatar iainmckay avatar jaburjak avatar jfwiebe avatar johnstoncode avatar kevinpapst avatar lctrs avatar livda avatar lorenzoprod avatar mbrowniebytes avatar olegdm-tr avatar pdf-pangebault avatar pitbulk avatar piterssson avatar ppatrik avatar preovaleo avatar samnela avatar samuel-queniart avatar szabogyula avatar tarjei avatar tlesne avatar vincentclair avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.