example.go
· 2.6 KiB · Go
Sin formato
type iLogin struct {
code string
state string
}
var loginCh = make(chan iLogin)
func init() {
// Load login webserver
http.HandleFunc("/auth/sauron", func(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
state := r.URL.Query().Get("state")
w.Write([]byte("You can now close this window"))
loginCh <- iLogin{
code: code,
state: state,
}
})
}
func webAuthUser() (string, string, error) {
resp, err := helpers.NewReq().Get("list/oauth2").Do()
if err != nil {
return "", "", errors.New("error occurred while getting OAuth2 URL: " + err.Error())
}
var oauth2Data types.OauthMeta
err = resp.Json(&oauth2Data)
if err != nil {
fmt.Print(helpers.RedText("Error parsing OAuth2 URL: " + err.Error()))
return "", "", err
}
// Open a http server on port 3000
srv := &http.Server{Addr: ":3000"}
go func() {
err := srv.ListenAndServe()
if err != http.ErrServerClosed {
log.Fatal(err)
}
}()
state := crypto.RandString(32)
fmt.Println("")
fmt.Println("")
fmt.Print(helpers.BlueText("Please open the following URL in your browser and follow the instructions:"))
fmt.Println("")
fmt.Println(strings.ReplaceAll(oauth2Data.URL, "%REDIRECT_URL%", "http://localhost:3000") + "&state=" + state)
// Wait for login
login := <-loginCh
fmt.Println("Got login code", login.code, "with state", login.state)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
srv.Shutdown(ctx)
cancel()
if login.state != state {
time.Sleep(5 * time.Second)
return "", "", errors.New("invalid state, please try again")
}
// Exchange code for token
resp, err = helpers.NewReq().Put("users").Json(types.AuthorizeRequest{
ClientID: oauth2Data.ClientID,
Code: login.code,
Scope: "external_auth",
Nonce: "@external",
RedirectURI: "http://localhost:3000/auth/sauron",
}).Do()
if err != nil {
time.Sleep(5 * time.Second)
return "", "", errors.New("error occurred while exchanging code for token: " + err.Error())
}
if resp.Response.StatusCode != 200 {
fmt.Println("Login failed, got response code", resp.Response.StatusCode)
body, err := resp.Body()
if err != nil {
return "", "", errors.New("error occurred while parsing error when exchanging code for token: " + err.Error())
}
fmt.Println("Error body:", string(body))
return "", "", errors.New("login failed, got response code " + fmt.Sprint(resp.Response.StatusCode))
}
var loginData types.UserLogin
err = resp.Json(&loginData)
if err != nil {
return "", "", errors.New("error occurred while parsing login data: " + err.Error())
}
return loginData.UserID, loginData.Token, nil
}
1 | type iLogin struct { |
2 | code string |
3 | state string |
4 | } |
5 | |
6 | var loginCh = make(chan iLogin) |
7 | |
8 | func init() { |
9 | // Load login webserver |
10 | http.HandleFunc("/auth/sauron", func(w http.ResponseWriter, r *http.Request) { |
11 | code := r.URL.Query().Get("code") |
12 | state := r.URL.Query().Get("state") |
13 | |
14 | w.Write([]byte("You can now close this window")) |
15 | |
16 | loginCh <- iLogin{ |
17 | code: code, |
18 | state: state, |
19 | } |
20 | }) |
21 | } |
22 | |
23 | |
24 | func webAuthUser() (string, string, error) { |
25 | resp, err := helpers.NewReq().Get("list/oauth2").Do() |
26 | |
27 | if err != nil { |
28 | return "", "", errors.New("error occurred while getting OAuth2 URL: " + err.Error()) |
29 | } |
30 | |
31 | var oauth2Data types.OauthMeta |
32 | |
33 | err = resp.Json(&oauth2Data) |
34 | |
35 | if err != nil { |
36 | fmt.Print(helpers.RedText("Error parsing OAuth2 URL: " + err.Error())) |
37 | return "", "", err |
38 | } |
39 | |
40 | // Open a http server on port 3000 |
41 | srv := &http.Server{Addr: ":3000"} |
42 | |
43 | go func() { |
44 | err := srv.ListenAndServe() |
45 | if err != http.ErrServerClosed { |
46 | log.Fatal(err) |
47 | } |
48 | }() |
49 | |
50 | state := crypto.RandString(32) |
51 | |
52 | fmt.Println("") |
53 | fmt.Println("") |
54 | fmt.Print(helpers.BlueText("Please open the following URL in your browser and follow the instructions:")) |
55 | fmt.Println("") |
56 | fmt.Println(strings.ReplaceAll(oauth2Data.URL, "%REDIRECT_URL%", "http://localhost:3000") + "&state=" + state) |
57 | |
58 | // Wait for login |
59 | login := <-loginCh |
60 | |
61 | fmt.Println("Got login code", login.code, "with state", login.state) |
62 | |
63 | ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) |
64 | |
65 | srv.Shutdown(ctx) |
66 | |
67 | cancel() |
68 | |
69 | if login.state != state { |
70 | time.Sleep(5 * time.Second) |
71 | return "", "", errors.New("invalid state, please try again") |
72 | } |
73 | |
74 | // Exchange code for token |
75 | resp, err = helpers.NewReq().Put("users").Json(types.AuthorizeRequest{ |
76 | ClientID: oauth2Data.ClientID, |
77 | Code: login.code, |
78 | Scope: "external_auth", |
79 | Nonce: "@external", |
80 | RedirectURI: "http://localhost:3000/auth/sauron", |
81 | }).Do() |
82 | |
83 | if err != nil { |
84 | time.Sleep(5 * time.Second) |
85 | return "", "", errors.New("error occurred while exchanging code for token: " + err.Error()) |
86 | } |
87 | |
88 | if resp.Response.StatusCode != 200 { |
89 | fmt.Println("Login failed, got response code", resp.Response.StatusCode) |
90 | |
91 | body, err := resp.Body() |
92 | |
93 | if err != nil { |
94 | return "", "", errors.New("error occurred while parsing error when exchanging code for token: " + err.Error()) |
95 | } |
96 | |
97 | fmt.Println("Error body:", string(body)) |
98 | return "", "", errors.New("login failed, got response code " + fmt.Sprint(resp.Response.StatusCode)) |
99 | } |
100 | |
101 | var loginData types.UserLogin |
102 | |
103 | err = resp.Json(&loginData) |
104 | |
105 | if err != nil { |
106 | return "", "", errors.New("error occurred while parsing login data: " + err.Error()) |
107 | } |
108 | |
109 | return loginData.UserID, loginData.Token, nil |
110 | } |