Files
go-nc-exapp/credentials.go
T

66 lines
2.1 KiB
Go

package gonexapp
import (
"encoding/base64"
"fmt"
"net/http"
"strings"
)
// Credentials are what an ExApp needs to call Nextcloud as one user.
// BaseURL is the Nextcloud instance URL. A trailing slash is tolerated by
// callers in this package and is removed when they build a URL.
// AppID, AppVersion, and AAVersion are sent as EX-APP-ID, EX-APP-VERSION,
// and AA-VERSION. AppSecret and UserID form the AUTHORIZATION-APP-API token.
type Credentials struct {
BaseURL string
AppID string
AppVersion string
AAVersion string
AppSecret string
UserID string
}
// AuthHeaders returns AppAPI headers for a request to Nextcloud.
// The set is AA-VERSION, EX-APP-ID, EX-APP-VERSION, AUTHORIZATION-APP-API,
// and OCS-APIRequest. AUTHORIZATION-APP-API is base64 of UserID, a colon,
// and AppSecret. The method does not return an error; empty fields are sent as empty.
func (c Credentials) AuthHeaders() http.Header {
h := make(http.Header)
h.Set("AA-VERSION", c.AAVersion)
h.Set("EX-APP-ID", c.AppID)
h.Set("EX-APP-VERSION", c.AppVersion)
token := base64.StdEncoding.EncodeToString([]byte(c.UserID + ":" + c.AppSecret))
h.Set("AUTHORIZATION-APP-API", token)
h.Set("OCS-APIRequest", "true")
return h
}
// WithUser returns a copy whose UserID is userID.
// The receiver is not modified.
func (c Credentials) WithUser(userID string) Credentials {
out := c
out.UserID = userID
return out
}
// UserFromRequest reads the requesting user from AUTHORIZATION-APP-API
// on an inbound ExApp request.
// It returns an error when the header is missing, is not base64, or contains
// no user id before the colon.
func UserFromRequest(r *http.Request) (string, error) {
raw := r.Header.Get("AUTHORIZATION-APP-API")
if raw == "" {
return "", fmt.Errorf("missing AUTHORIZATION-APP-API")
}
decoded, err := base64.StdEncoding.DecodeString(raw)
if err != nil {
return "", fmt.Errorf("invalid AUTHORIZATION-APP-API: %w", err)
}
parts := strings.SplitN(string(decoded), ":", 2)
if len(parts) < 1 || strings.TrimSpace(parts[0]) == "" {
return "", fmt.Errorf("AUTHORIZATION-APP-API has no user id")
}
return parts[0], nil
}