Skip to content

Commit be93dc5

Browse files
Merge pull request #1 from TheDeveloperDen/discord-oauth
Discord oauth2
2 parents 0f4b290 + ee83d06 commit be93dc5

8 files changed

Lines changed: 154 additions & 8 deletions

File tree

build.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ dependencies {
1313
implementation("org.springframework.boot:spring-boot-starter-data-redis")
1414
implementation("org.springframework.boot:spring-boot-starter-data-rest")
1515
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
16+
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
1617
implementation("org.springframework.boot:spring-boot-starter-security")
1718
implementation("org.springframework.boot:spring-boot-starter-web")
19+
implementation("org.mariadb.jdbc:mariadb-java-client:2.7.3")
1820
developmentOnly("org.springframework.boot:spring-boot-devtools")
1921
testImplementation("org.springframework.boot:spring-boot-starter-test")
2022
testImplementation("org.springframework.security:spring-security-test")
@@ -30,7 +32,8 @@ tasks {
3032
withType<JavaCompile> {
3133
options.encoding = "UTF-8"
3234
}
35+
3336
withType<Test> {
3437
useJUnitPlatform()
3538
}
36-
}
39+
}
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
package net.developerden.backend.controller;
22

3+
4+
import net.developerden.backend.security.DiscordUser;
35
import org.springframework.security.core.annotation.AuthenticationPrincipal;
46
import org.springframework.web.bind.annotation.GetMapping;
57
import org.springframework.web.bind.annotation.RestController;
68

79
@RestController
810
public class InfoController {
911

12+
@GetMapping("/user")
13+
public String user(@AuthenticationPrincipal DiscordUser principal) {
14+
return "Hello, %s (%s)".formatted(principal.fullName(), principal.id());
15+
}
16+
1017
@GetMapping("/ping")
1118
public String ping() {
1219
return "pong";
1320
}
14-
}
21+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package net.developerden.backend.security;
2+
3+
import org.springframework.security.core.GrantedAuthority;
4+
import org.springframework.security.oauth2.core.user.OAuth2User;
5+
6+
import java.util.Collection;
7+
import java.util.Map;
8+
9+
/* TODO we might wanna convert this to a database entity in the future so we can add more data*/
10+
11+
/**
12+
* Java representation of all of the data that Discord gives us from the /users/@me API endpoint.
13+
*/
14+
public record DiscordUser(String id, String username, String discriminator, String locale) implements OAuth2User {
15+
public String fullName() {
16+
return username + "#" + discriminator;
17+
}
18+
19+
@Override
20+
public Map<String, Object> getAttributes() {
21+
return Map.of(
22+
"id", id,
23+
"username", fullName(),
24+
"locale", locale
25+
);
26+
}
27+
28+
@Override
29+
public Collection<? extends GrantedAuthority> getAuthorities() {
30+
return null;
31+
}
32+
33+
@Override
34+
public String getName() {
35+
return fullName();
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package net.developerden.backend.security;
2+
3+
import org.springframework.http.HttpEntity;
4+
import org.springframework.http.HttpHeaders;
5+
import org.springframework.http.HttpMethod;
6+
import org.springframework.http.MediaType;
7+
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
8+
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
9+
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
10+
import org.springframework.security.oauth2.core.user.OAuth2User;
11+
import org.springframework.web.client.RestTemplate;
12+
13+
import java.util.List;
14+
15+
public class DiscordUserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
16+
private static final String DISCORD_USERINFO_URI = "https://discord.com/api/users/@me";
17+
18+
19+
@Override
20+
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
21+
final var headers = new HttpHeaders();
22+
23+
final String authorization = userRequest.getAccessToken().getTokenType().getValue() + " " + userRequest.getAccessToken().getTokenValue();
24+
headers.add("Authorization", authorization);
25+
26+
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
27+
28+
final var entity = new HttpEntity<>(headers);
29+
30+
final var user = new RestTemplate()
31+
.exchange(DISCORD_USERINFO_URI, HttpMethod.GET,
32+
entity, DiscordUser.class)
33+
.getBody();
34+
35+
return user;
36+
}
37+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package net.developerden.backend.security;
2+
3+
import org.springframework.http.HttpStatus;
4+
import org.springframework.security.config.Customizer;
5+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
7+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
8+
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
9+
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
10+
11+
import java.util.Collections;
12+
13+
@EnableWebSecurity
14+
public class OAuth2LoginConfig extends WebSecurityConfigurerAdapter {
15+
@Override
16+
protected void configure(HttpSecurity http) throws Exception {
17+
http.authorizeRequests(a ->
18+
a.antMatchers("/", "/error").permitAll()
19+
.anyRequest().authenticated()
20+
)
21+
22+
.oauth2Login()
23+
.userInfoEndpoint()
24+
.userService(new DiscordUserService());
25+
}
26+
}

src/main/resources/application.properties

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/main/resources/application.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
spring:
2+
jpa:
3+
hibernate:
4+
ddl-auto: none
5+
show-sql: true
6+
datasource:
7+
url: jdbc:mariadb://${DDB_DATABASE_URL}:3306/${DDB_DATABASE_NAME}
8+
username: ${DDB_DATABASE_USER}
9+
password: ${DDB_DATABASE_PASSWORD}
10+
driver-class-name: org.mariadb.jdbc.Driver
11+
security:
12+
oauth2:
13+
client:
14+
registration:
15+
discord:
16+
clientId: ${DDB_CLIENT_ID}
17+
clientSecret: ${DDB_CLIENT_SECRET}
18+
authorizationGrantType: authorization_code
19+
redirectUri: "{baseUrl}/login/oauth2/code/discord"
20+
scope: identify
21+
provider:
22+
discord:
23+
authorizationUri: https://discord.com/api/oauth2/authorize
24+
tokenUri: https://discord.com/api/oauth2/token
25+
26+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8"/>
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
6+
<title>Demo</title>
7+
<meta name="description" content=""/>
8+
<meta name="viewport" content="width=device-width"/>
9+
<base href="/"/>
10+
</head>
11+
<body>
12+
<h1>Demo</h1>
13+
<div class="container"></div>
14+
</body>
15+
<a href="/oauth2/authorization/discord">Login</a>
16+
</html>

0 commit comments

Comments
 (0)