-
Notifications
You must be signed in to change notification settings - Fork 19
/
main.go
126 lines (111 loc) · 3.46 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// autotoken retrieves a Slack token and cookie using your Slack team
// credentials.
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"strings"
"time"
"github.com/chromedp/cdproto/runtime"
"github.com/chromedp/cdproto/storage"
"github.com/chromedp/chromedp"
"github.com/spf13/pflag"
)
var (
flagDebug = pflag.BoolP("debug", "d", false, "Enable debug log")
flagShowBrowser = pflag.BoolP("show-browser", "b", false, "show browser, useful for debugging")
flagChromePath = pflag.StringP("chrome-path", "c", "", "Custom path for chrome browser")
flagTimeout = pflag.DurationP("timeout", "t", 5*time.Minute, "Timeout")
)
func main() {
usage := func() {
fmt.Fprintf(os.Stderr, "autotoken: log into slack team and get token and cookie.\n\n")
fmt.Fprintf(os.Stderr, "Usage: %s [-d|--debug] [-m|--mfa <token>] [-g|--gdpr] teamname[.slack.com]\n\n", os.Args[0])
pflag.PrintDefaults()
os.Exit(1)
}
pflag.Usage = usage
pflag.Parse()
if len(pflag.Args()) < 1 {
usage()
}
team := pflag.Arg(0)
timeout := *flagTimeout
token, cookie, err := fetchCredentials(context.TODO(), team, timeout, *flagDebug, *flagChromePath)
if err != nil {
log.Fatalf("Failed to fetch credentials for team `%s`: %v", team, err)
}
fmt.Printf("%s|%s\n", token, cookie)
}
// fetchCredentials fetches Slack token and cookie for a given team.
func fetchCredentials(ctx context.Context, team string, timeout time.Duration, doDebug bool, chromePath string) (string, string, error) {
if !strings.HasSuffix(team, ".slack.com") {
team += ".slack.com"
}
var cancel func()
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
// show browser
var allocatorOpts []chromedp.ExecAllocatorOption
if *flagShowBrowser {
allocatorOpts = append(allocatorOpts, chromedp.NoFirstRun, chromedp.NoDefaultBrowserCheck)
} else {
allocatorOpts = append(allocatorOpts, chromedp.Headless)
}
if chromePath != "" {
allocatorOpts = append(allocatorOpts, chromedp.ExecPath(chromePath))
}
ctx, cancel = chromedp.NewExecAllocator(ctx, allocatorOpts...)
defer cancel()
var opts []chromedp.ContextOption
if doDebug {
opts = append(opts, chromedp.WithDebugf(log.Printf))
}
ctx, cancel = chromedp.NewContext(ctx, opts...)
defer cancel()
fmt.Fprintf(os.Stderr, "Fetching token and cookie for %s \n", team)
// run chromedp tasks
return extractTokenAndCookie(ctx, team)
}
// extractTokenAndCookie extracts Slack token and cookie from an existing
// context.
func extractTokenAndCookie(ctx context.Context, team string) (string, string, error) {
teamURL := "https://" + team
var token, cookie string
tasks := chromedp.Tasks{
chromedp.Navigate(teamURL),
chromedp.WaitVisible(".p-workspace__primary_view_contents"),
chromedp.ActionFunc(func(ctx context.Context) error {
v, exp, err := runtime.Evaluate(`q=JSON.parse(localStorage.localConfig_v2)["teams"]; q[Object.keys(q)[0]]["token"]`).Do(ctx)
if err != nil {
return err
}
if exp != nil {
return exp
}
if err := json.Unmarshal(v.Value, &token); err != nil {
return fmt.Errorf("failed to unmarshal token: %v", err)
}
return nil
}),
chromedp.ActionFunc(func(ctx context.Context) error {
cookies, err := storage.GetCookies().Do(ctx)
if err != nil {
return err
}
for _, c := range cookies {
if c.Name == "d" {
cookie = fmt.Sprintf("d=%s;", c.Value)
}
}
return nil
}),
}
if err := chromedp.Run(ctx, tasks); err != nil {
return "", "", err
}
return token, cookie, nil
}