Spring Security - Github Login

Let us create an example Spring Security OAuth 2.0 application

Register Client App

You need to register your application with a OAuth 2.0 provider before you use OAuth 2.0 in your application.

Login to github.com, then go to Settings > Developer settings. Press New Auth APP to add a new OAuth App

Register a new OAuth application. Set Authorization callback URL to be http://localhost:8080/login/oauth2/code/github

Authorization callback URL is actually the redirect URL. This redirect URL is used for sending authorization code from Authorization Server to the Client. By default, Spring Boot configures this redirect URI as /login/oauth2/code/{registrationId}. Some examples are

After registration, you will get a client ID and client secret for the client app.

Maven Dependency

Add oauth2-client maven dependency to Spring Boot Application

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

application.yml

Add client registration for Github. Spring Security will configure a ClientRegistration for us.

application.yml

1
2
3
4
5
6
7
8
9
spring:
security:
oauth2:
client:
registration:
github:
clientId: <client-id>
clientSecret: <client-secret>
scope: read:user, user:email

You can specify scopes for Github Client App. This page shows all the available scopes you can use: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/

Security configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated();

http.oauth2Login()
.loginPage("/login.html")
.defaultSuccessUrl("/")
.permitAll();

http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
.deleteCookies("true")
.logoutSuccessUrl("/login.html?logout")
.permitAll();
}
}

SecurityConfiguration class customize OAuth 2.0 login. It sets the loginPage(“/login.html”).

login.html

This is the login page.

static/login.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Oauth2.0 Github Login</title>
</head>
<body>
<div>
Login with <a href="/oauth2/authorization/github">Github</a>
</div>
</body>
</html>

Here the login URL is /oauth2/authorization/github. This is the Authorization Endpoint. It can be customized in OAuth2 configuration.

Controller

Controller that displays user info

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@RestController
class HelloController {
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;

@GetMapping(value="/")
public String sayHello(@AuthenticationPrincipal OAuth2User principal) {
return "Hello, " + principal.getAttribute("name");
}

@GetMapping(value="/getAuthentication", produces="application/json")
public String getAuthentication(OAuth2AuthenticationToken authenticaiton) {
return authenticaiton.toString();
}

@GetMapping(value = "/getEmails", produces = "application/json")
public String getEmails(OAuth2AuthenticationToken authentication) {
OAuth2AuthorizedClient client = authorizedClientService.loadAuthorizedClient(
authentication.getAuthorizedClientRegistrationId(),
authentication.getPrincipal().getName());

String getEmailUrl = "https://api.github.com/user/emails";

// send HTTP request to get user emails
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + client.getAccessToken().getTokenValue());
HttpEntity entity = new HttpEntity("", headers);
ResponseEntity response = restTemplate.exchange(getEmailUrl, HttpMethod.GET, entity, String.class);
return response.getBody().toString();
}
}

Three endpoints are created here.

  • “/“ prints principal name. Here you need @AuthenticationPrincipal annotation to get OAuth2User from Authenticaiton.
  • “/getAuthenticaiont” prints the whole Authentication Object.
  • “/getEmails” demonstrate how to get additional resource by attaching access token to the Http Request.

Github API provides an endpoint(https://api.github.com/user/emails) to get user’s emails. You need to have user:email scope to access the email information. see https://developer.github.com/v3/users/emails/#list-email-addresses-for-the-authenticated-user for more information on this Github API endpoint

Test

Open http://localhost:8080 and login with Github.

You will receive index page that displays user name. open http://localhost:8080/getEmails to get defailed user emails from Github.

Source Code for Github OAuth 2.0 login: https://github.com/xinghua24/SpringBootExamples/tree/master/OAuth2Github

Source Code for Google OAuth 2.0 login: https://github.com/xinghua24/SpringBootExamples/tree/master/OAuth2Google

Google OAuth 2.0 login is very similar to Github OAuth 2.0 login. The biggest difference is you register the OAuth 2.0 Client App at Google API Console instead.

Reference