Obexal Docs

Docs/Fédération/IdP SAML (SSO sortant)

SSO SAML vers vos applications (Obexal comme IdP)

Obexal émet des assertions SAML 2.0 signées vers vos applications, avec une identité de signature par organisation, une politique stricte d'ACS unique et des garanties d'e-mail vérifié.

Beaucoup de produits SaaS (et la plupart des applications d'entreprise historiques) ne parlent que SAML 2.0 pour le single sign-on. Obexal joue le rôle d'Identity Provider SAML pour votre organisation : vos utilisateurs s'authentifient une fois auprès d'Obexal, qui émet une assertion signée vers chaque application enregistrée (le Service Provider, SP). C'est le pendant sortant du SSO d'entreprise entrant, où Obexal est le SP.

L'identité de signature de votre organisation

Chaque organisation possède sa propre identité de signature SAML : une clé privée RSA-2048 et un certificat X.509 auto-signé (valable 10 ans). Elle est générée automatiquement au premier appel des métadonnées ou de l'endpoint SSO du tenant, et la clé privée est stockée chiffrée au repos (AES-256-GCM), comme les clés de signature OIDC. Le certificat est publié dans vos métadonnées IdP ; deux organisations ne partagent jamais une clé.

Les endpoints IdP

{tenant} est le slug de votre organisation. Les exemples utilisent accounts.obexal.com, le domaine par défaut ; votre domaine de connexion personnalisé le remplace si vous en avez un.

EndpointRôle
GET /saml/idp/{tenant}/metadataMétadonnées IdP (XML). L'entityID de votre IdP est cette URL
GET ou POST /saml/idp/{tenant}/ssoSSO SP-initiated (reçoit l'AuthnRequest, binding Redirect ou POST)
GET /saml/idp/{tenant}/apps/{appId}/ssoSSO IdP-initiated vers une app enregistrée (paramètre RelayState optionnel)
curl https://accounts.obexal.com/saml/idp/acme/metadata
# 200, Content-Type: application/samlmetadata+xml

La plupart des SP acceptent directement cette URL de métadonnées ; sinon, recopiez l'entityID, l'URL SSO et le certificat depuis le XML.

Enregistrer un service provider

L'enregistrement exige la permission apps:manage (session console ou jeton d'API admin obx_). Chaque SP est déclaré avec son entityID et exactement une URL ACS :

curl -sS -X POST https://accounts.obexal.com/v1/admin/saml-idp/apps \
  -H "Authorization: Bearer $OBEXAL_API_TOKEN" -H 'Content-Type: application/json' \
  -d '{
    "name": "Grafana",
    "entityId": "https://grafana.example.eu/saml/metadata",
    "acsUrl": "https://grafana.example.eu/saml/acs",
    "nameIdFormat": "emailAddress",
    "nameIdAttribute": "email",
    "enabled": true
  }'
# 200 -> {"id":"samlsp_...","name":"Grafana","entityId":"...","acsUrl":"...","nameIdFormat":"emailAddress","nameIdAttribute":"email","enabled":true}
  • L'appel est un upsert dont la clé est entityId : reposter le même entityID met l'app à jour en place.
  • acsUrl doit être une URL absolue en https://. L'assertion est un credential bearer posté à cette adresse : le transport en clair est refusé.
  • Anti-exfiltration : l'assertion n'est jamais postée ailleurs que vers l'ACS enregistré. Une AuthnRequest qui demande une autre AssertionConsumerServiceURL est refusée ; un SP compromis ne peut pas détourner les assertions.
  • "enabled": false est un kill switch : un SP désactivé est traité comme inexistant.
  • GET /v1/admin/saml-idp retourne les coordonnées de votre IdP (entityId, metadataUrl, ssoUrl) et les apps enregistrées ; DELETE /v1/admin/saml-idp/apps/{id} en supprime une.

NameID et attributs de l'assertion

nameIdAttribute choisit ce qui identifie l'utilisateur chez le SP :

  • email (défaut) : le NameID est l'adresse e-mail de l'utilisateur. Obexal refuse d'affirmer un e-mail non vérifié (HTTP 403) : une assertion signée est un acte d'attestation, et affirmer une adresse non prouvée serait une primitive d'usurpation.
  • subject : le NameID est l'identifiant interne stable de l'utilisateur. Ce mode fonctionne même sans e-mail vérifié.

nameIdFormat fixe le format déclaré : emailAddress (défaut), persistent ou unspecified.

Quand l'e-mail est vérifié, l'assertion le porte aussi dans les attributs uid, eduPersonPrincipalName et cn. Si l'utilisateur appartient à des groupes, leurs noms sont émis dans un attribut multivalué eduPersonAffiliation (omis s'il est vide).

SSO SP-initiated et IdP-initiated

SP-initiated : l'application redirige le navigateur vers votre endpoint SSO avec une AuthnRequest. Sans session Obexal, l'utilisateur passe d'abord par la page de connexion puis revient automatiquement. Obexal répond par un formulaire auto-soumis qui POSTe la réponse signée vers l'ACS de l'application. La validité de session affirmée est plafonnée à 8 heures.

IdP-initiated : l'utilisateur clique la tuile de l'application dans son portail Obexal, ce qui ouvre /saml/idp/{tenant}/apps/{appId}/sso. Aucune AuthnRequest n'entre en jeu ; l'assertion part directement vers l'ACS enregistré.

Dans les deux flux, une session Obexal active est exigée, et la session doit appartenir au tenant de l'IdP : un utilisateur d'une autre organisation reçoit un 403, jamais une assertion.

Les erreurs

RéponseSignification
302 vers la page de connexionPas de session active ; l'utilisateur se connecte puis revient
400AuthnRequest malformée, ou SP inconnu ou désactivé (volontairement indistinguables)
403Mode NameID email avec une adresse non vérifiée, ou session d'un autre tenant

Limites, en toute honnêteté

  • Pas de Single Logout SAML : se déconnecter d'Obexal termine la session Obexal, mais les sessions déjà établies chez les SP vivent jusqu'à leur propre expiration. Voir sessions et déconnexion.
  • Le certificat de signature est auto-signé uniquement : impossible d'importer un certificat émis par une CA ou d'apporter votre propre clé.
  • Une seule URL ACS par SP, binding HTTP-POST uniquement.
  • Les assertions sont signées mais pas chiffrées.