Intégrer pismile avec Spring Boot
Connexion OIDC avec Spring Security, comptes locaux liés au sub, déconnexion complète.
Ce guide construit une application Spring Boot 3 où les utilisateurs se connectent avec pismile. À la première connexion, un compte local est créé et lié au sub de l'utilisateur. Durée : 15 minutes.
Ajoutez les dépendances
pom.xml<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency>Déclarez pismile
application.propertiesserver.port=8090 spring.security.oauth2.client.registration.pismile.client-id=VOTRE_CLIENT_ID spring.security.oauth2.client.registration.pismile.client-secret=${PISMILE_CLIENT_SECRET} spring.security.oauth2.client.registration.pismile.client-name=pismile spring.security.oauth2.client.registration.pismile.client-authentication-method=client_secret_basic spring.security.oauth2.client.registration.pismile.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.pismile.scope=openid,profile spring.security.oauth2.client.registration.pismile.redirect-uri={baseUrl}/login/oauth2/code/{registrationId} spring.security.oauth2.client.provider.pismile.issuer-uri=https://pismile.comAu démarrage, Spring lit
https://pismile.com/.well-known/openid-configurationet trouve seul les endpoints et les clés de signature.Créez le compte local
Le
subest la clé du compte : jamais le nom.Account.java@Entity @Table(name = "accounts") public class Account { @Id @GeneratedValue(strategy = GenerationType.UUID) private UUID id; @Column(name = "pismile_sub", nullable = false, unique = true) private String pismileSub; @Column(name = "verified_name") private String verifiedName; @Column(name = "country", length = 2) private String country; @Column(name = "category", length = 1) private String category; @Column(name = "last_login_at") private Instant lastLoginAt; protected Account() { } public Account(String pismileSub) { this.pismileSub = pismileSub; } public void refresh(String name, String country, String category) { this.verifiedName = name; this.country = country; this.category = category; this.lastLoginAt = Instant.now(); } public String getVerifiedName() { return verifiedName; } public String getCountry() { return country; } public String getCategory() { return category; } }AccountRepository.javapublic interface AccountRepository extends JpaRepository<Account, UUID> { Optional<Account> findByPismileSub(String pismileSub); }Liez chaque connexion au compte
Ce service est appelé à chaque connexion réussie : il crée le compte la première fois, puis met à jour le nom et le pays.
PismileUserService.java@Service public class PismileUserService extends OidcUserService { private final AccountRepository accounts; public PismileUserService(AccountRepository accounts) { this.accounts = accounts; } @Override @Transactional public OidcUser loadUser(OidcUserRequest request) { OidcUser user = super.loadUser(request); Account account = accounts.findByPismileSub(user.getSubject()) .orElseGet(() -> accounts.save(new Account(user.getSubject()))); account.refresh(user.getFullName(), user.getClaimAsString("pismile_country"), user.getClaimAsString("pismile_category")); return user; } }Configurez la sécurité
PKCE à l'aller, compte local au retour, déconnexion de votre site et de pismile.
SecurityConfig.java@Configuration @EnableWebSecurity public class SecurityConfig { @Bean SecurityFilterChain security(HttpSecurity http, ClientRegistrationRepository registrations, PismileUserService pismileUserService) throws Exception { DefaultOAuth2AuthorizationRequestResolver resolver = new DefaultOAuth2AuthorizationRequestResolver(registrations, "/oauth2/authorization"); resolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce()); OidcClientInitiatedLogoutSuccessHandler logout = new OidcClientInitiatedLogoutSuccessHandler(registrations); logout.setPostLogoutRedirectUri("{baseUrl}/"); http .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/error", "/css/**").permitAll() .anyRequest().authenticated()) .oauth2Login(login -> login .authorizationEndpoint(endpoint -> endpoint.authorizationRequestResolver(resolver)) .userInfoEndpoint(userInfo -> userInfo.oidcUserService(pismileUserService)) .defaultSuccessUrl("/compte", true)) .logout(out -> out.logoutSuccessHandler(logout)); return http.build(); } }Affichez le compte
AccountController.java@Controller public class AccountController { private final AccountRepository accounts; public AccountController(AccountRepository accounts) { this.accounts = accounts; } @GetMapping("/") String home() { return "home"; } @GetMapping("/compte") String account(@AuthenticationPrincipal OidcUser user, Model model) { model.addAttribute("account", accounts.findByPismileSub(user.getSubject()).orElseThrow()); return "account"; } }templates/home.html<a href="/oauth2/authorization/pismile">Se connecter avec pismile</a>templates/account.html<h1>Bonjour <span th:text="${account.verifiedName}">AWA MENSAH</span></h1> <p> Pays : <span th:text="${account.country}">TG</span> · Catégorie : <span th:text="${account.category}">P</span> </p> <form th:action="@{/logout}" method="post"> <button type="submit">Se déconnecter</button> </form>Testez
Terminalexport PISMILE_CLIENT_SECRET=votre_secret ./mvnw spring-boot:runOuvrez
http://localhost:8090, connectez-vous avec un alias de test du sandbox BCEAO, confirmez la demande dans le playground : vous arrivez sur/compte, et une ligne apparaît dans la tableaccounts.
Cette page vous a-t-elle aidé ?
Merci, votre avis nous aide à améliorer la documentation.