-
Notifications
You must be signed in to change notification settings - Fork 34
/
oauth.go
87 lines (71 loc) · 1.88 KB
/
oauth.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
package robinhood
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"
"github.com/pkg/errors"
"golang.org/x/oauth2"
)
// DefaultClientID is used by the website.
const DefaultClientID = "c82SH0WZOsabOXGP2sxqcj34FxkvfnWRZBKlBjFS"
// OAuth implements oauth2 using the robinhood implementation
type OAuth struct {
Endpoint, ClientID, Username, Password, MFA string
}
// ErrMFARequired indicates the MFA was required but not provided.
var ErrMFARequired = fmt.Errorf("Two Factor Auth code required and not supplied")
// Token implements TokenSource
func (p *OAuth) Token() (*oauth2.Token, error) {
cliID := p.ClientID
if cliID == "" {
cliID = DefaultClientID
}
u, _ := url.Parse(EPLogin)
q := map[string]interface{}{
"expires_in": 86400,
"client_id": cliID,
"device_token": "34898bf2-3aad-4540-8401-bea572ab8c09",
"grant_type": "password",
"scope": "internal",
"username": p.Username,
"password": p.Password,
}
if p.MFA != "" {
q["mfa_code"] = p.MFA
}
bs, _ := json.Marshal(q)
req, err := http.NewRequest(
"POST",
u.String(),
bytes.NewReader(bs),
)
if err != nil {
return nil, errors.Wrap(err, "could not create request")
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "*/*")
req.Header.Set("X-Robinhood-API-Version", "1.431.4")
res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, errors.Wrap(err, "could not post login")
}
defer res.Body.Close()
var o struct {
oauth2.Token
ExpiresIn int `json:"expires_in"`
MFARequired bool `json:"mfa_required"`
MFAType string `json:"mfa_type"`
}
err = json.NewDecoder(res.Body).Decode(&o)
if err != nil {
return nil, errors.Wrap(err, "could not decode token")
}
if o.MFARequired {
return nil, ErrMFARequired
}
o.Token.Expiry = time.Now().Add(time.Duration(o.ExpiresIn) * time.Second)
return &o.Token, nil
}