> ## Documentation Index
> Fetch the complete documentation index at: https://auth0.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API Java Spring Boot

> Ajoutez l’authentification JWT d’Auth0 à une API Spring Boot avec des points de terminaison protégés

Ce Quickstart est actuellement en **bêta**. Nous aimerions beaucoup avoir vos commentaires !

> **Utiliser l’IA pour intégrer Auth0**
>
> Si vous utilisez un assistant de codage IA comme Claude Code, Cursor ou GitHub Copilot, vous pouvez ajouter l’authentification Auth0 automatiquement en quelques minutes grâce à [Agent Skills](https://agentskills.io/home).
>
> **Installer :**
>
> ```bash theme={null}
> npx skills add auth0/agent-skills --skill auth0
> ```
>
> **Demandez ensuite à votre assistant IA :**
>
> ```text theme={null}
> Add Auth0 JWT authentication to my Spring Boot API
> ```
>
> Votre assistant IA créera automatiquement votre API Auth0, récupérera les identifiants, ajoutera la dépendance SDK Auth0 Spring Boot API, configurera `application.yml` et mettra en place un `SecurityFilterChain` avec validation des JWT et points de terminaison protégés. [Documentation complète sur Agent Skills →](https://auth0.com/docs/fr-ca/quickstart/agent-skills.md)

> [!NOTE]
>
> **Prérequis :** Avant de commencer, assurez-vous d’avoir installé ce qui suit :
>
> * **[JDK 17+](https://openjdk.org/projects/jdk/17/)** pour la compatibilité avec Spring Boot 3.2+
> * **[Maven 3.6+](https://maven.apache.org/download.cgi)** ou **[Gradle 7+](https://gradle.org/install/)** pour la gestion des dépendances
> * Votre IDE de préférence (IntelliJ IDEA, Eclipse ou VS Code avec prise en charge de Java)
>
> **Compatibilité des versions Java :** Ce Quickstart fonctionne avec **Java 17+** et **Spring Boot 3.2+**.

## Pour commencer

Ce Quickstart montre comment ajouter l’authentification JWT d’Auth0 à une API Spring Boot. Vous créerez une API sécurisée avec des points de terminaison protégés à l’aide du SDK Auth0 Spring Boot API.

**1. Créer un nouveau projet**

Créez un nouveau projet d’API Spring Boot pour ce Quickstart :

**Avec Spring Initializr :**

```bash theme={null}
curl -L https://start.spring.io/starter.zip \
    -d dependencies=web,security \
    -d javaVersion=17 \
    -d name=auth0-api \
    -d artifactId=auth0-api \
    -d packageName=com.example.auth0api \
    -o auth0-api.zip

mkdir auth0-api && unzip auth0-api.zip -d auth0-api && cd auth0-api
```

**Ou créez manuellement avec Maven :**

```bash theme={null}
mvn archetype:generate \
    -DgroupId=com.example \
    -DartifactId=auth0-api \
    -DarchetypeArtifactId=maven-archetype-quickstart \
    -DinteractiveMode=false

cd auth0-api
```

**2. Ajouter le SDK Auth0**

Ajoutez l’Auth0 Spring Boot API SDK aux dépendances de votre projet :

**Maven (`pom.xml`) :**

```xml theme={null}
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>auth0-springboot-api</artifactId>
    <version>1.0.0-beta.0</version>
</dependency>
```

**Gradle (`build.gradle`) :**

```gradle theme={null}
dependencies {
    implementation 'com.auth0:auth0-springboot-api:1.0.0-beta.0'
}
```

**3. Configurez votre API Auth0**

Ensuite, vous devez créer une nouvelle API sur votre tenant Auth0 et ajouter la configuration à votre projet.

Vous pouvez effectuer cette opération automatiquement en exécutant une commande CLI ou manuellement via le Dashboard :

**CLI**

Exécutez la commande shell suivante à la racine de votre projet pour créer une API Auth0 et mettre à jour votre fichier `application.yml` :

**Mac/Linux**

```bash expandable theme={null}
AUTH0_API_NAME="My Spring Boot API" && \
AUTH0_API_IDENTIFIER="https://my-springboot-api" && \
brew tap auth0/auth0-cli && \
brew install auth0 && \
auth0 login --no-input && \
auth0 apis create -n "${AUTH0_API_NAME}" -i "${AUTH0_API_IDENTIFIER}" --offline-access --token-lifetime 86400 --signing-alg RS256 --json > auth0-api-details.json && \
DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && \
AUDIENCE=$(jq -r '.identifier' auth0-api-details.json) && \
mkdir -p src/main/resources && \
printf 'auth0:\n  domain: %s\n  audience: %s\n\nspring:\n  application:\n    name: auth0-api\n' "$DOMAIN" "$AUDIENCE" > src/main/resources/application.yml && \
rm auth0-api-details.json && \
echo "✅ application.yml created with your Auth0 API details:" && \
cat src/main/resources/application.yml
```

**Windows (PowerShell)**

```powershell expandable theme={null}
$ApiName = "My Spring Boot API"
$ApiIdentifier = "https://my-springboot-api"
$latestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/auth0/auth0-cli/releases/latest"
$latestVersion = $latestRelease.tag_name
$version = $latestVersion -replace "^v"
Invoke-WebRequest -Uri "https://github.com/auth0/auth0-cli/releases/download/${latestVersion}/auth0-cli_${version}_Windows_x86_64.zip" -OutFile ".\auth0.zip"
Expand-Archive ".\auth0.zip" .\
[System.Environment]::SetEnvironmentVariable('PATH', $Env:PATH + ";${pwd}")
auth0 login --no-input
auth0 apis create -n "$ApiName" -i "$ApiIdentifier" --offline-access --token-lifetime 86400 --signing-alg RS256 --json | Set-Content -Path auth0-api-details.json
$Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name
$Audience = (Get-Content -Raw auth0-api-details.json | ConvertFrom-Json).identifier
New-Item -ItemType Directory -Force -Path "src\main\resources"
@"
auth0:
  domain: "$Domain"
  audience: "$Audience"

spring:
  application:
    name: auth0-api
"@ | Set-Content "src\main\resources\application.yml"
Remove-Item auth0-api-details.json
Write-Output "✅ application.yml created with your Auth0 API details:"
Get-Content "src\main\resources\application.yml"
```

**Dashboard**

Avant de commencer, ajoutez la configuration Auth0 à votre fichier `src/main/resources/application.yml`

```yaml src/main/resources/application.yml expandable theme={null}
auth0:
  domain: "YOUR_AUTH0_DOMAIN"
  audience: "YOUR_AUTH0_API_IDENTIFIER"

spring:
  application:
    name: auth0-api
```

1. Accédez à [Auth0 Dashboard](https://manage.auth0.com) → **Applications** → **APIs**
2. Sélectionnez **Create API**
3. Entrez les détails de votre API :
   * **Name** : My Spring Boot API
   * **Identifier** : `https://my-springboot-api` (cela devient votre Audience)
   * **Signing Algorithm** : RS256
4. Sélectionnez **Create**
5. Remplacez `YOUR_AUTH0_DOMAIN` dans `application.yml` par votre **Domain** indiqué dans l’onglet Test (par exemple, `your-tenant.auth0.com`)
6. Remplacez `YOUR_AUTH0_API_IDENTIFIER` dans `application.yml` par votre **Identifier**. Par exemple : `https://my-springboot-api`.

> [!NOTE]
>
> Votre **Domain** ne doit pas inclure `https://`. Utilisez uniquement le domaine et la région. Par exemple : `your-tenant.auth0.com`.
>
> L’**Audience** (identifiant de l’API) est un identifiant unique pour votre API et peut être n’importe quel URI valide. Il n’a pas besoin d’être une URL accessible publiquement.

**4. Configurer l’authentification**

Créez une classe de configuration de sécurité pour activer l’authentification JWT d’Auth0. Créez `src/main/java/com/example/auth0api/SecurityConfig.java` :

```java src/main/java/com/example/auth0api/SecurityConfig.java lines expandable theme={null}
package com.example.auth0api;

import com.auth0.spring.boot.Auth0AuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig {

    @Bean
    SecurityFilterChain apiSecurity(HttpSecurity http, Auth0AuthenticationFilter authFilter) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())
            .sessionManagement(session ->
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public").permitAll()
                .requestMatchers("/api/private").authenticated()
                .anyRequest().permitAll())
            .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class)
            .build();
    }
}
```

**5. Créer des points de terminaison publics et protégés**

Créez des points de terminaison de l’API pour tester l’authentification. Créez `src/main/java/com/example/auth0api/ApiController.java` :

```java src/main/java/com/example/auth0api/ApiController.java expandable theme={null}
package com.example.auth0api;

import com.auth0.spring.boot.Auth0AuthenticationToken;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@RequestMapping("/api")
public class ApiController {

    // Endpoint public - aucune authentification requise
    @GetMapping("/public")
    public ResponseEntity<Map<String, String>> publicEndpoint() {
        return ResponseEntity.ok(Map.of(
            "message", "This endpoint is public - no authentication required"
        ));
    }

    // Endpoint protégé - authentification requise
    @GetMapping("/private")
    public ResponseEntity<Map<String, Object>> privateEndpoint(Authentication authentication) {
        Auth0AuthenticationToken auth0Token = (Auth0AuthenticationToken) authentication;

        return ResponseEntity.ok(Map.of(
            "message", "This endpoint requires authentication",
            "user", authentication.getName(),
            "scopes", auth0Token.getAuthorities()
        ));
    }
}
```

**6. Lancez votre API**

Lancez votre application Spring Boot :

**Maven :**

```bash theme={null}
./mvnw spring-boot:run
```

**Gradle :**

```bash theme={null}
./gradlew bootRun
```

Votre API est maintenant accessible à l’adresse `http://localhost:8080` (consultez la sortie de la console pour connaître l’URL exacte).

> [!TIP]
>
> **Vérification**
>
> Vous devriez maintenant avoir une API entièrement fonctionnelle protégée par Auth0 qui s’exécute sur [localhost](http://localhost:8080/)

***

## Utilisation avancée

> **Appeler des API protégées**
>
> Testez vos points de terminaison protégés avec un jeton d’accès.
>
> **1. Obtenez un jeton d’accès** d’Auth0 à l’aide du flux Client Credentials :
>
> ```bash theme={null}
> curl --request POST \
>   --url https://YOUR_DOMAIN/oauth/token \
>   --header 'content-type: application/json' \
>   --data '{"client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET","audience":"YOUR_AUDIENCE","grant_type":"client_credentials"}'
> ```
>
> > [!NOTE]
> >
> > Pour obtenir `YOUR_CLIENT_ID` et `YOUR_CLIENT_SECRET`, créez une
> > application Machine to Machine dans le [Auth0 Dashboard](https://manage.auth0.com/#/applications)
> > et autorisez-la pour votre API.
>
> **2. Testez le point de terminaison public** (devrait renvoyer 200 OK) :
>
> ```bash theme={null}
> curl http://localhost:8080/api/public
> ```
>
> **3. Testez le point de terminaison protégé sans authentification** (devrait renvoyer 401 Non autorisé) :
>
> ```bash theme={null}
> curl http://localhost:8080/api/private
> ```
>
> **4. Appelez le point de terminaison protégé avec le jeton :**
>
> ```bash theme={null}
> curl http://localhost:8080/api/private \
>   --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
> ```

> **Accéder aux claims JWT**
>
> Accédez à des renseignements supplémentaires sur l’utilisateur et aux claims du jeton dans vos points de terminaison.
>
> ```java theme={null}
> @GetMapping("/profile")
> public ResponseEntity<Map<String, Object>> getUserProfile(Authentication authentication) {
>     Auth0AuthenticationToken auth0Token = (Auth0AuthenticationToken) authentication;
>     Map<String, Object> claims = auth0Token.getAuthenticationContext().getClaims();
>
>     return ResponseEntity.ok(Map.of(
>         "userId", authentication.getName(),
>         "email", claims.get("email"),
>         "scope", claims.get("scope"),
>         "issuer", claims.get("iss"),
>         "audience", claims.get("aud")
>     ));
> }
> ```

> **Autorisation basée sur les scopes**
>
> Mettez en œuvre un contrôle d’accès précis à l’aide des scopes JWT pour une sécurité renforcée.
>
> **1. Définissez des scopes dans votre API Auth0 :**
>
> Dans le [Auth0 Dashboard](https://manage.auth0.com) → APIs → Your API → Permissions, ajoutez des scopes :
>
> * `read:users` - Lire les données utilisateur
> * `write:users` - Écrire des données utilisateur
> * `admin` - Accès administratif
>
> **2. Configurez les politiques d’autorisation :**
>
> ```java theme={null}
> @Configuration
> public class SecurityConfig {
>     @Bean
>     SecurityFilterChain apiSecurity(HttpSecurity http, Auth0AuthenticationFilter authFilter) throws Exception {
>         return http
>             .csrf(csrf -> csrf.disable())
>             .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
>             .authorizeHttpRequests(auth -> auth
>                 .requestMatchers("/api/admin/**").hasAuthority("SCOPE_admin")
>                 .requestMatchers("/api/users/**").hasAnyAuthority("SCOPE_read:users", "SCOPE_write:users")
>                 .requestMatchers("/api/private").authenticated()
>                 .anyRequest().permitAll())
>             .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class)
>             .build();
>     }
> }
> ```
>
> Lorsque vous demandez un jeton d’accès, incluez le scope requis :
>
> ```bash theme={null}
> curl --request POST \
>   --url https://YOUR_DOMAIN/oauth/token \
>   --header 'content-type: application/json' \
>   --data '{"client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET","audience":"YOUR_AUDIENCE","grant_type":"client_credentials","scope":"read:users write:users admin"}'
> ```

> **Sécurité renforcée DPoP**
>
> Activez DPoP (Demonstration of Proof-of-Possession) pour renforcer la sécurité des jetons en liant les jetons d’accès à des clés cryptographiques.
>
> **Configurez la prise en charge de DPoP dans application.yml :**
>
> ```yaml theme={null}
> auth0:
>   domain: "your-tenant.auth0.com"
>   audience: "https://my-springboot-api"
>   dpopMode: ALLOWED # DISABLED, ALLOWED (par défaut), REQUIRED
>   dpopIatOffsetSeconds: 300 # 5 minutes (par défaut)
>   dpopIatLeewaySeconds: 60 # marge de 1 minute (par défaut : 30s)
> ```
>
> **Modes DPoP :**
>
> * `ALLOWED` (par défaut) : accepte à la fois les jetons Bearer et DPoP
> * `REQUIRED` : accepte uniquement les jetons DPoP, rejette les jetons Bearer
> * `DISABLED` : validation JWT Bearer standard uniquement
>
>   > [!NOTE]
>   >
>   > Pour en savoir plus sur DPoP, consultez la [documentation DPoP d’Auth0](https://auth0.com/docs/fr-ca/secure/sender-constraining/demonstrating-proof-of-possession-dpop.md).

***

## Problèmes courants

> **401 Non autorisé - audience invalide**
>
> **Problème :** L’API renvoie un 401 même avec des jetons valides.
>
> **Solution :** Assurez-vous que `auth0.audience` correspond exactement à votre identifiant d’API Auth0. Le claim `audience` dans le jeton doit correspondre à cette valeur.
>
> ```yaml theme={null}
> # ❌ INCORRECT
> auth0:
>   audience: "my-api"
>
> # ✅ CORRECT
> auth0:
>   audience: "https://my-springboot-api"
> ```

> **401 Non autorisé - issuer invalide**
>
> **Problème :** La validation de l’issuer du jeton échoue.
>
> **Solution :** Vérifiez que votre domaine est correct et qu’il n’inclut pas `https://`. Utilisez le domaine sans le préfixe `https://`.
>
> ```yaml theme={null}
> # ❌ INCORRECT
> auth0:
>   domain: "https://your-tenant.auth0.com"
>
> # ✅ CORRECT
> auth0:
>   domain: "your-tenant.auth0.com"
> ```

> **Valeurs de configuration introuvables**
>
> **Problème :** L’application ne démarre pas en raison d’erreurs de configuration.
>
> **Solution :** Vérifiez la structure de `application.yml` et les noms des propriétés. Assurez-vous que la section auth0 contient les valeurs Domain et Audience.
>
> ```yaml theme={null}
> # ✅ structure CORRECTE
> auth0:
>   domain: "your-tenant.auth0.com"
>   audience: "https://your-api-identifier"
>
> spring:
>   application:
>     name: auth0-api
> ```

> **Problèmes d’ordre des filtres**
>
> **Problème :** L’authentification ne fonctionne pas malgré une configuration correcte.
>
> **Solution :** Assurez-vous que Auth0AuthenticationFilter est correctement intégré à la chaîne Spring Security. Le filtre doit être ajouté avant UsernamePasswordAuthenticationFilter.
>
> ```java theme={null}
> // ✅ ordre des filtres CORRECT
> .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class)
> ```

> **Problèmes de connectivité réseau**
>
> **Problème :** Échec de récupération de JWKS ou délais d’attente de connexion.
>
> **Solution :** Il se peut que le pare-feu de l’entreprise bloque les endpoints Auth0. Autorisez les domaines Auth0 pour l’accès HTTPS :
>
> ```bash theme={null}
> # Règles de pare-feu requises (HTTPS/443 sortant)
> *.auth0.com
> *.us.auth0.com  # Pour les tenants de la région US
> *.eu.auth0.com  # Pour les tenants de la région UE
> *.au.auth0.com  # Pour les tenants de la région AU
> ```

> **Les scopes ne fonctionnent pas dans les politiques d’autorisation**
>
> **Problème :** Les politiques d’autorisation basées sur les scopes échouent systématiquement.
>
> **Solution :** Assurez-vous que votre jeton d’accès inclut les scopes requis. Lors de la demande d’un jeton, précisez les scopes :
>
> ```bash theme={null}
> curl --request POST \
>   --url https://YOUR_DOMAIN/oauth/token \
>   --data '{"client_id":"...","client_secret":"...","audience":"...","grant_type":"client_credentials","scope":"read:users write:users admin"}'
> ```
>
> Vérifiez également que les scopes sont définis dans les paramètres de votre API Auth0 (Dashboard → APIs → Your API → Permissions).

***

## Ressources supplémentaires

> **[Documentation du SDK](https://github.com/auth0/auth0-auth-java/tree/main/auth0-springboot-api)**
>
> Documentation complète du SDK et référence de l’API

> **[Exemples de code](https://github.com/auth0/auth0-auth-java/blob/main/auth0-springboot-api/EXAMPLES.md)**
>
> Exemples de code détaillés et modèles d’intégration

> **[Documentation sur le DPoP](https://auth0.com/docs/fr-ca/secure/sender-constraining/demonstrating-proof-of-possession-dpop.md)**
>
> Découvrez l’amélioration de sécurité qu’apporte la preuve de possession

> **[Référence Spring Security](https://docs.spring.io/spring-security/reference/)**
>
> Documentation officielle de Spring Security

> **[Auth0 Dashboard](https://manage.auth0.com/)**
>
> Gérez vos API Auth0 et vos applications

> **[Forum de la communauté](https://community.auth0.com/)**
>
> Obtenez de l’aide auprès de la communauté Auth0

***

## Application d’exemple

Une application d’exemple complète présentant toutes les fonctionnalités se trouve dans le dépôt du SDK.

> **[Application de test](https://github.com/auth0/auth0-auth-java/tree/main/auth0-springboot-api-playground)**
>
> Comprend des points de terminaison publics et protégés, la prise en charge
> de DPoP et des exemples détaillés

Clonez et exécutez :

```bash theme={null}
git clone https://github.com/auth0/auth0-auth-java.git
cd auth0-auth-java/auth0-springboot-api-playground

# Mettez à jour src/main/resources/application.yml avec votre configuration Auth0
# Ensuite, exécutez :
./mvnw spring-boot:run
```

**Tester avec curl :**

```bash theme={null}
# Tester le point de terminaison public
curl http://localhost:8080/api/public

# Obtenir le jeton d'accès (remplacer par vos identifiants Auth0)
curl -X POST https://YOUR_DOMAIN/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "audience": "https://my-springboot-api",
    "grant_type": "client_credentials"
  }'

# Tester le point de terminaison protégé avec le jeton Bearer
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
     http://localhost:8080/api/private
```
