Skip to content

Authentification SSO et OAuth

Configurez Google OAuth, GitHub OAuth et OIDC générique dans Potato. Restreignez l'accès par domaine de messagerie ou organisation GitHub, et activez la connexion mixte avec mots de passe.

Nouveau dans la v2.3.0

Par défaut, Potato utilise une connexion par simple nom d'utilisateur : les annotateurs saisissent le nom de leur choix. C'est pratique en développement local et sur les petits projets, mais un déploiement en production a besoin d'une vraie authentification pour bloquer les accès non autorisés, confirmer l'identité des annotateurs et satisfaire les exigences institutionnelles.

Potato 2.3 prend en charge trois méthodes d'authentification :

  1. Google OAuth -- connexion avec un compte Google, avec restriction de domaine facultative
  2. GitHub OAuth -- connexion avec un compte GitHub, avec restriction d'organisation facultative
  3. OIDC générique -- connexion à n'importe quel fournisseur OpenID Connect (Okta, Azure AD, Auth0, Keycloak, etc.)

Chacune peut se combiner avec la connexion par nom d'utilisateur déjà présente dans Potato, pour un fonctionnement en mode mixte.

Google OAuth

Prérequis

  1. Créez un projet dans la Google Cloud Console
  2. Activez l'API « Google Identity »
  3. Créez des identifiants OAuth 2.0 (type Application Web)
  4. Ajoutez l'URL de votre serveur Potato aux « URI de redirection autorisés » : https://your-server.com/auth/google/callback

Configuration

yaml
authentication:
  method: google_oauth
 
  google_oauth:
    client_id: ${GOOGLE_CLIENT_ID}
    client_secret: ${GOOGLE_CLIENT_SECRET}
    redirect_uri: "https://your-server.com/auth/google/callback"
 
    # Optional: restrict to specific domain(s)
    allowed_domains:
      - "umich.edu"
      - "research-lab.org"
 
    # Optional: auto-register new users on first login
    auto_register: true
 
    # Optional: map Google profile fields to Potato user fields
    field_mapping:
      username: email            # use email as Potato username
      display_name: name         # show Google display name

Restriction de domaine

Quand allowed_domains est défini, seuls les utilisateurs dont l'adresse e-mail relève de ces domaines peuvent se connecter. Les autres voient un message d'erreur :

yaml
authentication:
  method: google_oauth
  google_oauth:
    client_id: ${GOOGLE_CLIENT_ID}
    client_secret: ${GOOGLE_CLIENT_SECRET}
    allowed_domains:
      - "umich.edu"
    domain_error_message: "This annotation task is restricted to University of Michigan accounts."

GitHub OAuth

Prérequis

  1. Allez dans GitHub Settings > Developer settings > OAuth Apps > New OAuth App
  2. Renseignez « Authorization callback URL » avec https://your-server.com/auth/github/callback
  3. Notez votre Client ID et générez un Client Secret

Configuration

yaml
authentication:
  method: github_oauth
 
  github_oauth:
    client_id: ${GITHUB_CLIENT_ID}
    client_secret: ${GITHUB_CLIENT_SECRET}
    redirect_uri: "https://your-server.com/auth/github/callback"
 
    # Optional: restrict to members of specific GitHub organizations
    allowed_organizations:
      - "my-research-lab"
      - "university-nlp-group"
 
    # Optional: restrict to specific teams within an organization
    allowed_teams:
      - "my-research-lab/annotators"
 
    # Scopes to request
    scopes:
      - "read:user"
      - "read:org"             # needed for organization restriction
 
    auto_register: true
 
    field_mapping:
      username: login            # GitHub username
      display_name: name

Restriction par organisation

GitHub OAuth permet de limiter l'accès aux membres de certaines organisations. Cela demande la portée read:org :

yaml
authentication:
  method: github_oauth
  github_oauth:
    client_id: ${GITHUB_CLIENT_ID}
    client_secret: ${GITHUB_CLIENT_SECRET}
    allowed_organizations:
      - "my-research-lab"
    scopes:
      - "read:user"
      - "read:org"
    org_error_message: "You must be a member of the my-research-lab GitHub organization."

