最后活跃于 1685623390

rootspring's Avatar rootspring 修订了这个 Gist 1685623390. 跳至此修订

1 file changed, 23 insertions

example.go

@@ -1,3 +1,26 @@
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 +
1 24 func webAuthUser() (string, string, error) {
2 25 resp, err := helpers.NewReq().Get("list/oauth2").Do()
3 26

rootspring's Avatar rootspring 修订了这个 Gist 1685623303. 跳至此修订

1 file changed, 87 insertions

example.go(file created)

@@ -0,0 +1,87 @@
1 + func webAuthUser() (string, string, error) {
2 + resp, err := helpers.NewReq().Get("list/oauth2").Do()
3 +
4 + if err != nil {
5 + return "", "", errors.New("error occurred while getting OAuth2 URL: " + err.Error())
6 + }
7 +
8 + var oauth2Data types.OauthMeta
9 +
10 + err = resp.Json(&oauth2Data)
11 +
12 + if err != nil {
13 + fmt.Print(helpers.RedText("Error parsing OAuth2 URL: " + err.Error()))
14 + return "", "", err
15 + }
16 +
17 + // Open a http server on port 3000
18 + srv := &http.Server{Addr: ":3000"}
19 +
20 + go func() {
21 + err := srv.ListenAndServe()
22 + if err != http.ErrServerClosed {
23 + log.Fatal(err)
24 + }
25 + }()
26 +
27 + state := crypto.RandString(32)
28 +
29 + fmt.Println("")
30 + fmt.Println("")
31 + fmt.Print(helpers.BlueText("Please open the following URL in your browser and follow the instructions:"))
32 + fmt.Println("")
33 + fmt.Println(strings.ReplaceAll(oauth2Data.URL, "%REDIRECT_URL%", "http://localhost:3000") + "&state=" + state)
34 +
35 + // Wait for login
36 + login := <-loginCh
37 +
38 + fmt.Println("Got login code", login.code, "with state", login.state)
39 +
40 + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
41 +
42 + srv.Shutdown(ctx)
43 +
44 + cancel()
45 +
46 + if login.state != state {
47 + time.Sleep(5 * time.Second)
48 + return "", "", errors.New("invalid state, please try again")
49 + }
50 +
51 + // Exchange code for token
52 + resp, err = helpers.NewReq().Put("users").Json(types.AuthorizeRequest{
53 + ClientID: oauth2Data.ClientID,
54 + Code: login.code,
55 + Scope: "external_auth",
56 + Nonce: "@external",
57 + RedirectURI: "http://localhost:3000/auth/sauron",
58 + }).Do()
59 +
60 + if err != nil {
61 + time.Sleep(5 * time.Second)
62 + return "", "", errors.New("error occurred while exchanging code for token: " + err.Error())
63 + }
64 +
65 + if resp.Response.StatusCode != 200 {
66 + fmt.Println("Login failed, got response code", resp.Response.StatusCode)
67 +
68 + body, err := resp.Body()
69 +
70 + if err != nil {
71 + return "", "", errors.New("error occurred while parsing error when exchanging code for token: " + err.Error())
72 + }
73 +
74 + fmt.Println("Error body:", string(body))
75 + return "", "", errors.New("login failed, got response code " + fmt.Sprint(resp.Response.StatusCode))
76 + }
77 +
78 + var loginData types.UserLogin
79 +
80 + err = resp.Json(&loginData)
81 +
82 + if err != nil {
83 + return "", "", errors.New("error occurred while parsing login data: " + err.Error())
84 + }
85 +
86 + return loginData.UserID, loginData.Token, nil
87 + }
更新 更早