├── .gitignore
├── src
└── main
│ ├── resources
│ └── application.properties
│ ├── webapp
│ └── login.ftl
│ └── java
│ └── com
│ └── hellokoding
│ └── sso
│ └── auth
│ ├── WebApplication.java
│ ├── JwtUtil.java
│ ├── CookieUtil.java
│ └── LoginController.java
├── README.md
├── LICENSE
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | out
3 | .settings
4 | .classpath
5 | .project
6 | .idea
7 | *.iml
8 | *.DS_Store
9 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.freemarker.template-loader-path: /
2 | spring.freemarker.suffix: .ftl
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Single Sign On (SSO) Example with JSON Web Token (JWT), Spring Boot - Authentication Service
2 |
3 | ## Guide
4 | https://hellokoding.com/hello-single-sign-on-sso-with-json-web-token-jwt-spring-boot/
5 |
6 | ## What you'll need
7 | - JDK 1.7+
8 | - Maven 3+
9 |
10 | ## Stack
11 | - Java
12 | - Spring Boot
13 | - FreeMarker
14 |
15 | ## Run
16 | - Run Authentication Service: `mvn spring-boot:run`
17 | - Run [Resource Service](https://github.com/hellokoding/hello-sso-jwt-resource) 1: `mvn spring-boot:run -Dserver.port=8180`
18 | - Run Resource Service 2: `mvn spring-boot:run -Dserver.port=8280`
19 |
--------------------------------------------------------------------------------
/src/main/webapp/login.ftl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Authentication Service
5 |
6 |
7 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/sso/auth/WebApplication.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.sso.auth;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.boot.builder.SpringApplicationBuilder;
6 | import org.springframework.boot.context.web.SpringBootServletInitializer;
7 |
8 | @SpringBootApplication
9 | public class WebApplication extends SpringBootServletInitializer {
10 | @Override
11 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
12 | return application.sources(WebApplication.class);
13 | }
14 |
15 | public static void main(String[] args) throws Exception {
16 | SpringApplication.run(WebApplication.class, args);
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/sso/auth/JwtUtil.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.sso.auth;
2 |
3 | import io.jsonwebtoken.JwtBuilder;
4 | import io.jsonwebtoken.Jwts;
5 | import io.jsonwebtoken.SignatureAlgorithm;
6 |
7 | import javax.servlet.http.HttpServletRequest;
8 | import java.util.Date;
9 |
10 | public class JwtUtil {
11 | public static String generateToken(String signingKey, String subject) {
12 | long nowMillis = System.currentTimeMillis();
13 | Date now = new Date(nowMillis);
14 |
15 | JwtBuilder builder = Jwts.builder()
16 | .setSubject(subject)
17 | .setIssuedAt(now)
18 | .signWith(SignatureAlgorithm.HS256, signingKey);
19 |
20 | return builder.compact();
21 | }
22 |
23 | public static String getSubject(HttpServletRequest httpServletRequest, String jwtTokenCookieName, String signingKey){
24 | String token = CookieUtil.getValue(httpServletRequest, jwtTokenCookieName);
25 | if(token == null) return null;
26 | return Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token).getBody().getSubject();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Hello Koding
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/sso/auth/CookieUtil.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.sso.auth;
2 |
3 | import org.springframework.web.util.WebUtils;
4 |
5 | import javax.servlet.http.Cookie;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 |
9 | public class CookieUtil {
10 | public static void create(HttpServletResponse httpServletResponse, String name, String value, Boolean secure, Integer maxAge, String domain) {
11 | Cookie cookie = new Cookie(name, value);
12 | cookie.setSecure(secure);
13 | cookie.setHttpOnly(true);
14 | cookie.setMaxAge(maxAge);
15 | cookie.setDomain(domain);
16 | cookie.setPath("/");
17 | httpServletResponse.addCookie(cookie);
18 | }
19 |
20 | public static void clear(HttpServletResponse httpServletResponse, String name) {
21 | Cookie cookie = new Cookie(name, null);
22 | cookie.setPath("/");
23 | cookie.setHttpOnly(true);
24 | cookie.setMaxAge(0);
25 | httpServletResponse.addCookie(cookie);
26 | }
27 |
28 | public static String getValue(HttpServletRequest httpServletRequest, String name) {
29 | Cookie cookie = WebUtils.getCookie(httpServletRequest, name);
30 | return cookie != null ? cookie.getValue() : null;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | hello-sso-jwt-auth
5 | hello-sso-jwt-auth
6 | hello-sso-jwt-auth
7 |
8 | org.springframework.boot
9 | spring-boot-starter-parent
10 | 1.3.5.RELEASE
11 |
12 |
13 |
14 | 1.7
15 |
16 |
17 |
18 |
19 | org.springframework.boot
20 | spring-boot-starter-freemarker
21 |
22 |
23 | io.jsonwebtoken
24 | jjwt
25 | 0.6.0
26 |
27 |
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-maven-plugin
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/sso/auth/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.sso.auth;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.ui.Model;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.bind.annotation.RequestMethod;
7 |
8 | import javax.servlet.http.HttpServletResponse;
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | @Controller
13 | public class LoginController {
14 | private static final String jwtTokenCookieName = "JWT-TOKEN";
15 | private static final String signingKey = "signingKey";
16 | private static final Map credentials = new HashMap<>();
17 |
18 | public LoginController() {
19 | credentials.put("hellokoding", "hellokoding");
20 | credentials.put("hellosso", "hellosso");
21 | }
22 |
23 | @RequestMapping("/")
24 | public String home(){
25 | return "redirect:/login";
26 | }
27 |
28 | @RequestMapping("/login")
29 | public String login(){
30 | return "login";
31 | }
32 |
33 | @RequestMapping(value = "login", method = RequestMethod.POST)
34 | public String login(HttpServletResponse httpServletResponse, String username, String password, String redirect, Model model){
35 | if (username == null || !credentials.containsKey(username) || !credentials.get(username).equals(password)){
36 | model.addAttribute("error", "Invalid username or password!");
37 | return "login";
38 | }
39 |
40 | String token = JwtUtil.generateToken(signingKey, username);
41 | CookieUtil.create(httpServletResponse, jwtTokenCookieName, token, false, -1, "localhost");
42 |
43 | return "redirect:" + redirect;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------