made LoginHandler slightly less awful

Signed-off-by: ari melody <ari@arimelody.me>
This commit is contained in:
ari melody 2024-07-31 04:21:52 +01:00
parent 5631c4bd87
commit 4b58a27fdc
2 changed files with 87 additions and 67 deletions

View file

@ -100,64 +100,23 @@ func LoginHandler() http.Handler {
return return
} }
// let's get an oauth token! auth_token, err := discord.GetOAuthTokenFromCode(code)
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/oauth2/token", discord.API_ENDPOINT),
strings.NewReader(url.Values{
"client_id": {discord.CLIENT_ID},
"client_secret": {discord.CLIENT_SECRET},
"grant_type": {"authorization_code"},
"code": {code},
"redirect_uri": {discord.MY_REDIRECT_URI},
}.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
res, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
fmt.Printf("Failed to retrieve OAuth token: %s\n", err) fmt.Printf("Failed to retrieve discord access token: %s\n", err)
w.WriteHeader(500) w.WriteHeader(500)
w.Write([]byte("Internal server error")) w.Write([]byte("Internal server error"))
return return
} }
oauth := discord.AccessTokenResponse{} discord_user, err := discord.GetDiscordUserFromAuth(auth_token)
err = json.NewDecoder(res.Body).Decode(&oauth)
if err != nil { if err != nil {
fmt.Printf("Failed to parse OAuth response data from discord: %s\n", err) fmt.Printf("Failed to retrieve discord user information: %s\n", err)
w.WriteHeader(500)
w.Write([]byte("Internal server error"))
return
}
res.Body.Close()
discord_access_token := oauth.AccessToken
// let's get authorisation information!
req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("%s/oauth2/@me", discord.API_ENDPOINT), nil)
req.Header.Add("Authorization", "Bearer " + discord_access_token)
res, err = http.DefaultClient.Do(req)
if err != nil {
fmt.Printf("Failed to retrieve discord auth information: %s\n", err)
w.WriteHeader(500) w.WriteHeader(500)
w.Write([]byte("Internal server error")) w.Write([]byte("Internal server error"))
return return
} }
auth_info := discord.AuthInfoResponse{} if discord_user.Id != ADMIN_ID_DISCORD {
err = json.NewDecoder(res.Body).Decode(&auth_info)
if err != nil {
fmt.Printf("Failed to parse auth information from discord: %s\n", err)
w.WriteHeader(500)
w.Write([]byte("Internal server error"))
return
}
res.Body.Close()
discord_user_id := auth_info.User.Id
if discord_user_id != ADMIN_ID_DISCORD {
// TODO: unauthorized user. revoke the token // TODO: unauthorized user. revoke the token
w.WriteHeader(401) w.WriteHeader(401)
w.Write([]byte("Unauthorized")) w.Write([]byte("Unauthorized"))
@ -165,7 +124,7 @@ func LoginHandler() http.Handler {
} }
// login success! // login success!
session := CreateSession(auth_info.User.Username) session := CreateSession(discord_user.Username)
sessions = append(sessions, &session) sessions = append(sessions, &session)
cookie := http.Cookie{} cookie := http.Cookie{}

View file

@ -1,44 +1,105 @@
package discord package discord
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
)
const API_ENDPOINT = "https://discord.com/api/v10" const API_ENDPOINT = "https://discord.com/api/v10"
const CLIENT_ID = "1268013769578119208" const CLIENT_ID = "1268013769578119208"
// TODO: good GOD change this later please i beg you. we've already broken // TODO: good GOD change this later please i beg you. we've already broken
// the rules by doing this at all // the rules by doing this at all
const CLIENT_SECRET = "JUEZnixhN7BxmLIHmbECiKETMP85VT0E" const CLIENT_SECRET = "JUEZnixhN7BxmLIHmbECiKETMP85VT0E"
const REDIRECT_URI = "https://discord.com/oauth2/authorize?client_id=1268013769578119208&response_type=code&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2Fapi%2Fv1%2Fadmin%2Flogin&scope=identify" const REDIRECT_URI = "https://discord.com/oauth2/authorize?client_id=1268013769578119208&response_type=code&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2Fapi%2Fv1%2Fadmin%2Flogin&scope=identify"
// TODO: change before prod // TODO: change before prod
const MY_REDIRECT_URI = "http://127.0.0.1:8080/api/v1/admin/login" const MY_REDIRECT_URI = "http://127.0.0.1:8080/api/v1/admin/login"
type ( type (
AccessTokenResponse struct { AccessTokenResponse struct {
TokenType string `json:"token_type"` TokenType string `json:"token_type"`
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"` ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"` RefreshToken string `json:"refresh_token"`
Scope string `json:"scope"` Scope string `json:"scope"`
} }
AuthInfoResponse struct { AuthInfoResponse struct {
Application struct { Application struct {
Id string Id string
Name string Name string
Icon string Icon string
Description string Description string
Hook bool Hook bool
BotPublic bool BotPublic bool
botRequireCodeGrant bool botRequireCodeGrant bool
VerifyKey bool VerifyKey bool
} }
Scopes []string Scopes []string
Expires string Expires string
User struct { User DiscordUser
Id string }
Username string
Avatar string DiscordUser struct {
Discriminator string Id string
GlobalName string Username string
PublicFlags int Avatar string
} Discriminator string
GlobalName string
PublicFlags int
} }
) )
func GetOAuthTokenFromCode(code string) (string, error) {
// let's get an oauth token!
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/oauth2/token", API_ENDPOINT),
strings.NewReader(url.Values{
"client_id": {CLIENT_ID},
"client_secret": {CLIENT_SECRET},
"grant_type": {"authorization_code"},
"code": {code},
"redirect_uri": {MY_REDIRECT_URI},
}.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
res, err := http.DefaultClient.Do(req)
if err != nil {
return "", errors.New(fmt.Sprintf("Failed while contacting discord API: %s", err))
}
oauth := AccessTokenResponse{}
err = json.NewDecoder(res.Body).Decode(&oauth)
if err != nil {
return "", errors.New(fmt.Sprintf("Failed to parse OAuth response data from discord: %s\n", err))
}
res.Body.Close()
return oauth.AccessToken, nil
}
func GetDiscordUserFromAuth(token string) (DiscordUser, error) {
// let's get authorisation information!
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/oauth2/@me", API_ENDPOINT), nil)
req.Header.Add("Authorization", "Bearer " + token)
res, err := http.DefaultClient.Do(req)
if err != nil {
return DiscordUser{}, errors.New(fmt.Sprintf("Failed to retrieve discord auth information: %s\n", err))
}
auth_info := AuthInfoResponse{}
err = json.NewDecoder(res.Body).Decode(&auth_info)
if err != nil {
return DiscordUser{}, errors.New(fmt.Sprintf("Failed to parse auth information from discord: %s\n", err))
}
defer res.Body.Close()
return auth_info.User, nil
}