func (c *Client) LoginV1() error {
	url, err := url.Parse(c.connectionString)
	if err != nil {
		return fmt.Errorf("unable to parse connection string url [%s]: %v", c.connectionString, err)
	}
	c.connectionURL = url
	body, err := c.authenticator.JSON()
	if err != nil {
		return fmt.Errorf("JSON marshal error: %v", err)
	}
	buffer := bytes.NewBuffer(body)
	resp, err := http.Post(c.Endpoint("api/v1/session"), c.contentType, buffer)
	if err != nil {
		return fmt.Errorf("authentication error: %v", err)
	}
	if resp.StatusCode != 200 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("unable to parse body for [%d] response: %v", resp.StatusCode, err)
		}
		return fmt.Errorf("login error [%d] %s", resp.StatusCode, body)
	}
	cfg := &Config{
		Config: &Options{},
	}
	bytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("unable to parse auth body: %v", err)
	}
	err = json.Unmarshal(bytes, &cfg)
	if err != nil {
		return fmt.Errorf("unable to json unmarshal auth body: %v", err)
	}
	token := resp.Header.Get(APIAuthHeaderKey)
	if token == "" {
		return fmt.Errorf("missing auth token from successful login")
	}
	c.v1client = v1.New(c.connectionURL, token, cfg.Config.DownloadToken)
	return nil
}
POST /api/v1/session

Data: {username: "admin", password: "missy"}
package photoprism
import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	v1 "github.com/kris-nova/photoprism-client-go/api/v1"
)
const (
	APIContentType string = "application/json; charset=utf-8"
	APIAuthHeaderKey string = "X-Session-Id"
)
func New(connectionString string) *Client {
	for strings.HasSuffix(connectionString, "/") {
		connectionString = connectionString[:len(connectionString)-1]
	}
	c := &Client{
		contentType:      APIContentType,
		connectionString: connectionString,
	}
	return c
}
func (c *Client) ConnectionString() string {
	return c.connectionString
}
type Client struct {
	v1client         *v1.V1Client
	authenticator    ClientAuthenticator
	contentType      string
	connectionString string
	connectionURL    *url.URL
}
type ClientAuthenticator interface {
	getKey() string
	getSecret() string
	JSON() ([]byte, error)
}
type ClientAuthLogin struct {
	authPayload
}
type authPayload struct {
	Username string `json:"username"`
	Password string `json:"password"`
}
func NewClientAuthLogin(user, pass string) ClientAuthenticator {
	return &ClientAuthLogin{
		authPayload: authPayload{
			Username: user,
			Password: pass,
		},
	}
}
func (c *ClientAuthLogin) getKey() string {
	return c.authPayload.Username
}
func (c *ClientAuthLogin) getSecret() string {
	return c.authPayload.Password
}
func (c *ClientAuthLogin) JSON() ([]byte, error) {
	return json.Marshal(c)
}
func (c *Client) V1() *v1.V1Client {
	return c.v1client
}
func (c *Client) Auth(auth ClientAuthenticator) error {
	c.authenticator = auth
	return c.LoginV1()
}