korotovsky / SingleSignOnServiceProviderBundle

Single Sign On bundle for Symfony2 projects. SP part.
MIT License
33 stars 18 forks source link

Further explanation on managers service id #3

Open timothyjeffcoat opened 8 years ago

timothyjeffcoat commented 8 years ago

Please forgive my ignorance. Could you please explain acme_bundle.your_own_fetch_service.id and acme_bundle.guzzle_service.id some more?

In regards to the following portion in the config.yml:

managers:
        http:
            provider:    service # Active provider for HTTP OTP manager
            providers:           # Available HTTP providers
                service:
                    id: acme_bundle.your_own_fetch_service.id

                guzzle:
                    client:   acme_bundle.guzzle_service.id
                    resource: http://idp.example.com/internal/v1/sso

I currently have the Identity Provider running. But am unable to run the service provider application

I get the following exception when trying to run the service provider server:

You have requested a non-existent service "acme_bundle.your_own_fetch_service.id".

The problem is I don't know how to implement the required service or understand what the code should be.

Your assistance is much appreciated.

korotovsky commented 8 years ago

Hey @timothyjeffcoat,

The service id acme_bundle.your_own_fetch_service.id should be implemented in the following way: you have to create a class, that will implement this interface: https://github.com/korotovsky/SingleSignOnLibrary/blob/0.3.x/src/Krtv/SingleSignOn/Manager/Http/Provider/ProviderInterface.php. This service have to return https://github.com/korotovsky/SingleSignOnLibrary/blob/0.3.x/src/Krtv/SingleSignOn/Model/OneTimePasswordInterface.php instance or null.

You could also use this https://github.com/korotovsky/SingleSignOnLibrary/blob/0.3.x/src/Krtv/SingleSignOn/Manager/Http/Provider/Guzzle/OneTimePasswordProvider.php built-in provider that already using guzzle library for HTTP requests. In this case you have to use this example of yml config:

                guzzle:
                    client:   acme_bundle.guzzle_service.id
                    resource: http://idp.example.com/internal/v1/sso

Where acme_bundle.guzzle_service.id is guzzle as a backend service. So in another words it should be simply guzzle http client instance.

All service ids above are just examples, and could have different names. So It's just a services in Dependency Injection container.

timothyjeffcoat commented 8 years ago

Thank you! I will work on that.

olotintemitope commented 8 years ago

Hi @korotovsky, While implementing the Service Provider part. I was welcomed with this error message. Can you please help me out.

  The service "security.authentication.provider.krtv_single_sign_on_service_provider.ma
  in" has a dependency on a non-existent service "security.user.provider.concrete.main"
  .
marvoh commented 7 years ago

I am experiencing the same issue

korotovsky commented 7 years ago

@marvoh Please, check that you have a firewall with key main

marvoh commented 7 years ago

I do have it

korotovsky commented 7 years ago

Please, could you provide full configuration of your app on gist?

marvoh commented 7 years ago

My website integrates with a different platform so I want people to access the other platform through SSO having registered on my website.

Will adding the sso key under the main interfere with my original registration and login process? On my website they just authenticate normally with username / password.

Here's my security.yml

`# To get started with security, check out the documentation:

http://symfony.com/doc/current/security.html

security:

encoders:
    FOS\UserBundle\Model\UserInterface: sha512

acl:
    connection: default

role_hierarchy:
    ROLE_ADMIN:       [ROLE_USER, ROLE_SONATA_ADMIN]
    ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
    SONATA:
        - ROLE_SONATA_PAGE_ADMIN_PAGE_EDIT  # if you are using acl then this line must be commented

providers:
    fos_userbundle:
        id: fos_user.user_manager

    db_provider:
        entity:
            class: Application\Sonata\UserBundle\Entity\User
            property: username

firewalls:
    # disables authentication for assets and the profiler, adapt it according to your needs
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    admin:
        pattern:            /admin(.*)
        context:            user
        form_login:
            provider:       fos_userbundle
            login_path:     /admin/login
            use_forward:    false
            check_path:     /admin/login_check
            failure_path:   null
        logout:
            path:           /admin/logout
            target:         /admin/login
        anonymous:          true
        switch_user: true

    main:
        pattern:             .*
        context:             user
        form_login:
            provider:       fos_userbundle
            login_path:     /login
            use_forward:    false
            check_path:     /login_check
            failure_path:   null
            always_use_default_target_path: false
            default_target_path: /portal
        logout:
            invalidate_session: true
            path: /logout
            target: http://demo.com/sso/logout?service=consumer1
        anonymous:          true

        sso:
            require_previous_session: false
            provider:                 main
            check_path:               /otp/validate/     # Same as in app/config/routing.yml

            sso_scheme:               http               # Required
            sso_host:                 demo.com    # Required

            # sso_otp_scheme:           http               # Optional
            # sso_otp_host:             consumer1.com      # Optional

            sso_failure_path:         /login             # Can also be as an absolute path to service provider
            sso_path:                 /sso/login/        # SSO endpoint on IdP.

            # sso_service_extra:           null            # Default service extra parameters. Optional.
            # sso_service_extra_parameter: service_extra   # Parameter name. Optional

            # sso_login_required:           1              # Optional
            # sso_login_required_parameter: login_required # Optional

            sso_service:                  consumer1      # Consumer name

    # saml:
    #   pattern:
    #   context:             user
    #   form_login:
    #       provider:       fos_userbundle
    #       success_handler: app.security.login_success_handler
    #   logout:
    #     success_handler: app.security.logout_success_handler

access_control:
    # URL of FOSUserBundle which need to be available to anonymous users
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/sso/login, role: IS_AUTHENTICATED_ANONYMOUSLY }

    # Admin login page needs to be accessed without credential
    - { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }

    # Secured part of the site
    # This config requires being logged for the whole site and having the admin role for the admin part.
    # Change these rules to adapt them to your needs
    - { path: ^/admin/, role: [ROLE_ADMIN, ROLE_SONATA_ADMIN] }
    - { path: ^/portal/, role: [ROLE_USER] }
    - { path: ^/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }

`

marvoh commented 7 years ago

Give me a second

korotovsky commented 7 years ago

My website integrates with a different platform so I want people to access the other platform through SSO having registered on my website.

You should consider yo use OAuth server in this case. SSO is better to use when you have full control of your SP services

marvoh commented 7 years ago

Unfortunately the platform only supports CAS and SAML so I'm stuck with having to use that for SSO

Here's the gist

https://gist.github.com/marvoh/80dc8e56996ceef8444ae6fc6443f008

soromamadou commented 6 years ago

Hello, i got the same issue with guzzle configuration part. The service "security.authentication.provider.krtv_single_sign_on_service_provider.main" has a dependency on a non-existent service "security.user.provider.concrete.main"

Could you please send us an example of implementation of your providers ?

providers: # Available HTTP providers service: id: acme_bundle.your_own_fetch_service.id

            guzzle:
                client:   acme_bundle.guzzle_service.id
                resource: http://idp.example.com/internal/v1/sso
ywcdiao commented 5 years ago

Hello, Can you please tell me on which case is the method fetch() (in class OneTimePasswordProvider.php) called? https://github.com/korotovsky/SingleSignOnLibrary/blob/0.3.x/src/Krtv/SingleSignOn/Manager/Http/Provider/Guzzle/OneTimePasswordProvider.php

I have two projects using the SSO bundle, the configurations are exactly the same. However one is working well, the other one do not. The other one seems never call the method fetch(), I do not know why. In the login action, I added this:

if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
            throw $this->createAccessDeniedException();
        }

But it is always throwing the exception. So in the end, it has an endless loop with the uri: /otp/validate. The log is like this: [2019-02-22 03:37:15] request.INFO: Matched route "otp". {"route_parameters":{"_controller":"Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction","path":"/otp/validate/","permanent":true,"scheme":null,"httpPort":80,"httpsPort":443,"_route":"otp"},"request_uri":"http://example.local/otp/validate?_hash=pmKByF%2FyHi5LvHcriNa67bvXcIJTSMoTTJ0d1QmyFio%3D&_otp=%2B4o3lAQmYH8w9H9sobYff4zZYO2FCROd%2FRYpAfFQLu8uPOoG2DRAWbv1XI2Y3P0tOwTy2NtMwxVsU48%2BLMxyUg%3D%3D&_target_path=http%3A%2F%2Fexample.local%2Fuser%2Flogin%3FauthAll%3Dtrue"} [] [2019-02-22 03:37:15] security.INFO: Populated the TokenStorage with an anonymous Token. [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Krtv\Bundle\SingleSignOnServiceProviderBundle\EventListener\AuthenticationContextSubscriber::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\DebugHandlersListener::configure". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\ValidateRequestListener::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\SessionListener::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\FragmentListener::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\RouterListener::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\TranslatorListener::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\Security\Http\Firewall::onKernelRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.request" to listener "SunCat\MobileDetectBundle\EventListener\RequestResponseListener::handleRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.controller" to listener "MDPI\MainBundle\Listener\ControllerListener::onKernelController". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.controller" to listener "Symfony\Bundle\FrameworkBundle\DataCollector\RouterDataCollector::onKernelController". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.controller" to listener "Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::onKernelController". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\ControllerListener::onKernelController". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\ParamConverterListener::onKernelController". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener::onKernelController". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "MDPI\MainBundle\Listener\ControllerListener::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bridge\Monolog\Handler\FirePHPHandler::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "SunCat\MobileDetectBundle\EventListener\RequestResponseListener::handleResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\ResponseListener::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\Security\Http\RememberMe\ResponseListener::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\CacheListener::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\SaveSessionListener::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\StreamedResponseListener::onKernelResponse". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.finish_request" to listener "Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelFinishRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.finish_request" to listener "Symfony\Component\HttpKernel\EventListener\TranslatorListener::onKernelFinishRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.finish_request" to listener "Symfony\Component\HttpKernel\EventListener\RouterListener::onKernelFinishRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.finish_request" to listener "Symfony\Component\Security\Http\Firewall::onKernelFinishRequest". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.terminate" to listener "Symfony\Bundle\SwiftmailerBundle\EventListener\EmailSenderListener::onTerminate". [] [] [2019-02-22 03:37:15] event.DEBUG: Notified event "kernel.terminate" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelTerminate". [] [] in a loop.

@korotovsky Could you please help me? Thank you

korotovsky commented 5 years ago

Hi @ywcdiao,

The fetch() method is called by https://github.com/korotovsky/SingleSignOnLibrary/blob/0.3.x/src/Krtv/SingleSignOn/Manager/Http/OneTimePasswordManager.php#L45 it means the whole flow is running in the https://github.com/korotovsky/SingleSignOnServiceProviderBundle/blob/0.3.x/src/Krtv/Bundle/SingleSignOnServiceProviderBundle/Authentication/Provider/OneTimePasswordAuthenticationProvider.php#L90 when authentication is activated. To activate the provider you either have to throw AccessDeniedException from security package (!) that's important or forward user to protected area behind any firewall.

To avoid cyclic loops make sure that your user got sufficient roles to pass the firewall after authentication process (provider flow)

Please let me know was it helpful or now to help other users of this bundle.

ywcdiao commented 5 years ago

Hi @korotovsky ,

Thank you very much for your kind help! I figured out the problem. It failed when symfony security check the check_path: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php#L115

Because I set the check_path as '/otp/validate/'. But in browser the uri is http://example.local/otp/validate?_hash=pmKByF%2FyHi5LvHcriNa67bvXcIJTSMoTTJ0d1QmyFio%3D&_otp=%2B4o3lAQmYH8w9H9sobYff4zZYO2FCROd%2FRYpAfFQLu8uPOoG2DRAWbv1XI2Y3P0tOwTy2NtMwxVsU48%2BLMxyUg%3D%3D&_target_path=http%3A%2F%2Fexample.local%2Fuser%2Flogin%3FauthAll%3Dtrue The path was changed to '/otp/validate' automatically by the nginx config, the suffix '/' was auto trimmed. That is why the url was redirected endlessly.