Authentification X.509 dans Spring Security

X.509 Authentication in Spring Security

1. Vue d'ensemble

Dans cet article, nous allons nous concentrer sur les principaux cas d'utilisation deX.509 certificate authentication -verifying the identity of a communication peer lors de l'utilisation du protocoleHTTPS (HTTP over SSL).

En termes simples, lorsqu'une connexion sécurisée est établie, le client vérifie le serveur en fonction de son certificat (émis par une autorité de certification de confiance).

Mais au-delà,X.509 dansSpring Security peut être utilisé pourverify the identity of a client via le serveur lors de la connexion. Cela s'appelle“mutual authentication, “ et nous verrons comment cela se fait ici également.

Enfin, nous aborderonswhen it makes sense to use this kind of authentication.

Pour démontrer la vérification du serveur, nous allons créer une application Web simple et installer une autorité de certification personnalisée dans un navigateur.

Et, pourmutual authentication, nous créerons un certificat client et modifierons notre serveur pour n'autoriser que les clients vérifiés.

2. Keystores

Optional Requirement: pour utiliser des clés cryptographiquement fortes avec des fonctionnalités de cryptage et de décryptage, vous devez installer les‘Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files' dans vosJVM.

Ceux-ci peuvent être téléchargés par exemple depuisOracle (suivez les instructions d'installation incluses dans le téléchargement). Certaines distributions Linux fournissent également un paquet installable via leurs gestionnaires de paquets.

Pour implémenterX.509 authentication dans une application Spring, nous allonsfirst create a keystore in the Java Key-Store (JKS) format.

Cekeystore doitcontain a valid certificate of authority or a chain of certificate authorities et un propre certificat pour notre serveur. Ce dernier doit être signé par l'un desauthorities inclus et doit être nommé d'après lehostname sur lequel le serveur fonctionne; nous allons utiliser l’applicationJavakeytool ici.

To simplify le processus de création dekeys etcertificates en utilisantkeytool, le codeon Github, fournit unMakefile commenté pour GNUmake , contenant toutes les étapes nécessaires pour compléter cette section. Vous pouvez également facilement le personnaliser via quelques variables d’environnement.

Tip: En tant queall-in-one step, vous pouvez exécutermake sans argument. Cela créera unkeystore, untruststore et deux certificats pour l'importation dans votre navigateur (un pourlocalhost et un pour un utilisateur appelé“cid”).

Pour créer un nouveaukeystore avec une autorité de certification, nous pouvons exécutermake comme suit:

$> make create-keystore PASSWORD=changeit

Maintenant, nous allons ajouter un certificat pour notre hôte de développement à cekeystore créé et le signer par noscertificate authority:

$> make add-host HOSTNAME=localhost

Pour autoriserclient authentication, nous avons également besoin d'unkeystore appelé“truststore”. Cetruststore doit contenir des certificats valides de noscertificate authority et de tous les clients autorisés. Pour plus d'informations sur l'utilisation dekeytool, veuillez consulter lesMakefile dans les sections données: suivantes

$> make create-truststore PASSWORD=changeit
$> make add-client CLIENTNAME=cid

3. Exemple d'application

Notre projet de serveur sécurisé SSL sera composé d'une classe d'application annotée@SpringBootApplication (qui est une sorte de@Configuration), d'un fichier de configurationapplication.properties et d'un frontal très simple de style MVC.

Tout ce que l'application a à faire est de présenter une pageHTML avec un message“Hello {User}!”. De cette façon, nous pouvons inspecter le certificat de serveur dans un navigateur pour nous assurer que la connexion est vérifiée et sécurisée.

Tout d'abord, nous créons un nouveau projetMaven avec trois bundlesSpring Boot Starter inclus:


    org.springframework.boot
    spring-boot-starter-security
    1.4.0.RELEASE


    org.springframework.boot
    spring-boot-starter-web
    1.4.0.RELEASE


    org.springframework.boot
    spring-boot-starter-thymeleaf
    1.4.0.RELEASE

For reference: vous trouverez les bundles surMaven Central (security,web,thymeleaf).

À l’étape suivante, nous créons la classe d’application principale et le contrôleur d’utilisateur:

@SpringBootApplication
public class X509AuthenticationServer {
    public static void main(String[] args) {
        SpringApplication.run(X509AuthenticationServer.class, args);
    }
}

@Controller
public class UserController {
    @RequestMapping(value = "/user")
    public String user(Model model, Principal principal) {

        UserDetails currentUser
          = (UserDetails) ((Authentication) principal).getPrincipal();
        model.addAttribute("username", currentUser.getUsername());
        return "user";
    }
}

Maintenant, nous disons à l'application où ils peuvent trouver noskeystore et comment y accéder. Nous définissonsSSL sur un état «activé» et changeons le port d'écoute standard enindicate a secured connection.

De plus, nous configurons certainsuser-details pour accéder à notre serveur viaBasic Authentication:

server.ssl.key-store=../keystore/keystore.jks
server.ssl.key-store-password=${PASSWORD}
server.ssl.key-alias=localhost
server.ssl.key-password=${PASSWORD}
server.ssl.enabled=true
server.port=8443
security.user.name=Admin
security.user.password=admin

Ce sera le modèle HTML, situé dans le dossierresources/templates:




    X.509 Authentication Demo


    

Hello !

Avant de terminer cette section et de regarder le site, nous devons encore installer notre autorité de certification générée en tant quetrusted certificate dans un navigateur de notre choix.

Une installation exemplaire de noscertificate authority pourMozilla Firefox ressemblerait à ceci:

  1. Tapezabout:preferences dans la barre d'adresse

  2. OuvrirAdvanced → Certificates → View Certificates → Authorities

  3. Cliquez surImport

  4. Localisez le dossierexample tutorials et son sous-dossierspring-security-x509/keystore

  5. Sélectionnez le fichierca.crt et cliquez surOK

  6. Choisissez «Trust this CA to identify websites” et cliquez surOK

Note: Si vous ne voulez pas ajouter noscertificate authority à la liste destrusted authorities, vous aurez plus tard la possibilité de faire unexception et de montrer le site Web dur, même quand il est mentionné comme non sécurisé. Mais ensuite, vous verrez un symbole de «point d'exclamation jaune» dans la barre d'adresse, indiquant la connexion non sécurisée!

Ensuite, nous allons naviguer vers le module spring-security-x509-basic-auth et exécuter:

mvn spring-boot:run

Enfin, nous frapponshttps://localhost:8443/user, entrons nos informations d'identification utilisateur à partir desapplication.properties et devrions voir un message“Hello Admin!”. Nous sommes désormais en mesure d'inspecter l'état de la connexion en cliquant sur le symbole "cadenas vert" dans la barre d'adresse, et il devrait s'agir d'une connexion sécurisée.

image

 

4. Authentification mutuelle

Dans cette section, nous utilisonsSpring Security pour permettre aux utilisateurs d'accéder à notre site Web de démonstration. La procédure rend un formulaire de connexion obsolète.

Mais avant de continuer à modifier notre serveur, nous discuterons brièvement du moment où il est logique de fournir ce type d’authentification.

Avantages:

  • La clé privée d'unX.509 client certificate eststronger than any user-defined password. Mais il faut garder le secret!

  • Avec un certificat, lesidentity d'un clientis well-known et faciles à vérifier.

  • Plus de mots de passe oubliés!

Les inconvénients:

  • Vous devez vous rappeler que pour chaque utilisateur qui doit être vérifié par le serveur, son certificat doit être installé dans lestruststore configurés. Pour les petites applications avec seulement quelques clients, cela peut être possible,with an increasing number of clients it may lead to complex key-management for users.

  • La clé privée d'un certificat doit être installée dans une application cliente. En fait:X.509 client authenticationis device dependent, ce qui rend impossible l'utilisation de ce type d'authentification dans les espaces publics, par exemple dans un cybercafé.

  • Il doit exister un mécanisme permettant de révoquer les certificats clients compromis.

Pour continuer, nous modifions nosX509AuthenticationServer pour étendre à partir deWebSecurityConfigurerAdapter et remplacer l'une des méthodes de configuration fournies. Ici, nous configurons le mécanismex.509 pour analyser le champCommon Name (CN) d'un certificat pour extraire les noms d'utilisateur.

Avec ces noms d'utilisateur extraits,Spring Security recherche dans unUserDetailsService fourni les utilisateurs correspondants. Nous avons donc également implémenté cette interface de service contenant un utilisateur de démonstration.

Tip: Dans les environnements de production, ceUserDetailsService peut charger ses utilisateurs par exemple à partir d'un lien: / spring-jdbc-jdbctemplate.

Vous devez noter que nous annotons notre classe avec@EnableWebSecurity et@EnableGlobalMethodSecurity avec une pré- / post-autorisation activée.

Avec ce dernier, nous pouvons annoter nos ressources avec@PreAuthorize et@PostAuthorize pour un contrôle d'accès fin:

@SpringBootApplication
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class X509AuthenticationServer extends WebSecurityConfigurerAdapter {
    ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
          .and()
          .x509()
            .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
            .userDetailsService(userDetailsService());
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) {
                if (username.equals("cid")) {
                    return new User(username, "",
                      AuthorityUtils
                        .commaSeparatedStringToAuthorityList("ROLE_USER"));
                }
            }
        };
    }
}

Comme dit précédemment, nous pouvons maintenant utiliserExpression-Based Access Control dans notre contrôleur. Plus précisément, nos annotations d'autorisation sont respectées grâce à l'annotation@EnableGlobalMethodSecurity dans nos@Configuration: __

@Controller
public class UserController {
    @PreAuthorize("hasAuthority('ROLE_USER')")
    @RequestMapping(value = "/user")
    public String user(Model model, Principal principal) {
        ...
    }
}

Vous trouverez un aperçu de toutes les options d'autorisation possibles dans lesofficial documentation.

Comme dernière étape de modification, nous devons dire à l'application où se trouve notretruststore et queSSL client authentication est nécessaire (server.ssl.client-auth=need).

Nous mettons donc ce qui suit dans nosapplication.properties:

server.ssl.trust-store=../keystore/truststore.jks
server.ssl.trust-store-password=${PASSWORD}
server.ssl.client-auth=need

Maintenant, si nous exécutons l'application et orientons notre navigateur vershttps://localhost:8443/user, nous nous informons que le pair ne peut pas être vérifié et il refuse d'ouvrir notre site Web. Nous devons donc également installer notreclient certificate, qui est décrit ici à titre d'exemple pourMozilla Firefox:

  1. Tapezabout:preferences dans la barre d'adresse

  2. OuvrirAdvanced → View Certificates → Your Certificates

  3. Cliquez surImport

  4. Localisez le dossierexample tutorials et son sous-dossierspring-security-x509/keystore

  5. Sélectionnez le fichiercid.p12 et cliquez surOK

  6. Saisissez le mot de passe de votre certificat et cliquez surOK

