Created
December 30, 2023 08:42
-
-
Save goodylili/f93485b16147dfac2c8c1e7ce5ce73d5 to your computer and use it in GitHub Desktop.
GitHub OAuth Golang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"encoding/json" | |
"fmt" | |
"golang.org/x/oauth2" | |
"golang.org/x/oauth2/github" | |
"io" | |
"net/http" | |
) | |
var ( | |
// Configuration for GitHub OAuth | |
GitHubOAuthConfig = &oauth2.Config{ | |
RedirectURL: "http://localhost:8080/auth/callback", | |
ClientID: "", | |
ClientSecret: "", | |
Scopes: []string{"user:email"}, | |
Endpoint: github.Endpoint, | |
} | |
oauthStateString = "random" // Replace this with a random state string for production | |
) | |
// GitHubUser represents the GitHub user information | |
type GitHubUser struct { | |
ID int `json:"id"` | |
Username string `json:"login"` // GitHub username | |
AvatarURL string `json:"avatar_url"` | |
Email string `json:"email"` | |
} | |
// HandleGitHubLogin redirects the user to the GitHub login page | |
func HandleGitHubLogin(w http.ResponseWriter, r *http.Request) { | |
url := GitHubOAuthConfig.AuthCodeURL(oauthStateString) | |
http.Redirect(w, r, url, http.StatusTemporaryRedirect) | |
} | |
// HandleGitHubCallback processes the OAuth callback from GitHub | |
func HandleGitHubCallback(w http.ResponseWriter, r *http.Request) { | |
user, err := GetUserInfo(r.URL.Query().Get("state"), r.URL.Query().Get("code")) | |
if err != nil { | |
fmt.Println(err.Error()) | |
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) | |
return | |
} | |
jsonData, err := json.Marshal(user) | |
if err != nil { | |
http.Error(w, err.Error(), http.StatusInternalServerError) | |
return | |
} | |
w.Header().Set("Content-Type", "application/json") | |
w.Write(jsonData) | |
} | |
// GetUserInfo retrieves the user information from GitHub | |
func GetUserInfo(state string, code string) (GitHubUser, error) { | |
var user GitHubUser | |
if state != oauthStateString { | |
return user, fmt.Errorf("invalid oauth state") | |
} | |
token, err := GitHubOAuthConfig.Exchange(context.TODO(), code) | |
if err != nil { | |
return user, fmt.Errorf("code exchange failed: %s", err.Error()) | |
} | |
client := &http.Client{} | |
req, err := http.NewRequest("GET", "https://api.github.com/user", nil) | |
if err != nil { | |
return user, fmt.Errorf("failed creating request: %s", err.Error()) | |
} | |
req.Header.Set("Authorization", "Bearer "+token.AccessToken) | |
resp, err := client.Do(req) | |
if err != nil { | |
return user, fmt.Errorf("failed getting user info: %s", err.Error()) | |
} | |
defer resp.Body.Close() | |
contents, err := io.ReadAll(resp.Body) | |
if err != nil { | |
return user, fmt.Errorf("failed reading response body: %s", err.Error()) | |
} | |
err = json.Unmarshal(contents, &user) | |
if err != nil { | |
return user, fmt.Errorf("failed unmarshalling user info: %s", err.Error()) | |
} | |
return user, nil | |
} | |
func main() { | |
http.HandleFunc("/login", HandleGitHubLogin) | |
http.HandleFunc("/auth/callback", HandleGitHubCallback) | |
fmt.Println("Starting server on :8080...") | |
http.ListenAndServe(":8080", nil) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment