-
Notifications
You must be signed in to change notification settings - Fork 9
/
main.go
104 lines (86 loc) · 2.33 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package main
import (
"context"
"crypto/rand"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"sync"
"golang.org/x/oauth2"
)
type Scopes []string
func (s *Scopes) String() string {
return fmt.Sprintf("%s", *s)
}
func (s *Scopes) Set(value string) error {
*s = append(*s, value)
return nil
}
func randString() string {
buf := make([]byte, 32)
rand.Read(buf)
return base64.StdEncoding.EncodeToString(buf)
}
func main() {
var (
port = flag.Int("port", 8080, "Callback port")
path = flag.String("path", "/oauth/callback", "Callback path")
clientID = flag.String("id", "", "Client ID")
clientSecret = flag.String("secret", "", "Client secret")
authURL = flag.String("auth", "https://localhost/oauth/authorize", "Authorization URL")
tokenURL = flag.String("token", "https://localhost/oauth/token", "Token URL")
scopes Scopes
)
flag.Var(&scopes, "scope", "oAuth scopes to authorize (can be specified multiple times")
flag.Parse()
config := &oauth2.Config{
ClientID: *clientID,
ClientSecret: *clientSecret,
Scopes: scopes,
RedirectURL: fmt.Sprintf("http://127.0.0.1:%d%s", *port, *path),
Endpoint: oauth2.Endpoint{
AuthURL: *authURL,
TokenURL: *tokenURL,
},
}
state := randString()
url := config.AuthCodeURL(state, oauth2.AccessTypeOffline)
fmt.Printf("Visit this URL in your browser:\n\n%s\n\n", url)
ctx := context.Background()
var wg sync.WaitGroup
wg.Add(1)
http.HandleFunc(*path, func(w http.ResponseWriter, r *http.Request) {
defer wg.Done()
if s := r.URL.Query().Get("state"); s != state {
http.Error(w, fmt.Sprintf("Invalid state: %s", s), http.StatusUnauthorized)
return
}
code := r.URL.Query().Get("code")
token, err := config.Exchange(ctx, code)
if err != nil {
http.Error(w, fmt.Sprintf("Exchange error: %s", err), http.StatusServiceUnavailable)
return
}
tokenJSON, err := json.MarshalIndent(token, "", " ")
if err != nil {
http.Error(w, fmt.Sprintf("Token parse error: %s", err), http.StatusServiceUnavailable)
return
}
w.Write(tokenJSON)
})
server := http.Server{
Addr: fmt.Sprintf(":%d", *port),
}
go func() {
if err := server.ListenAndServe(); err != http.ErrServerClosed {
log.Fatalln(err)
}
}()
wg.Wait()
if err := server.Shutdown(ctx); err != nil {
log.Fatalln(err)
}
}