From d90552454dfdbeba83a008f041a97ba122bab40c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Tue, 8 Oct 2019 18:18:59 +0200 Subject: [PATCH] Preliminary OAuth flow --- .gitignore | 1 + auth/oauth.go | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 auth/oauth.go diff --git a/.gitignore b/.gitignore index 450ea9096..2b35ac2cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bin/gh /gh-cli +.envrc diff --git a/auth/oauth.go b/auth/oauth.go new file mode 100644 index 000000000..b6a0cd2ce --- /dev/null +++ b/auth/oauth.go @@ -0,0 +1,68 @@ +package main + +import ( + "context" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "os" + "os/exec" + "time" +) + +func main() { + port := 3999 // TODO: find available port number + state := "TODO" // replace with random unguessable value + + clientID := os.Getenv("GH_OAUTH_CLIENT_ID") + clientSecret := os.Getenv("GH_OAUTH_CLIENT_SECRET") + + q := url.Values{} + q.Set("client_id", clientID) + q.Set("redirect_uri", fmt.Sprintf("http://localhost:%d", port)) + q.Set("scope", "repo") + q.Set("state", state) + + cmd := exec.Command("open", fmt.Sprintf("https://github.com/login/oauth/authorize?%s", q.Encode())) + err := cmd.Run() + if err != nil { + panic(err) + } + + code := "" + srv := &http.Server{Addr: fmt.Sprintf(":%d", port)} + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + rq := r.URL.Query() + code = rq.Get("code") + // TODO: rq.Get("state") + w.Header().Add("content-type", "text/html") + fmt.Fprintf(w, "

You have authenticated GitHub CLI. You may now close this page.

") + time.AfterFunc(10*time.Millisecond, func() { + srv.Shutdown(context.TODO()) + }) + }) + srv.ListenAndServe() + + resp, err := http.PostForm("https://github.com/login/oauth/access_token", + url.Values{ + "client_id": {clientID}, + "client_secret": {clientSecret}, + "code": {code}, + "state": {state}, + }) + if err != nil { + panic(err) + } + + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + panic(err) + } + tokenValues, err := url.ParseQuery(string(body)) + if err != nil { + panic(err) + } + fmt.Printf("OAuth access token: %s\n", tokenValues.Get("access_token")) +}