OIDC générique

Pour les fournisseurs SSO d'entreprise (Okta, Azure AD, Auth0, Keycloak, etc.), passez par l'intégration OpenID Connect générique.

Configuration

yaml
authentication:
  method: oidc
 
  oidc:
    # Discovery URL (provider's .well-known endpoint)
    discovery_url: "https://accounts.example.com/.well-known/openid-configuration"
 
    # Or specify endpoints manually
    # authorization_endpoint: "https://accounts.example.com/authorize"
    # token_endpoint: "https://accounts.example.com/token"
    # userinfo_endpoint: "https://accounts.example.com/userinfo"
    # jwks_uri: "https://accounts.example.com/.well-known/jwks.json"
 
    client_id: ${OIDC_CLIENT_ID}
    client_secret: ${OIDC_CLIENT_SECRET}
    redirect_uri: "https://your-server.com/auth/oidc/callback"
 
    scopes:
      - "openid"
      - "profile"
      - "email"
 
    auto_register: true
 
    field_mapping:
      username: preferred_username
      display_name: name
      email: email

Exemple Azure AD

yaml
authentication:
  method: oidc
 
  oidc:
    discovery_url: "https://login.microsoftonline.com/${AZURE_TENANT_ID}/v2.0/.well-known/openid-configuration"
    client_id: ${AZURE_CLIENT_ID}
    client_secret: ${AZURE_CLIENT_SECRET}
    redirect_uri: "https://your-server.com/auth/oidc/callback"
    scopes:
      - "openid"
      - "profile"
      - "email"
    auto_register: true
    field_mapping:
      username: preferred_username
      display_name: name

Exemple Okta

yaml
authentication:
  method: oidc
 
  oidc:
    discovery_url: "https://your-org.okta.com/.well-known/openid-configuration"
    client_id: ${OKTA_CLIENT_ID}
    client_secret: ${OKTA_CLIENT_SECRET}
    redirect_uri: "https://your-server.com/auth/oidc/callback"
    scopes:
      - "openid"
      - "profile"
      - "email"
      - "groups"               # request group membership
    auto_register: true
 
    # Restrict to specific groups
    allowed_groups:
      - "annotation-team"
 
    field_mapping:
      username: preferred_username
      display_name: name
      groups: groups

Exemple Keycloak

yaml
authentication:
  method: oidc
 
  oidc:
    discovery_url: "https://keycloak.example.com/realms/annotation/.well-known/openid-configuration"
    client_id: ${KEYCLOAK_CLIENT_ID}
    client_secret: ${KEYCLOAK_CLIENT_SECRET}
    redirect_uri: "https://your-server.com/auth/oidc/callback"
    scopes:
      - "openid"
      - "profile"
      - "email"
    auto_register: true
    field_mapping:
      username: preferred_username
      display_name: name

Restriction de domaine

Toutes les méthodes OAuth acceptent une restriction de domaine fondée sur l'adresse e-mail. C'est pratique quand vous voulez autoriser n'importe quel compte d'un établissement donné :

yaml
authentication:
  method: google_oauth          # or github_oauth, oidc
 
  domain_restriction:
    enabled: true
    allowed_domains:
      - "umich.edu"
      - "stanford.edu"
    error_message: "Access is restricted to university accounts."

Pour les fournisseurs OIDC qui renvoient une revendication email, la restriction de domaine fonctionne d'elle-même. Pour ceux qui ne la renvoient pas, il faut parfois demander explicitement la portée email.

Inscription automatique

Par défaut, un utilisateur doit être enregistré dans Potato avant de pouvoir annoter. Avec auto_register: true, tout utilisateur qui s'authentifie avec succès est créé automatiquement dans Potato lors de sa première connexion.

yaml
authentication:
  auto_register: true
  auto_register_role: annotator   # annotator or admin

Pour pré-approuver certains utilisateurs et bloquer les autres :

