{"id":13,"date":"2024-09-10T19:47:59","date_gmt":"2024-09-10T19:47:59","guid":{"rendered":"https:\/\/marcinzygmunt.pl\/blog\/?p=13"},"modified":"2025-09-24T18:43:40","modified_gmt":"2025-09-24T18:43:40","slug":"quick-guide-jwt-authentication-in-spring-boot","status":"publish","type":"post","link":"https:\/\/marcinzygmunt.pl\/blog\/quick-guide-jwt-authentication-in-spring-boot\/","title":{"rendered":"Simple JWT Authentication in Spring Boot"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\"><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>JWT (JSON Web Token)<\/strong> is an open standard (RFC 7519) used for the secure exchange of information between parties in JSON format. It is most commonly used for <strong>authentication and authorization<\/strong> of users in web and mobile applications.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h3 class=\"wp-block-heading\">Why is JWT so popular?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83d\udd11 <strong>Stateless<\/strong> \u2013 the server doesn\u2019t need to store sessions, the token itself is enough.<\/li>\n\n\n\n<li>\u26a1 <strong>Efficient<\/strong> \u2013 the token is sent in the HTTP header and verified quickly.<\/li>\n\n\n\n<li>\ud83c\udf0d <strong>Universal<\/strong> \u2013 works across different environments (web, mobile, microservices).<\/li>\n\n\n\n<li>\ud83d\udd12 <strong>Secure<\/strong> \u2013 the digital signature guarantees that the token has not been tampered with.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In practice, it works like this: a user logs in \u2192 receives a JWT \u2192 uses it in subsequent requests to the API. Thanks to this, the application remains scalable and easy to maintain.<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6aab2530e7998&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6aab2530e7998\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"812\" height=\"788\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/marcinzygmunt.pl\/blog\/wp-content\/uploads\/2025\/09\/jwt_1.png\" alt=\"\" class=\"wp-image-22\" srcset=\"https:\/\/marcinzygmunt.pl\/blog\/wp-content\/uploads\/2025\/09\/jwt_1.png 812w, https:\/\/marcinzygmunt.pl\/blog\/wp-content\/uploads\/2025\/09\/jwt_1-300x291.png 300w, https:\/\/marcinzygmunt.pl\/blog\/wp-content\/uploads\/2025\/09\/jwt_1-768x745.png 768w\" sizes=\"auto, (max-width: 812px) 100vw, 812px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Example Implementation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Below you\u2019ll find an example of a simple <strong>JWT mechanism with Spring Boot 3<\/strong> to help you get a secure JWT-protected API up and running.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">What\u2019s included in the implementation:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Basic Auth + JWT<\/strong>: Log in with credentials, receive a JWT token, and use it for subsequent requests.<\/li>\n\n\n\n<li><strong>PostgreSQL<\/strong>: User data is stored in a real database.<\/li>\n\n\n\n<li><strong>Swagger UI<\/strong>: Explore and test all endpoints at <code>http:\/\/localhost:8088\/swagger-ui\/index.html<\/code>.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Setup in 4 Steps<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Clone the repository<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone https:\/\/github.com\/marcinzygmunt-pl\/spring-boot-jwt-basic.git\ncd spring-boot-jwt-basic\n<\/code><\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Configure PostgreSQL<\/strong><br>Edit the <code>application.yml<\/code> file with your database credentials.<\/li>\n\n\n\n<li><strong>Run the application<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/mvnw spring-boot:run\n<\/code><\/pre>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>Test endpoints in Swagger UI<\/strong><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">And that\u2019s it! You now have a fully functional JWT-secured API.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>spring-boot-jwt-basic<\/strong> was designed as a practical starter project. Within minutes, you can launch a working JWT authentication flow \u2013 without unnecessary complexity.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">See also:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>JWT with refresh<\/li>\n\n\n\n<li>JWT with refresh in CACHE<\/li>\n\n\n\n<li>JWT with refresh in HAZELCAST<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>JWT (JSON Web Token) is an open standard (RFC 7519) used for the secure exchange of information between parties in JSON format. It is most commonly used for\u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1],"tags":[9,5],"class_list":["post-13","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-jwt","tag-springboot"],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/posts\/13","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/comments?post=13"}],"version-history":[{"count":9,"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/posts\/13\/revisions"}],"predecessor-version":[{"id":153,"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/posts\/13\/revisions\/153"}],"wp:attachment":[{"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/media?parent=13"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/categories?post=13"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marcinzygmunt.pl\/blog\/wp-json\/wp\/v2\/tags?post=13"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}