Persisting user with SAML connection in Symfony

105 Views Asked by At

Before jumping into the problem, a little of context :

My project is in Symfony 6 and I use SAML to authenticate and fetch some properties about users. I use the bundle nbgrp/onelogin-saml-bundle for the SAML part.

I followed the configuration mentionned in the Gitlab and the authentication works fine but I struggle with the persistence of the user. The user is stored in the database but when I log out and log in again with the same user, I get a sweet error message for integrity constraint violation as the user already exist in the database (which is normal).

How to manage that when a user already exists, it doesn't try to create it again in the database ?

here is my security.yaml

providers:
    # used to reload user from session & other features (e.g. switch_user)
    #app_user_provider:
    #    entity:
    #        class: App\Entity\User
    #        property: FullName
    saml_provider:
        ##  Basic provider instantiates a user with identifier and default roles
        saml:
            user_class: 'App\Entity\User'
            default_roles: ['ROLE_USER']
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        lazy: true
        pattern: ^/
        saml:
            ##  Match SAML attribute 'uid' with user identifier.
            ##  Otherwise, used \OneLogin\Saml2\Auth::getNameId() method by default.
            identifier_attribute: uid
            ##  Use the attribute's friendlyName instead of the name.
            use_attribute_friendly_name: true
            check_path: saml_acs
            login_path: saml_login
            user_factory: saml_user_factory
            persist_user: true
        logout:
            path: saml_logout

and my services.yaml

services:
saml_user_factory:
    class: Nbgrp\OneloginSamlBundle\Security\User\SamlUserFactory
    arguments:
        ##  User class
        - App\Entity\User
        ##  Attribute mapping
        - password: 'notused'
         
          FullName: $cn
          
          roles: ['ROLE_USER']

and the user entity if needed

<?php

namespace App\Entity;

use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Nbgrp\OneloginSamlBundle\Security\User\SamlUserInterface;

#[ORM\Entity(repositoryClass: UserRepository::class)]
class User implements UserInterface, SamlUserInterface
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 180, unique: true)]
    private ?string $FullName = null;

    #[ORM\Column]
    private array $roles = [];

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getFullName(): ?string
    {
        return $this->FullName;
    }

    public function setFullName(string $FullName): static
    {
        $this->FullName = $FullName;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUserIdentifier(): string
    {
        return (string) $this->FullName;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): static
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials(): void
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    public function setSamlAttributes(array $attributes): void
    {
        $this->FullName = $attributes['cn'][0];
    }
}
0

There are 0 best solutions below