Skip to content

Instantly share code, notes, and snippets.

@KaiserWerk
Last active August 18, 2024 15:10
Show Gist options
  • Save KaiserWerk/322b5ee66eed7826da459204d70c3397 to your computer and use it in GitHub Desktop.
Save KaiserWerk/322b5ee66eed7826da459204d70c3397 to your computer and use it in GitHub Desktop.
Quick and dirty example for a discord social login with Golang
<!doctype html>
<html>
<head>
</head>
<body>
<h2>Discord login</h2>
Token: {{ .Token }}
<br><br>
Login URL: <a href="{{ .AuthURL }}">Authorize me!</a>
<br><br>
User Info:<br><br>
<pre>
{{ .UserInfo }}
</pre>
</body>
</html>
package main
import (
"fmt"
"io"
"net/http"
"path"
"text/template"
"net/url"
"encoding/json"
"strings"
)
type accessTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn uint `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
Scope string `json:"scope"`
}
type UserInfo struct {
ID string `json:"id"`
Username string `json:"username"`
GlobalName string `json:"global_name"`
MfaEnabled bool `json:"mfa_enabled"`
Locale string `json:"locale"`
Email string `json:"email"`
Verified bool `json:"verified"`
}
var (
token = ""
redirectURL = "http://localhost:8080/callback"
authURL = "<your generated authorization url here>"
tokenURL = "https://discord.com/api/oauth2/token"
clientID = "<your client id here>"
clientSecret = "<your client secret here>"
apiURL = "https://discord.com/api"
client = http.Client{}
userInfo UserInfo
rawUserInfo string
)
func main() {
http.HandleFunc("/", handleAuthInit)
http.HandleFunc("/callback", handleCallback)
fmt.Println("starting up server on :8080...")
http.ListenAndServe(":8080", nil)
}
func handleAuthInit(w http.ResponseWriter, r *http.Request) {
if token != "" {
getUserInfo()
}
data := struct {
Token string
AuthURL string
UserInfo string
}{
Token: token,
AuthURL: authURL,
UserInfo: rawUserInfo,
}
executeTemplate(w, "templates/authorize.html", data)
}
func handleCallback(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
values := url.Values{}
values.Add("grant_type", "authorization_code")
values.Add("code", code)
values.Add("redirect_uri", redirectURL)
values.Add("client_id", clientID)
values.Add("client_secret", clientSecret)
req, _ := http.NewRequest(http.MethodPost, tokenURL, strings.NewReader(values.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
panic(err)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Printf("%s\n", body)
var tokenResponse accessTokenResponse
err = json.Unmarshal(body, &tokenResponse)
if err != nil {
panic(err)
}
token = tokenResponse.AccessToken
fmt.Printf("%+v\n", tokenResponse)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func executeTemplate(w io.Writer, tmplFile string, data any) {
tmpl, err := template.New(path.Base(tmplFile)).ParseFiles(tmplFile)
if err != nil {
panic(err)
}
err = tmpl.Execute(w, data)
if err != nil {
panic(err)
}
}
func getUserInfo() {
req, _ := http.NewRequest(http.MethodGet, apiURL + "/users/@me", nil)
req.Header.Add("Authorization", "Bearer " + token);
resp, err := client.Do(req)
if err != nil {
panic(err)
}
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
panic(err)
}
var ui UserInfo
err = json.Unmarshal(body, &ui)
if err != nil {
panic(err)
}
userInfo = ui
rawUserInfo = string(body)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment