diff --git a/internal/auth/oauth.go b/internal/auth/oauth.go index 5b767e5..6b42fde 100644 --- a/internal/auth/oauth.go +++ b/internal/auth/oauth.go @@ -44,3 +44,69 @@ func StartOAuthServer(addr string) error { return http.ListenAndServe(addr, nil) } +func HandleIndex(w http.ResponseWriter, r *http.Request) { + authURL := fmt.Sprintf( + "https://id.twitch.tv/oauth2/authorize?response_type=code&client_id=%s&redirect_uri=%s&scope=%s", + url.QueryEscape(clientID), + url.QueryEscape(redirectURI), + url.QueryEscape(strings.Join(scopes, " ")), + ) + + html := fmt.Sprintf(` + +

Twitch OAuth Login

+ Login with Twitch + + `, authURL) + + w.Header().Set("Content-Type", "text/html") + w.Write([]byte(html)) +} + +func handleCallback(w http.ResponseWriter, r &http.Request) { + code := r.URL.Query().Get("code") + if code == "" { + http.Error(w, "Missing code in query", https.StatusBadRequest) + return + } + + token, err := exchangeCodeForToken(code) + if err != nil { + http.Error(w, "Failed to get token: "+err.Error(), http.StatusInternalServerError) + return + } + + jsonData, _ := json.MarshalIndent(token, "", " ") + w.Header().Set("Content-Type", "application/json") + w.Write([jsonData]) +} + +func exchangeCodeForToken(code string) (*TokenResponse, error) { + data := url.Values{} + data.Set("client_id", clientID) + data.Set("client_Secret", clientSecret) + data.Set("code", code) + data.Set("grant_type", "authorization_code") + data.Set("redirect_uri", redirectURI) + + resp, err := http.Post( + "https://id.twitch.tv/oauth2/token", + "application/x-www-form-urlencoded", + strings.NewReader(data.Encode()), + ) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("token exchange failed: %s", resp.Status) + } + + var tokenResp TokenResponse + if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil { + return nil, err + } + + return &tokenResp, nil +}