Initial discord remote auth support.
It works, but nothing is persisted yet as the user object needs some tweaking especially the database side.
This commit is contained in:
109
remoteauth/client.go
Normal file
109
remoteauth/client.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package remoteauth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
URL string
|
||||
Origin string
|
||||
|
||||
conn *websocket.Conn
|
||||
|
||||
qrChan chan string
|
||||
doneChan chan struct{}
|
||||
|
||||
user User
|
||||
err error
|
||||
|
||||
heartbeats int
|
||||
closed bool
|
||||
|
||||
privateKey *rsa.PrivateKey
|
||||
}
|
||||
|
||||
// New creates a new Discord remote auth client. qrChan is a channel that will
|
||||
// receive the qrcode once it is available.
|
||||
func New() (*Client, error) {
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{
|
||||
URL: "wss://remote-auth-gateway.discord.gg/?v=1",
|
||||
Origin: "https://discord.com",
|
||||
privateKey: privateKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Dialo will start the QRCode login process. ctx may be used to abandon the
|
||||
// process.
|
||||
func (c *Client) Dial(ctx context.Context, qrChan chan string, doneChan chan struct{}) error {
|
||||
header := http.Header{
|
||||
"Origin": []string{c.Origin},
|
||||
}
|
||||
|
||||
c.qrChan = qrChan
|
||||
c.doneChan = doneChan
|
||||
|
||||
conn, _, err := websocket.DefaultDialer.DialContext(ctx, c.URL, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.conn = conn
|
||||
|
||||
go c.processMessages()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Result() (User, error) {
|
||||
return c.user, c.err
|
||||
}
|
||||
|
||||
func (c *Client) close() error {
|
||||
if c.closed {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.conn.WriteMessage(
|
||||
websocket.CloseMessage,
|
||||
websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""),
|
||||
)
|
||||
|
||||
c.closed = true
|
||||
|
||||
defer close(c.doneChan)
|
||||
|
||||
return c.conn.Close()
|
||||
}
|
||||
|
||||
func (c *Client) write(p clientPacket) error {
|
||||
payload, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.conn.WriteMessage(websocket.TextMessage, payload)
|
||||
}
|
||||
|
||||
func (c *Client) decrypt(payload string) ([]byte, error) {
|
||||
// Decode the base64 string.
|
||||
raw, err := base64.StdEncoding.DecodeString(payload)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
// Decrypt the data.
|
||||
return rsa.DecryptOAEP(sha256.New(), nil, c.privateKey, raw, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user