{"id":134412,"date":"2025-05-30T17:46:00","date_gmt":"2025-05-30T14:46:00","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=134412"},"modified":"2025-05-29T12:57:28","modified_gmt":"2025-05-29T09:57:28","slug":"spring-security-integrate-passkeys-example","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html","title":{"rendered":"Spring Security &#8211; Integrate Passkeys Example"},"content":{"rendered":"<p>With the increasing demand for passwordless authentication, passkeys have emerged as a modern, secure alternative. Let us delve into understanding how to integrate passkeys in Spring Security.<\/p>\n<h2><a name=\"section-1\"><\/a>1. Introduction to Passkeys<\/h2>\n<p>Passkeys are a modern, passwordless authentication method designed to replace traditional passwords with a more secure and user-friendly alternative. Passkeys are based on <a href=\"https:\/\/en.wikipedia.org\/wiki\/Public-key_cryptography\" target=\"_blank\" rel=\"noopener\">public-key cryptography<\/a>, where each user\u2019s device generates a unique key pair consisting of a <em>public key<\/em> and a <em>private key<\/em>.<\/p>\n<p>When a user registers with a service using a passkey, the public key is sent to the server and stored, while the private key never leaves the user\u2019s device. During authentication, the server sends a challenge that is signed by the private key, and the signature is verified using the stored public key.<\/p>\n<p>This method makes passkeys inherently resistant to phishing, credential stuffing, and brute-force attacks, since there&#8217;s no shared secret that can be reused or stolen. It also eliminates the need to remember complex passwords or use third-party password managers.<\/p>\n<p>Passkeys are built on top of the <a href=\"https:\/\/www.w3.org\/TR\/webauthn\/\" target=\"_blank\" rel=\"noopener\">Web Authentication API (WebAuthn)<\/a> and the <a href=\"https:\/\/fidoalliance.org\/fido2\/\" target=\"_blank\" rel=\"noopener\">FIDO2 standard<\/a>, developed by the <a href=\"https:\/\/fidoalliance.org\/\" target=\"_blank\" rel=\"noopener\">FIDO Alliance<\/a>. These standards enable strong, cryptographic authentication on the web and across devices.<\/p>\n<p>Support for passkeys is rapidly growing across major ecosystems. They are natively supported by:<\/p>\n<ul>\n<li><a href=\"https:\/\/support.apple.com\/en-us\/HT213305\" target=\"_blank\" rel=\"noopener\">Apple\u2019s iOS and macOS<\/a><\/li>\n<li><a href=\"https:\/\/developer.android.com\/training\/sign-in\/passkeys\" target=\"_blank\" rel=\"noopener\">Google\u2019s Android<\/a><\/li>\n<li><a href=\"https:\/\/support.google.com\/chrome\/answer\/12819954\" target=\"_blank\" rel=\"noopener\">Google Chrome<\/a><\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/active-directory\/authentication\/howto-authentication-passwordless-security-key\" target=\"_blank\" rel=\"noopener\">Microsoft Windows<\/a><\/li>\n<\/ul>\n<p>Because passkeys are synced via cloud providers (e.g., iCloud Keychain or Google Password Manager), they can also be used seamlessly across multiple devices, enhancing both convenience and security.<\/p>\n<h2><a name=\"section-2\"><\/a>2. Adding Passkeys to Spring Boot Applications<\/h2>\n<p>To integrate passkeys, we use the WebAuthn4J library that enables WebAuthn\/FIDO2 support for Spring Boot applications.<\/p>\n<h3>2.1 Add Dependencies<\/h3>\n<p>To start using passkeys in your Spring Boot application, you need to include the necessary dependency for WebAuthn support. The <code>webauthn-spring-security<\/code> library integrates WebAuthn into Spring Security, enabling secure passwordless authentication using public-key cryptography.<\/p>\n<pre class=\"brush:xml; wrap-lines:false;\">&lt;dependency&gt;\n  &lt;groupId&gt;com.webauthn4j.springframework.security&lt;\/groupId&gt;\n  &lt;artifactId&gt;webauthn-spring-security&lt;\/artifactId&gt;\n  &lt;version&gt;latest__jar__version&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<h3>2.2 Main File<\/h3>\n<p>This is the entry point of your Spring Boot application. The <code>PasskeyApplication<\/code> class contains the <code>main<\/code> method that launches the application using Spring Boot\u2019s auto-configuration mechanism.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">package com.example.passkey;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class PasskeyApplication {\n    public static void main(String[] args) {\n        SpringApplication.run(PasskeyApplication.class, args);\n    }\n}\n<\/pre>\n<h3>2.3 Security Configuration File<\/h3>\n<p>The security configuration class integrates WebAuthn into Spring Security by applying the <code>WebAuthnSecurityFilterChainConfigurer<\/code>. It configures CSRF protection, defines open endpoints (like register and authenticate), and ensures authenticated access to other routes.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">package com.example.passkey.config;\n\nimport com.webauthn4j.springframework.security.WebAuthnSecurityConfigurer;\nimport com.webauthn4j.springframework.security.WebAuthnSecurityFilterChainConfigurer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.web.SecurityFilterChain;\n\n@Configuration\npublic class WebAuthnSecurityConfig {\n\n    @Bean\n    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n        WebAuthnSecurityFilterChainConfigurer webAuthnConfigurer = new WebAuthnSecurityFilterChainConfigurer();\n        http\n            .csrf().disable()\n            .authorizeHttpRequests(authz -&gt; authz\n                .requestMatchers(\"\/register\", \"\/authenticate\").permitAll()\n                .anyRequest().authenticated())\n            .apply(webAuthnConfigurer);\n\n        return http.build();\n    }\n}\n<\/pre>\n<h3>2.4 Entity File<\/h3>\n<p>The <code>CredentialEntity<\/code> class represents a persisted user credential. It stores essential fields such as the credential ID, user ID, public key, and signature count, and maps to a database table using JPA annotations.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java; wrap-lines:false;\">package com.example.passkey.entity;\n\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.Id;\nimport lombok.*;\n\n@Entity\n@Getter @Setter @NoArgsConstructor @AllArgsConstructor\npublic class CredentialEntity {\n    @Id\n    private String credentialId;\n    private String userId;\n    private byte[] publicKey;\n    private long signatureCount;\n}\n<\/pre>\n<h3>2.5 Repository File<\/h3>\n<p>The <code>CredentialRepository<\/code> interface provides data access methods for managing <code>CredentialEntity<\/code> objects using Spring Data JPA. It includes a custom finder method to retrieve credentials by user ID.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">package com.example.passkey.repository;\n\nimport com.example.passkey.entity.CredentialEntity;\nimport org.springframework.data.jpa.repository.JpaRepository;\n\nimport java.util.Optional;\n\npublic interface CredentialRepository extends JpaRepository&lt;CredentialEntity, String&gt; {\n    Optional&lt;CredentialEntity&gt; findByUserId(String userId);\n}\n<\/pre>\n<h3>2.6 Register Controller<\/h3>\n<p>This controller handles user registration using passkeys. It receives the client\u2019s credential data, validates it with the WebAuthn registration manager, and stores the generated public key and related metadata in the database.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">package com.example.passkey.controller;\n\nimport com.example.passkey.entity.CredentialEntity;\nimport com.example.passkey.repository.CredentialRepository;\nimport com.webauthn4j.data.RegistrationRequest;\nimport com.webauthn4j.data.RegistrationData;\nimport com.webauthn4j.data.RegistrationParameters;\nimport com.webauthn4j.springframework.security.WebAuthnRegistrationManager;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Base64;\n\n@Data\nclass RegistrationRequestDTO {\n    private String userId;\n    private CredentialDTO credential;\n}\n\n@RestController\n@RequestMapping(\"\/register\")\npublic class RegisterController {\n\n    @Autowired\n    private WebAuthnRegistrationManager registrationManager;\n\n    @Autowired\n    private CredentialRepository credentialRepository;\n\n    @PostMapping\n    public ResponseEntity&lt;?&gt; register(@RequestBody RegistrationRequestDTO request) {\n        try {\n            RegistrationRequest registrationRequest = new RegistrationRequest(\n                request.getCredential().getClientDataJSON(),\n                request.getCredential().getAttestationObject()\n            );\n\n            RegistrationData registrationData = registrationManager.parse(registrationRequest);\n            RegistrationParameters registrationParameters = new RegistrationParameters(\n                registrationData.getAttestationObject().getAuthenticatorData().getRpIdHash(),\n                false\n            );\n            registrationManager.validate(registrationData, registrationParameters);\n\n            String credentialId = Base64.getEncoder().encodeToString(registrationData.getAttestationObject().getAuthenticatorData().getAttestedCredentialData().getCredentialId());\n            byte[] publicKeyCose = registrationData.getAttestationObject().getAuthenticatorData().getAttestedCredentialData().getCredentialPublicKey().getBytes();\n\n            CredentialEntity credential = new CredentialEntity();\n            credential.setCredentialId(credentialId);\n            credential.setUserId(request.getUserId());\n            credential.setPublicKey(publicKeyCose);\n            credential.setSignatureCount(registrationData.getAttestationObject().getAuthenticatorData().getSignCount());\n\n            credentialRepository.save(credential);\n\n            return ResponseEntity.ok(\"Registration successful\");\n        } catch (Exception e) {\n            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(\"Registration failed: \" + e.getMessage());\n        }\n    }\n}\n<\/pre>\n<h4>2.6.1 Code Explanation<\/h4>\n<p>This code implements passkey-based user registration using Spring Boot and the WebAuthn4J library. The <code>RegistrationRequestDTO<\/code> class encapsulates the user ID and credential information required for registration. The <code>RegisterController<\/code> exposes a POST endpoint at <code>\/register<\/code> that receives a WebAuthn registration payload from the client. It creates a <code>RegistrationRequest<\/code> object using the <code>clientDataJSON<\/code> and <code>attestationObject<\/code> received, and parses it into <code>RegistrationData<\/code> using the <code>WebAuthnRegistrationManager<\/code>. The controller then validates the registration data against expected parameters, such as relying party ID hash. Upon successful validation, it extracts the credential ID and public key, encodes them appropriately, and stores them in a <code>CredentialEntity<\/code> object along with the user ID and signature count. This credential is then saved in the database via the <code>CredentialRepository<\/code>. If any exception occurs during parsing or validation, it returns a 400 Bad Request with an appropriate error message; otherwise, it confirms successful registration.<\/p>\n<h3>2.7 Authentication Controller<\/h3>\n<p>The authentication controller verifies login attempts by validating the credentials against stored data. It uses the WebAuthn authentication manager to parse and validate the incoming credential, updating the signature count upon successful authentication.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">package com.example.passkey.controller;\n\nimport com.example.passkey.entity.CredentialEntity;\nimport com.example.passkey.repository.CredentialRepository;\nimport com.webauthn4j.data.AuthenticationData;\nimport com.webauthn4j.data.AuthenticationParameters;\nimport com.webauthn4j.data.AuthenticationRequest;\nimport com.webauthn4j.springframework.security.WebAuthnAuthenticationManager;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.*;\n\n@Data\nclass CredentialDTO {\n    private String id;\n    private byte[] clientDataJSON;\n    private byte[] attestationObject;\n    private byte[] authenticatorData;\n    private byte[] signature;\n}\n\n@Data\nclass AuthenticationRequestDTO {\n    private CredentialDTO credential;\n}\n\n@RestController\n@RequestMapping(\"\/authenticate\")\npublic class AuthController {\n\n    @Autowired\n    private WebAuthnAuthenticationManager authenticationManager;\n\n    @Autowired\n    private CredentialRepository credentialRepository;\n\n    @PostMapping\n    public ResponseEntity&lt;?&gt; authenticate(@RequestBody AuthenticationRequestDTO request) {\n        try {\n            String credentialId = request.getCredential().getId();\n            CredentialEntity storedCredential = credentialRepository.findById(credentialId)\n                .orElseThrow(() -&gt; new RuntimeException(\"Credential not found\"));\n\n            AuthenticationRequest authenticationRequest = new AuthenticationRequest(\n                credentialId,\n                request.getCredential().getClientDataJSON(),\n                request.getCredential().getAuthenticatorData(),\n                request.getCredential().getSignature()\n            );\n\n            AuthenticationParameters authenticationParameters = new AuthenticationParameters(\n                storedCredential.getPublicKey(),\n                storedCredential.getSignatureCount()\n            );\n\n            AuthenticationData authenticationData = authenticationManager.parse(authenticationRequest);\n            authenticationManager.validate(authenticationData, authenticationParameters);\n\n            \/\/ Update signature counter\n            storedCredential.setSignatureCount(authenticationData.getAuthenticatorData().getSignCount());\n            credentialRepository.save(storedCredential);\n\n            return ResponseEntity.ok(\"Authentication successful\");\n        } catch (Exception e) {\n            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(\"Authentication failed: \" + e.getMessage());\n        }\n    }\n}\n<\/pre>\n<h4>2.7.1 Code Explanation<\/h4>\n<p>This code defines a passkey-based authentication workflow using Spring Boot and WebAuthn4J. The <code>CredentialDTO<\/code> class acts as a data carrier for WebAuthn credential fields received from the client, including the credential ID, client data, attestation object, authenticator data, and signature\u2014all in byte array form. The <code>AuthenticationRequestDTO<\/code> wraps this credential for incoming requests. The <code>AuthController<\/code> exposes a POST endpoint <code>\/authenticate<\/code> that receives these credentials, locates the corresponding stored credential in the database via <code>CredentialRepository<\/code>, and constructs an <code>AuthenticationRequest<\/code> to parse and validate the incoming WebAuthn data using the <code>WebAuthnAuthenticationManager<\/code>. If validation succeeds, it updates the signature counter in the database to prevent replay attacks and responds with a success message. If validation fails due to incorrect or tampered data, it returns a 401 Unauthorized error with the failure reason.<\/p>\n<h3>2.8 Configuration File<\/h3>\n<p>This is the application\u2019s configuration file using Spring Boot\u2019s <code>application.yml<\/code> style in plain format. It sets up an in-memory H2 database for development, enables SQL logging, and exposes the H2 console for easy inspection.<\/p>\n<pre class=\"brush:plain; wrap-lines:false;\">spring:\n  datasource:\n    url: jdbc:h2:mem:testdb\n    driver-class-name: org.h2.Driver\n    username: sa\n    password:\n  jpa:\n    hibernate:\n      ddl-auto: update\n    show-sql: true\n  h2:\n    console:\n      enabled: true\n<\/pre>\n<h3>2.9 Code Output<\/h3>\n<p>The <code>AuthController<\/code> is responsible for handling the authentication process using passkeys (WebAuthn). When a client application sends a <code>POST<\/code> request to the <code>\/authenticate<\/code> endpoint with credential data such as the credential ID, client data JSON, authenticator data, and a signature, the controller begins by extracting the credential ID. It then attempts to retrieve the corresponding <code>CredentialEntity<\/code> from the database using the <code>CredentialRepository<\/code>. If the credential is not found, the controller responds with an HTTP 401 Unauthorized status and a descriptive error message.<\/p>\n<p>If the credential exists, the controller constructs an <code>AuthenticationRequest<\/code> object from the request payload. It also creates an <code>AuthenticationParameters<\/code> object using the stored public key and signature counter, which are essential for verifying the signature and ensuring the request isn&#8217;t a replay attack. The controller then uses the <code>WebAuthnAuthenticationManager<\/code> to parse and validate the authentication request.<\/p>\n<p>If the authentication data is valid, it means the cryptographic signature is correct and the authenticator is trustworthy. The controller proceeds to update the stored signature counter to reflect the most recent authentication event and persists the updated <code>CredentialEntity<\/code> back to the database. Upon success, it returns an HTTP 200 OK response with a message indicating successful authentication.<\/p>\n<p>In case of any failure\u2014such as an invalid signature, tampered client data, a mismatch in the signature counter, or a missing credential\u2014the controller catches the exception and returns an HTTP 401 Unauthorized response, along with an error message explaining the failure. This implementation ensures a secure, passwordless login mechanism by leveraging the WebAuthn standard and public-key cryptography.<\/p>\n<h2><a name=\"section-3\"><\/a>3. Conclusion<\/h2>\n<p>Passkeys represent a future-ready approach to secure authentication. Integrating them into Spring Security with WebAuthn4J enables passwordless flows that enhance both security and user experience. With WebAuthn support expanding across ecosystems, adopting passkeys now can position your application ahead of the curve. For production systems, consider secure storage, multi-device sync, and user experience enhancements. The WebAuthn4J library is flexible, enabling custom implementations of challenge storage, credential resolution, and validation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With the increasing demand for passwordless authentication, passkeys have emerged as a modern, secure alternative. Let us delve into understanding how to integrate passkeys in Spring Security. 1. Introduction to Passkeys Passkeys are a modern, passwordless authentication method designed to replace traditional passwords with a more secure and user-friendly alternative. Passkeys are based on public-key &hellip;<\/p>\n","protected":false},"author":26931,"featured_media":242,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[125],"class_list":["post-134412","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring-security"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Security - Integrate Passkeys Example - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Spring security integrate passkeys: Secure your Spring app by integrating passkey authentication using WebAuthn and Spring Security.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Security - Integrate Passkeys Example - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Spring security integrate passkeys: Secure your Spring app by integrating passkey authentication using WebAuthn and Spring Security.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-30T14:46:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-security-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Yatin Batra\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Yatin Batra\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html\"},\"author\":{\"name\":\"Yatin Batra\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/cda31a4c1965373fed40c8907dc09b8d\"},\"headline\":\"Spring Security &#8211; Integrate Passkeys Example\",\"datePublished\":\"2025-05-30T14:46:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html\"},\"wordCount\":1123,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-security-logo.jpg\",\"keywords\":[\"Spring Security\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html\",\"name\":\"Spring Security - Integrate Passkeys Example - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-security-logo.jpg\",\"datePublished\":\"2025-05-30T14:46:00+00:00\",\"description\":\"Spring security integrate passkeys: Secure your Spring app by integrating passkey authentication using WebAuthn and Spring Security.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-security-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-security-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-security-integrate-passkeys-example.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Spring Security &#8211; Integrate Passkeys Example\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/cda31a4c1965373fed40c8907dc09b8d\",\"name\":\"Yatin Batra\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/Yatin.batra_.jpg\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/Yatin.batra_.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/Yatin.batra_.jpg\",\"caption\":\"Yatin Batra\"},\"description\":\"An experience full-stack engineer well versed with Core Java, Spring\\\/Springboot, MVC, Security, AOP, Frontend (Angular &amp; React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).\",\"sameAs\":[\"https:\\\/\\\/www.javacodegeeks.com\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/yatin-batra\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Security - Integrate Passkeys Example - Java Code Geeks","description":"Spring security integrate passkeys: Secure your Spring app by integrating passkey authentication using WebAuthn and Spring Security.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html","og_locale":"en_US","og_type":"article","og_title":"Spring Security - Integrate Passkeys Example - Java Code Geeks","og_description":"Spring security integrate passkeys: Secure your Spring app by integrating passkey authentication using WebAuthn and Spring Security.","og_url":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2025-05-30T14:46:00+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-security-logo.jpg","type":"image\/jpeg"}],"author":"Yatin Batra","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Yatin Batra","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html"},"author":{"name":"Yatin Batra","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/cda31a4c1965373fed40c8907dc09b8d"},"headline":"Spring Security &#8211; Integrate Passkeys Example","datePublished":"2025-05-30T14:46:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html"},"wordCount":1123,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-security-logo.jpg","keywords":["Spring Security"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html","url":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html","name":"Spring Security - Integrate Passkeys Example - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-security-logo.jpg","datePublished":"2025-05-30T14:46:00+00:00","description":"Spring security integrate passkeys: Secure your Spring app by integrating passkey authentication using WebAuthn and Spring Security.","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-security-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-security-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/spring-security-integrate-passkeys-example.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Spring Security &#8211; Integrate Passkeys Example"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/cda31a4c1965373fed40c8907dc09b8d","name":"Yatin Batra","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/12\/Yatin.batra_.jpg","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/12\/Yatin.batra_.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/12\/Yatin.batra_.jpg","caption":"Yatin Batra"},"description":"An experience full-stack engineer well versed with Core Java, Spring\/Springboot, MVC, Security, AOP, Frontend (Angular &amp; React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).","sameAs":["https:\/\/www.javacodegeeks.com"],"url":"https:\/\/www.javacodegeeks.com\/author\/yatin-batra"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/134412","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/26931"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=134412"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/134412\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/242"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=134412"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=134412"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=134412"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}