{"id":19044665,"url":"https://github.com/pkini2002/jwt-authentication-springboot","last_synced_at":"2025-09-07T03:31:24.065Z","repository":{"id":196342898,"uuid":"695468746","full_name":"pkini2002/JWT-Authentication-SpringBoot","owner":"pkini2002","description":"JWT Authentication API using Spring Boot 3.1.4 (Using Spring Security + Lombok + Spring Web dependencies)","archived":false,"fork":false,"pushed_at":"2023-09-24T07:30:18.000Z","size":103,"stargazers_count":18,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-08T22:46:57.294Z","etag":null,"topics":["intellij","java","jsonwebtoken","jwt-authentication","lombok","postman-testing","spring-boot","spring-security-jwt","spring-web"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pkini2002.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-09-23T09:24:41.000Z","updated_at":"2024-11-05T09:00:36.000Z","dependencies_parsed_at":"2023-09-29T12:08:24.362Z","dependency_job_id":null,"html_url":"https://github.com/pkini2002/JWT-Authentication-SpringBoot","commit_stats":null,"previous_names":["pkini2002/jwt-authentication-springboot"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkini2002%2FJWT-Authentication-SpringBoot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkini2002%2FJWT-Authentication-SpringBoot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkini2002%2FJWT-Authentication-SpringBoot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkini2002%2FJWT-Authentication-SpringBoot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pkini2002","download_url":"https://codeload.github.com/pkini2002/JWT-Authentication-SpringBoot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232168858,"owners_count":18482484,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["intellij","java","jsonwebtoken","jwt-authentication","lombok","postman-testing","spring-boot","spring-security-jwt","spring-web"],"created_at":"2024-11-08T22:47:01.199Z","updated_at":"2025-01-02T08:18:27.530Z","avatar_url":"https://github.com/pkini2002.png","language":"Java","readme":"# JWT-Authentication using SpringBoot 3.1.4\n\nJWT stands for JSON Web Token. They are a popular way to implement authentication and authorization in web applications. \n\nA JWT is made up of three parts:\n\u003cbr\u003e\n- `Header` : The header contains information about the token, such as the type of token (JWT) and the signing algorithm used.\n- `Payload` : The payload is the main body of the token and contains the claims, which are statements about the user or other entity.\n- `Signature` : The signature is used to verify the token's integrity. It is created by signing the header and payload with a secret or public/private key pair.\n\n\u003cbr\u003e\n\nWhen a user logs in to a web application, the server generates a JWT and sends it back to the client. The client can then store the token in local storage or session storage.\nWhen the user makes subsequent requests to the server, the client includes the JWT in the request header. The server can then verify the token and authenticate the user.\n\n\u003cbr\u003e\n\n## Architecture of JWT Authentication Flow\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/pkini2002/NMAMIT-CSE-Labs-2020-24/assets/84091455/c39f242b-8d08-4a4d-92b5-74f76cdf6be0\" width=\"500\"\u003e\u003c/p\u003e\n\n## Steps to implement the project\n\n- Navigate to \u003ca href=\"https://start.spring.io/\"\u003eSpring Initializr \u003c/a\u003e and create a new Spring Boot Project\n\n  \u003cbr\u003e\n\n### Specifications\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003eType\u003c/th\u003e\n    \u003cth\u003eValue\u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eLanguage\u003c/td\u003e\n    \u003ctd\u003eJava\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eBuild Automation tool\u003c/td\u003e\n    \u003ctd\u003eMaven\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eSpring Boot Version\u003c/td\u003e\n    \u003ctd\u003e3.1.4\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003ePackaging\u003c/td\u003e\n    \u003ctd\u003eJAR\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eJava Version\u003c/td\u003e\n    \u003ctd\u003e17\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\u003cbr\u003e\n\n### Dependencies Used\n\n- Web Dependency\n\u003cbr\u003e\n\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n    \u003cartifactId\u003espring-boot-starter-web\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\n\n\u003cbr\u003e\n\n- Security\n\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n    \u003cartifactId\u003espring-boot-starter-security\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\n\n\u003cbr\u003e\n\n- Lombok\n\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.projectlombok\u003c/groupId\u003e\n    \u003cartifactId\u003elombok\u003c/artifactId\u003e\n    \u003coptional\u003etrue\u003c/optional\u003e\n\u003c/dependency\u003e\n```\n\n\u003cbr\u003e\n\n- JWT Dependencies\n\u003cbr\u003e\n\n```\n \u003c!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.jsonwebtoken\u003c/groupId\u003e\n    \u003cartifactId\u003ejjwt-api\u003c/artifactId\u003e\n    \u003cversion\u003e0.11.5\u003c/version\u003e\n\u003c/dependency\u003e\n\n\n     \u003c!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.jsonwebtoken\u003c/groupId\u003e\n    \u003cartifactId\u003ejjwt-impl\u003c/artifactId\u003e\n    \u003cversion\u003e0.11.5\u003c/version\u003e\n    \u003cscope\u003eruntime\u003c/scope\u003e\n\u003c/dependency\u003e\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.jsonwebtoken\u003c/groupId\u003e\n    \u003cartifactId\u003ejjwt-jackson\u003c/artifactId\u003e \u003c!-- or jjwt-gson if Gson is preferred --\u003e\n    \u003cversion\u003e0.11.5\u003c/version\u003e\n    \u003cscope\u003eruntime\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n\u003cbr\u003e\n\n### Steps\n\n- Create an Endpoint to be secured by creating a controller package in order to create views\n\u003cbr\u003e\n\n```\n@RestController\npublic class HomeController {\n    Logger logger = LoggerFactory.getLogger(HomeController.class);\n    @RequestMapping(\"/test\")\n    public String test() {\n        this.logger.warn(\"This is working message\");\n        return \"Testing message\";\n    }\n}\n```\n\n\u003cbr\u003e\n\n- Create In-Memory User with UserDetailService Bean\n\u003cbr\u003e\n\n```\n@Configuration\nclass MyConfig {\n    @Bean\n    public UserDetailsService userDetailsService() {\n        UserDetails userDetails = User.builder().\n                username(\"DURGESH\")\n                .password(passwordEncoder().encode(\"DURGESH\")).roles(\"ADMIN\").\n                build();\n        return new InMemoryUserDetailsManager(userDetails);\n    }\n\n    @Bean\n    public PasswordEncoder passwordEncoder() {\n        return new BCryptPasswordEncoder();\n    }\n\n    @Bean\n    public AuthenticationManager authenticationManager(AuthenticationConfiguration builder) throws Exception {\n        return builder.getAuthenticationManager();\n    }\n}\n```\n\n\u003cbr\u003e\n\n### Steps to implement JWT Token\n\u003cbr\u003e\n\n- Make sure `spring-boot-starter-security` is there in pom.xml\n\n\u003cbr\u003e\n\n- Create Class `JWTAthenticationEntryPoint` that implements `AuthenticationEntryPoint`. The method of this class is called whenever an exception is thrown due to an\n\n\u003cbr\u003e\n\n- Unauthenticated user trying to access the resource that required authentication.\n\n\u003cbr\u003e\n\n```\n@Component\npublic class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {\n    @Override\n    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {\n        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);\n        PrintWriter writer = response.getWriter();\n        writer.println(\"Access Denied !! \" + authException.getMessage());\n    }\n}\n```\n\n\u003cbr\u003e\n\n- Create the `JWTHelper` class This class contains a method related to perform operations with jwt tokens like generateToken, validateToken, etc.\n\n\u003cbr\u003e\n\n```\n@Component\npublic class JwtHelper {\n\n    //requirement :\n    public static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;\n\n    //    public static final long JWT_TOKEN_VALIDITY =  60;\n    private String secret = \"afafasfafafasfasfasfafacasdasfasxASFACASDFACASDFASFASFDAFASFASDAADSCSDFADCVSGCFVADXCcadwavfsfarvf\";\n\n    //retrieve username from jwt token\n    public String getUsernameFromToken(String token) {\n        return getClaimFromToken(token, Claims::getSubject);\n    }\n\n    //retrieve expiration date from jwt token\n    public Date getExpirationDateFromToken(String token) {\n        return getClaimFromToken(token, Claims::getExpiration);\n    }\n\n    public \u003cT\u003e T getClaimFromToken(String token, Function\u003cClaims, T\u003e claimsResolver) {\n        final Claims claims = getAllClaimsFromToken(token);\n        return claimsResolver.apply(claims);\n    }\n\n    //for retrieveing any information from token we will need the secret key\n    private Claims getAllClaimsFromToken(String token) {\n        return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();\n    }\n\n    //check if the token has expired\n    private Boolean isTokenExpired(String token) {\n        final Date expiration = getExpirationDateFromToken(token);\n        return expiration.before(new Date());\n    }\n\n    //generate token for user\n    public String generateToken(UserDetails userDetails) {\n        Map\u003cString, Object\u003e claims = new HashMap\u003c\u003e();\n        return doGenerateToken(claims, userDetails.getUsername());\n    }\n\n    //while creating the token -\n    //1. Define  claims of the token, like Issuer, Expiration, Subject, and the ID\n    //2. Sign the JWT using the HS512 algorithm and secret key.\n    //3. According to JWS Compact Serialization(https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-3.1)\n    //   compaction of the JWT to a URL-safe string\n    private String doGenerateToken(Map\u003cString, Object\u003e claims, String subject) {\n\n        return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))\n                .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))\n                .signWith(SignatureAlgorithm.HS512, secret).compact();\n    }\n\n    //validate token\n    public Boolean validateToken(String token, UserDetails userDetails) {\n        final String username = getUsernameFromToken(token);\n        return (username.equals(userDetails.getUsername()) \u0026\u0026 !isTokenExpired(token));\n    }\n}\n```\n\n\u003cbr\u003e\n\n- Create `JWTAuthenticationFilter` that extends `OncePerRequestFilter` and override method and write the logic to check the token that is comming in header. We have to write 5 important logic\n     - Get Token from request\n     - Validate Token\n     - GetUsername from token\n     - Load user associated with this token\n     - Set Authentication\n\u003cbr\u003e\n\n```\n@Component\npublic class JwtAuthenticationFilter extends OncePerRequestFilter {\n    private Logger logger = LoggerFactory.getLogger(OncePerRequestFilter.class);\n    @Autowired\n    private JwtHelper jwtHelper;\n    @Autowired\n    private UserDetailsService userDetailsService;\n\n    @Override\n    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {\n        //Authorization\n        String requestHeader = request.getHeader(\"Authorization\");\n        //Bearer 2352345235sdfrsfgsdfsdf\n        logger.info(\" Header :  {}\", requestHeader);\n        String username = null;\n        String token = null;\n        if (requestHeader != null \u0026\u0026 requestHeader.startsWith(\"Bearer\")) {\n            //looking good\n            token = requestHeader.substring(7);\n            try {\n                username = this.jwtHelper.getUsernameFromToken(token);\n            } catch (IllegalArgumentException e) {\n                logger.info(\"Illegal Argument while fetching the username !!\");\n                e.printStackTrace();\n            } catch (ExpiredJwtException e) {\n                logger.info(\"Given jwt token is expired !!\");\n                e.printStackTrace();\n            } catch (MalformedJwtException e) {\n                logger.info(\"Some changed has done in token !! Invalid Token\");\n                e.printStackTrace();\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        } else {\n            logger.info(\"Invalid Header Value !! \");\n        }\n        if (username != null \u0026\u0026 SecurityContextHolder.getContext().getAuthentication() == null) {\n            //fetch user detail from username\n            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);\n            Boolean validateToken = this.jwtHelper.validateToken(token, userDetails);\n            if (validateToken) {\n                //set the authentication\n                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());\n                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));\n                SecurityContextHolder.getContext().setAuthentication(authentication);\n            } else {\n                logger.info(\"Validation fails !!\");\n            }\n        }\n        filterChain.doFilter(request, response);\n    }\n}\n```\n\n\u003cbr\u003e\n\n- Configure spring security in configuration file:\n\n\u003cbr\u003e\n\n```\n@Configuration\npublic class SecurityConfig {\n    @Autowired\n    private JWTAthenticationEntryPoint point;\n    @Autowired\n    private JWTAuthenticationFilter filter;\n\n    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n        // configuration\n        http.csrf(csrf-\u003ecsrf.disable())\n                .cors(cors-\u003ecors.disable())\n                .authorizeHttpRequests(auth-\u003eauth.requestMatchers(\"/home/**\").authenticated()\n                        .requestMatchers(\"/auth/login\").permitAll().anyRequest()\n                        .authenticated())\n                        .exceptionHandling(ex-\u003eex.authenticationEntryPoint(point))\n                        .sessionManagement(session-\u003esession.sessionCreationPolicy(SessionCreationPolicy.STATELESS));\n        http.addFilterBefore(filter,UsernamePasswordAuthenticationFilter.class);\n        return http.build();\n    }\n}\n```\n\u003cbr\u003e\n\n- Create `JWTRequest` and `JWTResponse` in models package to receive request data and send a Login success response.\n\n\u003e JWTRequest\n\n\u003cbr\u003e\n\n```\n@Getter\n@Setter\n@NoArgsConstructor\n@AllArgsConstructor\n@Builder\n@ToString\npublic class JwtRequest {\n    private String email;\n    private String password;\n}\n\n```\n\u003cbr\u003e\n\n\u003e JWTResponse\n\n```\n@Getter\n@Setter\n@NoArgsConstructor\n@AllArgsConstructor\n@Builder\n@ToString\npublic class JwtResponse {\n    private String jwtToken;\n    private String username;\n}\n\n```\n\n\u003cbr\u003e\n\n- Create login api to accept username and password and return token if username and password is correct.\n\n\u003cbr\u003e\n\n```\n@RestController\n@RequestMapping(\"/auth\")\npublic class AuthController {\n    @Autowired\n    private UserDetailsService userDetailsService;\n\n    @Autowired\n    private AuthenticationManager manager;\n    @Autowired\n    private JwtHelper helper;\n    private Logger logger = LoggerFactory.getLogger(AuthController.class);\n    @PostMapping(\"/login\")\n    public ResponseEntity\u003cJwtResponse\u003e login(@RequestBody JwtRequest request) {\n\n        this.doAuthenticate(request.getEmail(), request.getPassword());\n        UserDetails userDetails = userDetailsService.loadUserByUsername(request.getEmail());\n        String token = this.helper.generateToken(userDetails);\n\n        JwtResponse response = JwtResponse.builder()\n                .jwtToken(token)\n                .username(userDetails.getUsername()).build();\n        return new ResponseEntity\u003c\u003e(response, HttpStatus.OK);\n    }\n\n    private void doAuthenticate(String email, String password) {\n\n        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(email, password);\n        try {\n            manager.authenticate(authentication);\n        } catch (BadCredentialsException e) {\n            throw new BadCredentialsException(\" Invalid Username or Password  !!\");\n        }\n    }\n\n    @ExceptionHandler(BadCredentialsException.class)\n    public String exceptionHandler() {\n        return \"Credentials Invalid !!\";\n    }\n}\n```\n\u003cbr\u003e\n\n- Test the application\n     \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpkini2002%2Fjwt-authentication-springboot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpkini2002%2Fjwt-authentication-springboot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpkini2002%2Fjwt-authentication-springboot/lists"}