Skip to content

Commit

Permalink
Add Mist authentication to catalyst-api (#1317)
Browse files Browse the repository at this point in the history
  • Loading branch information
leszko authored Jul 12, 2024
1 parent 90fc3d1 commit ca7f48f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 9 deletions.
77 changes: 72 additions & 5 deletions clients/mist_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package clients

import (
"bytes"
"crypto/md5"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -44,6 +45,8 @@ type MistAPIClient interface {

type MistClient struct {
ApiUrl string
Username string
Password string
HttpReqUrl string
TriggerCallback string
configMu sync.Mutex
Expand All @@ -53,6 +56,8 @@ type MistClient struct {
func NewMistAPIClient(user, password, host string, port int, ownURL string) MistAPIClient {
mist := &MistClient{
ApiUrl: fmt.Sprintf("http://%s:%d", host, port),
Username: user,
Password: password,
TriggerCallback: ownURL,
cache: cache.New(defaultCacheExpiration, cacheCleanupInterval),
}
Expand Down Expand Up @@ -117,6 +122,13 @@ type MistState struct {
PushAutoList []*MistPushAuto `json:"push_auto_list"`
}

type AuthorizationResponse struct {
Authorize struct {
Status string `json:"status"`
Challenge string `json:"challenge"`
} `json:"authorize"`
}

func (ms MistState) IsIngestStream(stream string) bool {
if ms.ActiveStreams == nil {
return false
Expand Down Expand Up @@ -351,6 +363,38 @@ func (mc *MistClient) getCurrentTriggers() (Triggers, error) {
}

func (mc *MistClient) sendCommand(command interface{}) (string, error) {
resp, err := mc.sendCommandToMist(command)
if authErr := validateAuth(resp, err); authErr != nil {
glog.Infof("Request to Mist not authorized, authorizing and retrying command: %v", command)
if authErr := mc.authorize(resp); authErr != nil {
glog.Warningf("Failed to authorize Mist request: %v", authErr)
return resp, err
}
return mc.sendCommandToMist(command)
}
return resp, err
}

// authorize authorizes the communication with Mist Server by sending the authorization command.
// Mist doc: https://docs.mistserver.org/docs/mistserver/integration/api/authentication
func (mc *MistClient) authorize(unauthResp string) error {
r := AuthorizationResponse{}
if err := json.Unmarshal([]byte(unauthResp), &r); err != nil {
return err
}
passwordMd5, err := computeMD5Hash(mc.Password)
if err != nil {
return err
}
password, err := computeMD5Hash(passwordMd5 + r.Authorize.Challenge)
if err != nil {
return err
}
c := commandAuthorize(mc.Username, password)
return validateAuth(mc.sendCommandToMist(c))
}

func (mc *MistClient) sendCommandToMist(command interface{}) (string, error) {
c, err := commandToString(command)
if err != nil {
return "", err
Expand Down Expand Up @@ -449,6 +493,24 @@ func (mc *MistClient) GetState() (MistState, error) {
return stats, nil
}

type authorizeCommand struct {
Authorize Authorize `json:"authorize"`
}

type Authorize struct {
Username string `json:"username"`
Password string `json:"password"`
}

func commandAuthorize(username, password string) interface{} {
return authorizeCommand{
Authorize: Authorize{
Username: username,
Password: password,
},
}
}

type addStreamCommand struct {
Addstream map[string]Stream `json:"addstream"`
}
Expand Down Expand Up @@ -723,11 +785,7 @@ func validateAuth(resp string, err error) error {
if err != nil {
return err
}
r := struct {
Authorize struct {
Status string `json:"status"`
} `json:"authorize"`
}{}
r := AuthorizationResponse{}

if err := json.Unmarshal([]byte(resp), &r); err != nil {
return err
Expand All @@ -738,6 +796,15 @@ func validateAuth(resp string, err error) error {
return nil
}

func computeMD5Hash(input string) (string, error) {
hasher := md5.New()
_, err := io.WriteString(hasher, input)
if err != nil {
return "", err
}
return fmt.Sprintf("%x", hasher.Sum(nil)), nil
}

func wrapErr(err error, streamName string) error {
if err != nil {
return fmt.Errorf("error in processing stream '%s': %w", streamName, err)
Expand Down
4 changes: 0 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,6 @@ func main() {
return
}

if cli.MistUser != "" || cli.MistPassword != "" {
glog.Warning("DEPRECATION NOTICE: mist-user and mist-password are no longer used and will be removed in a later version")
}

// TODO: I don't love the global variables for these
config.ImportIPFSGatewayURLs = cli.ImportIPFSGatewayURLs
config.ImportArweaveGatewayURLs = cli.ImportArweaveGatewayURLs
Expand Down

0 comments on commit ca7f48f

Please sign in to comment.