Enfin, nous actualisons l'onglet de notre navigateur contenant le site Web et sélectionnons notre certificat client dans la nouvelle boîte de dialogue de sélection.

image

Si nous voyons un message de bienvenue comme“Hello cid!”, nous avons réussi!

5. Authentification mutuelle avec XML

L'ajout deX.509 client authentication à unhttp security configuration in XML est également possible:


    ...
    

    
        
            
                
            
        
    
    ...

Pour configurer unTomcat sous-jacent, nous devons mettre noskeystore et nostruststore dans son dossierconf et éditer lesserver.xml:

Tip: AvecclientAuth défini sur“want”,SSL est toujours activé, même si le client ne fournit pas de certificat valide. Mais dans ce cas, nous devons utiliser un deuxième mécanisme d'authentification, par exemple, un formulaire de connexion, pour accéder aux ressources sécurisées.

6. Conclusion

In summary, nous avons appris à créer unkeystore contenant uncertificate authority et unself-signed certificate for our development environment.

Nous avons créé lestruststore containing a certificate authority and a client certificate, et nous avons utilisé les deux versverify our server côté clientand our client côté serveur.

Si vous avez étudié lesMakefile, vous devriez être capable decreate certificates, make certificate-requests and import signed certificates en utilisant Javakeytool.

De plus, vous devriez maintenant pouvoir utiliserexport a client certificate into the PKCS12 format et l'utiliser dans une application cliente comme un navigateur, par exemple,Mozilla Firefox.

Et nous avons discuté de la pertinence d'utiliserSpring Security X.509 client authentication, c'est donc à vous de décider de l'implémenter ou non dans votre application Web.

Et pour conclure, vous trouverez le code source de cet articleon Github.