Implement discord authentication

Hi, im tring to add login with discord in my nextjs and springboot application but i can't find what should be the best way to implement it, i reimplemented in a lot of different ways but nothing seems the right way to do it.
35 Replies
JavaBot
JavaBotβ€’7d ago
βŒ› This post has been reserved for your question.
Hey @π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.
straightface
straightfaceβ€’7d ago
what do you mean? show us examples this servers bot uses discord4j https://github.com/Java-Discord/JavaBot
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
Im creating a discord bot with a web interaface, and i need to make the user login on the website using the discord oauth2 service, but i don't know how to do it without any security vunerability
@RequestMapping("discord")
@Async
public CompletableFuture<ResponseEntity<?>> loginWithDiscord(@RequestParam(name = "code") String code) {
return discordOAuthService.getAccessTokenFromCode(code).thenApply(optAccessToken -> optAccessToken
.map(accessToken -> {
String sessionId = userSessionService.createSession(accessToken.token(), accessToken.refreshToken(), accessToken.expiresIn());

ResponseCookie cookie = ResponseCookie.from(SESSION_COOKIE)
.value(sessionId)
.domain("localhost")
.path("/")
.maxAge(accessToken.expiresIn())
.httpOnly(true)
.build();

return ResponseEntity.status(HttpStatus.FOUND)
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.header(HttpHeaders.LOCATION, "http://localhost:3000")
.build();
})

.orElse(ResponseEntity.badRequest().build()));
}
@RequestMapping("discord")
@Async
public CompletableFuture<ResponseEntity<?>> loginWithDiscord(@RequestParam(name = "code") String code) {
return discordOAuthService.getAccessTokenFromCode(code).thenApply(optAccessToken -> optAccessToken
.map(accessToken -> {
String sessionId = userSessionService.createSession(accessToken.token(), accessToken.refreshToken(), accessToken.expiresIn());

ResponseCookie cookie = ResponseCookie.from(SESSION_COOKIE)
.value(sessionId)
.domain("localhost")
.path("/")
.maxAge(accessToken.expiresIn())
.httpOnly(true)
.build();

return ResponseEntity.status(HttpStatus.FOUND)
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.header(HttpHeaders.LOCATION, "http://localhost:3000")
.build();
})

.orElse(ResponseEntity.badRequest().build()));
}
This is the current code for the auth endpoint
straightface
straightfaceβ€’7d ago
security is hard, why do you think this is insecure>
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
I searched online i saw people setting up websecurity stuff, and im not understanding how to do it
ayylmao123xdd
ayylmao123xddβ€’7d ago
not relatable to the question but why do you use async with request mapping
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
Because i have the getAccessTokenFrom code method wich returns a completablefuture
straightface
straightfaceβ€’7d ago
yeah i dont think that works the way you think lol, try without it as well
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
public CompletableFuture<Optional<DiscordAccessTokenResponse>> getAccessTokenFromCode(String code) {
String data = String.format("grant_type=authorization_code&code=%s&redirect_uri=%s", code, redirectUri);

return webClient.post()
.uri("/token")
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Authorization", createAuthHeaderString(clientId, clientSecret))
.bodyValue(data)
.retrieve()
.bodyToMono(DiscordAccessTokenResponse.class)
.map(Optional::of)
.onErrorReturn(Optional.empty())
.doOnError(throwable -> LOGGER.error(throwable.getMessage(), throwable))
.toFuture();
}
public CompletableFuture<Optional<DiscordAccessTokenResponse>> getAccessTokenFromCode(String code) {
String data = String.format("grant_type=authorization_code&code=%s&redirect_uri=%s", code, redirectUri);

return webClient.post()
.uri("/token")
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Authorization", createAuthHeaderString(clientId, clientSecret))
.bodyValue(data)
.retrieve()
.bodyToMono(DiscordAccessTokenResponse.class)
.map(Optional::of)
.onErrorReturn(Optional.empty())
.doOnError(throwable -> LOGGER.error(throwable.getMessage(), throwable))
.toFuture();
}
So i should do .toBlocking() here?
straightface
straightfaceβ€’7d ago
no never, if you are need blocking you are doing it incorrectly just return Optional<DiscordAccessTokenResponse>
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
how? I can only return future or blocking
straightface
straightfaceβ€’7d ago
ahh you are using webclient, do you intend your endpoint to be reactive? then return Mono else just use RestClient i think for blocking apis
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
I need to make the user login and retrive the access token from discord api so i can make requests to discord getting the user information like username and server
straightface
straightfaceβ€’7d ago
have you tried this does it work?
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
Yes it does I just have issues with how to implement it The current one works but it sucks, it's just a mess to work with and i need to make contiuous database requests and api calls to discord api because im not storing the user info after retriving them from discord, but i need to retrive them from the discord api and then get my own user data and send them when the user endpoint is called But thats not the issue, i don't know how to setup the websecurity part, and i don't know what should i save in the user cookie
straightface
straightfaceβ€’7d ago
wouldnt you save tokens returned by discord?
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
Is it a good idea? could't it compromise security?
ayylmao123xdd
ayylmao123xddβ€’7d ago
you can always hash them
straightface
straightfaceβ€’7d ago
i mean someone is able to access your cookies your users have bigger problemes
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
If i create a JWT token with the discord token in it and my own database user Id?
straightface
straightfaceβ€’7d ago
what no, you need the token for api requests
ayylmao123xdd
ayylmao123xddβ€’7d ago
oh lmao i thought you meant storing them in a db
straightface
straightfaceβ€’7d ago
even for storing in database hashing makes no sense this isnt a password
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
The token i need to save is the discord user oauth2 token Is something like this possibile?
straightface
straightfaceβ€’7d ago
yeah its possible
straightface
straightfaceβ€’7d ago
so your application will make discord api call only for username/email?
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
for username, emain, avatar, guilds and similar stuff
straightface
straightfaceβ€’7d ago
then store token on your server not in cookies
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
so i should only send a JWT token containing my database userid? and the user table should contain the token and the refresh token?
straightface
straightfaceβ€’7d ago
yep encrypted of course
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
should i cache it in redis? because for things like retriving the guilds i don't need any data from my database but only the discord token
straightface
straightfaceβ€’7d ago
thats up to you if you like redis then thats fine
things like retriving the guilds i don't need any data from my database but only the discord token
wouldnt you run into rate limits?
π“–π“Ύπ“»π”€π“²πŸ‘πŸŽ
O right, im caching the guilds so there is no need, my bad
JavaBot
JavaBotβ€’7d ago
πŸ’€ Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived. If your question was not answered yet, feel free to re-open this post or create a new one. In case your post is not getting any attention, you can try to use /help ping. Warning: abusing this will result in moderative actions taken against you.

Did you find this page helpful?