Migrate FOS-User to Keycloak SSO

FOS User Bundle died

FOS USer bundle is not supported any more, but worked until Symfony 4.4.11. If you want to upgrade you need to change the FOS-User Library or implment the Security by yourself.

Why Keycloak

Keycloak makes it easy to manage Users over several Applications and grant access to each of your own application.

Read More about Keycloak

With KEycloak you can als integrate social Login like Facebook, Goolge or Github as an Identity Provider.

How to implment

  1. We want to take all our User we managed with FOS and try to connect them with the new SSO Service
  2. We want to use the internal Symfony Security Bundle to manage local Application Users
  3. We want to authenticate with a guard the given firewalls

1. Remove FOS-User Bundle

First remove all Stuff from FOS-User from your composer.json.

Remove the fos_user from configuration and from the routing.

Look in the services.yaml, if there is something from the FOS-User Bundle.

Remove everything that is from FOS-User from the security.yaml

#config/packages/security.yaml
security:
    encoders:
        FOS\UserBundle\Model\UserInterface: bcrypt

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email 

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            pattern: ^/
            #remove from here
            form_login:
                provider: fos_userbundle
                csrf_token_generator: security.csrf.token_manager
                check_path: fos_user_security_check
                login_path: fos_user_security_login
            logout:
                path: fos_user_security_logout
            remember_me:
                secret:   '%kernel.secret%'
                lifetime: 86400 # 1 day in seconds
                path:     /
                always_remember_me: true
            #remove to here

If you don`t do so, you could get later when compose trys to clean the cache. run

composer update

to remove FOS-User-Bundle correct.

2. Install KNP-OAUTH2 Bundle and Keycloak Extension

We will use:

https://github.com/knpuniversity/oauth2-client-bundle

and

https://github.com/stevenmaguire/oauth2-keycloak

composer require knpuniversity/oauth2-client-bundle stevenmaguire/oauth2-keycloak 

Hopefully this will install without error. If there are errors, please fix it by removing the FOS-User Parts.

3. Generate new Config Files

Composer will add some new config files with the reciept.

Configuration file to tell the boundle to use keycloak

#config/packages/knpu_oauth2_client.yaml
knpu_oauth2_client:
    clients:
        keycloak_main:
            # must be "keycloak" - it activates that type!
            type: keycloak
            # add and set these environment variables in your .env files
            client_id: '%env(OAUTH_KEYCLOAK_CLIENT_ID)%'
            client_secret: '%env(OAUTH_KEYCLOAK_CLIENT_SECRET)%'
            # a route name you'll create
            redirect_route: connect_keycloak_check
            redirect_params: {}
            # Keycloak server URL
            auth_server_url: '%env(OAUTH_KEYCLOAK_SERVER)%'
            # Keycloak realm
            realm: '%env(OAUTH_KEYCLOAK_REALM)%'
            # Optional: Encryption algorith, i.e. RS256
            # encryption_algorithm: null
            # Optional: Encryption key path, i.e. ../key.pem
            # encryption_key_path: null
            # Optional: Encryption key, i.e. contents of key or certificate
            # encryption_key: null
            # whether to check OAuth2 "state": defaults to true
            # use_state: true

New security.yaml we see what the different parts are later

#config/packages/security.yaml
security:
    encoders:
        App\Entity\User:
            algorithm: auto

    role_hierarchy:
        ROLE_SUPER_ADMIN: ROLE_ADMIN
        ROLE_ADMIN:       [ROLE_ALLOWED_TO_SWITCH]

    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
    providers:
        # used to reload user from session & other features (e.g. switch_user)
        users:
            entity:
                class: App\Entity\User
                property: keycloakId

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            pattern: ^/
            anonymous:    true
            switch_user: true
            logout:
                path:   app_logout
                target: logout_keycloak
            guard:
                authenticators:
                #here we connect our guard to protect the firewall
                    - App\Security\GuardServiceKeycloak

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
        - { path: /backend/, role: ROLE_ADMIN }
        - { path: /login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: /no_team$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: /resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: /cron/, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: /client/, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: /register, role: ROLE_ADMIN }
        - { path: /, role: ROLE_USER }

The route to logout

#config/routes.yaml
...
app_logout:
  path: /login/logout
  methods: GET

Set some parameters we later need in the application

#config/services.yaml
...
parameters:
    KEYCLOAK_URL: '%env(OAUTH_KEYCLOAK_SERVER)%'
    KEYCLOAK_REALM: '%env(OAUTH_KEYCLOAK_REALM)%'
    KEYCLOAK_SECRETE: '%env(OAUTH_KEYCLOAK_CLIENT_SECRET)%'
    KEYCLOAK_ID: '%env(OAUTH_KEYCLOAK_CLIENT_ID)%'

Some new Env-Variables in your .env file You need to set them in your .env.local to the correct values. These values you should get from your Admin.

Important: the URL ist the https://domain/auth

#.env
###> oauth-bundle ###
OAUTH_KEYCLOAK_CLIENT_ID=addHere
OAUTH_KEYCLOAK_CLIENT_SECRET=addHere
OAUTH_KEYCLOAK_SERVER=addHere/auth
OAUTH_KEYCLOAK_REALM=addHere
###< oauth-bundle ###