yaml
authentication:
  auto_register: false
  allowed_users:
    - "researcher@umich.edu"
    - "student1@umich.edu"
    - "student2@umich.edu"
  user_not_found_message: "Your account has not been approved. Contact the project administrator."

Mode mixte

Vous pouvez activer plusieurs méthodes d'authentification en même temps. La page de connexion affiche alors un bouton par méthode activée, plus un champ de nom d'utilisateur facultatif.

yaml
authentication:
  methods:
    - google_oauth
    - github_oauth
    - username                   # keep simple username login as fallback
 
  google_oauth:
    client_id: ${GOOGLE_CLIENT_ID}
    client_secret: ${GOOGLE_CLIENT_SECRET}
    redirect_uri: "https://your-server.com/auth/google/callback"
 
  github_oauth:
    client_id: ${GITHUB_CLIENT_ID}
    client_secret: ${GITHUB_CLIENT_SECRET}
    redirect_uri: "https://your-server.com/auth/github/callback"
 
  # Username login settings
  username:
    enabled: true
    require_password: true       # require a password for username login
    password_file: "auth/passwords.yaml"

Le mode mixte sert surtout pendant une migration : activez OAuth à côté de la connexion par nom d'utilisateur, puis désactivez cette dernière une fois que tous les annotateurs ont rattaché leur compte OAuth.

Gestion des sessions

Réglez le comportement des sessions pour les utilisateurs authentifiés :

yaml
authentication:
  session:
    lifetime_hours: 24           # session duration
    refresh: true                # refresh session on activity
    cookie_secure: true          # require HTTPS for cookies
    cookie_samesite: "Lax"       # SameSite cookie attribute

Authentification des administrateurs

Les comptes administrateurs peuvent emprunter le même flux OAuth ou une méthode d'authentification distincte :

yaml
authentication:
  method: google_oauth
  google_oauth:
    client_id: ${GOOGLE_CLIENT_ID}
    client_secret: ${GOOGLE_CLIENT_SECRET}
 
  admin:
    # Admins must match these emails
    admin_emails:
      - "pi@umich.edu"
      - "lead-ra@umich.edu"
 
    # Or use a separate API key for admin access
    api_key: ${ADMIN_API_KEY}

Exigences HTTPS

En production, les fournisseurs OAuth imposent HTTPS pour les URI de redirection. En développement local, HTTP reste possible avec localhost :

yaml
# Development (HTTP allowed)
authentication:
  google_oauth:
    redirect_uri: "http://localhost:8000/auth/google/callback"
 
# Production (HTTPS required)
authentication:
  google_oauth:
    redirect_uri: "https://annotation.example.com/auth/google/callback"

Pour un déploiement en production derrière un proxy inverse (nginx, Caddy), vérifiez que le proxy transmet bien l'en-tête X-Forwarded-Proto :

nginx
# nginx example
location / {
    proxy_pass http://localhost:8000;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
}

Exemple complet

Configuration d'authentification complète pour la production, avec Google OAuth, restriction de domaine et clé d'API d'administration :

yaml
task_name: "Annotation Project"
task_dir: "."
 
authentication:
  method: google_oauth
 
  google_oauth:
    client_id: ${GOOGLE_CLIENT_ID}
    client_secret: ${GOOGLE_CLIENT_SECRET}
    redirect_uri: "https://annotation.umich.edu/auth/google/callback"
    allowed_domains:
      - "umich.edu"
    auto_register: true
    field_mapping:
      username: email
      display_name: name
 
  session:
    lifetime_hours: 48
    cookie_secure: true
 
  admin:
    admin_emails:
      - "pi@umich.edu"
    api_key: ${ADMIN_API_KEY}
 
data_files:
  - "data/instances.jsonl"
 
annotation_schemes:
  - annotation_type: radio
    name: sentiment
    labels: [Positive, Neutral, Negative]
 
output_annotation_dir: "output/"
output_annotation_format: "jsonl"

Pour aller plus loin

Pour les détails d'implémentation, consultez la documentation source.