Skip to content

Commit

Permalink
Accept comma separated macaroons
Browse files Browse the repository at this point in the history
  • Loading branch information
gofeuer committed Aug 11, 2024
1 parent a308758 commit 9236532
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 18 deletions.
5 changes: 4 additions & 1 deletion auth/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@ func (l *L402Authenticator) Accept(header *http.Header, serviceName string) bool
// Try reading the macaroon and preimage from the HTTP header. This can
// be in different header fields depending on the implementation and/or
// protocol.
mac, preimage, err := l402.FromHeader(header)
macs, preimage, err := l402.FromHeader(header)
if err != nil {
log.Debugf("Deny: %v", err)
return false
}

// TODO: Be able to accept multiple macaroons
mac := macs[0]

verificationParams := &mint.VerificationParams{
Macaroon: mac,
Preimage: preimage,
Expand Down
48 changes: 32 additions & 16 deletions l402/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"regexp"
"strings"

"github.com/lightningnetwork/lnd/lntypes"
"gopkg.in/macaroon.v2"
Expand Down Expand Up @@ -42,7 +43,7 @@ var (
//
// If only the macaroon is sent in header 2 or three then it is expected to have
// a caveat with the preimage attached to it.
func FromHeader(header *http.Header) (*macaroon.Macaroon, lntypes.Preimage, error) {
func FromHeader(header *http.Header) (macaroon.Slice, lntypes.Preimage, error) {
var authHeader string

switch {
Expand Down Expand Up @@ -71,14 +72,22 @@ func FromHeader(header *http.Header) (*macaroon.Macaroon, lntypes.Preimage, erro
macBase64, preimageHex := matches[2], matches[3]
macBytes, err := base64.StdEncoding.DecodeString(macBase64)
if err != nil {
return nil, lntypes.Preimage{}, fmt.Errorf("base64 "+
"decode of macaroon failed: %v", err)
// macBase64 might be multiple macaroons separated by commas,
// so we strip them and try again
macBase64 = strings.ReplaceAll(macBase64, ",", "")
macBytes, err = base64.StdEncoding.DecodeString(macBase64)
if err != nil {
return nil, lntypes.Preimage{},
fmt.Errorf("base64 decode of macaroon failed: %v", err)
}
}
mac := &macaroon.Macaroon{}
// macBytes can contain multiple macaroons,
// (* macaroon.Slice) knows how to decode them without separators
mac := make(macaroon.Slice, 0, 1)
err = mac.UnmarshalBinary(macBytes)
if err != nil {
return nil, lntypes.Preimage{}, fmt.Errorf("unable to "+
"unmarshal macaroon: %v", err)
return nil, lntypes.Preimage{},
fmt.Errorf("unable to unmarshal macaroon: %v", err)
}
preimage, err := lntypes.MakePreimageFromStr(preimageHex)
if err != nil {
Expand Down Expand Up @@ -107,32 +116,39 @@ func FromHeader(header *http.Header) (*macaroon.Macaroon, lntypes.Preimage, erro
// extract the preimage.
macBytes, err := hex.DecodeString(authHeader)
if err != nil {
return nil, lntypes.Preimage{}, fmt.Errorf("hex decode of "+
"macaroon failed: %v", err)
return nil, lntypes.Preimage{},
fmt.Errorf("hex decode of macaroon failed: %v", err)
}
mac := &macaroon.Macaroon{}
mac := make(macaroon.Slice, 0, 1)
err = mac.UnmarshalBinary(macBytes)
if err != nil {
return nil, lntypes.Preimage{}, fmt.Errorf("unable to "+
"unmarshal macaroon: %v", err)
}
preimageHex, ok := HasCaveat(mac, PreimageKey)
if !ok {
return nil, lntypes.Preimage{}, errors.New("preimage caveat " +
"not found")
var preimageHex string
var ok bool
for _, m := range mac {
if preimageHex, ok = HasCaveat(m, PreimageKey); ok {
break
}
}
if preimageHex == "" || !ok {
return nil, lntypes.Preimage{},
errors.New("preimage caveat not found")
}

preimage, err := lntypes.MakePreimageFromStr(preimageHex)
if err != nil {
return nil, lntypes.Preimage{}, fmt.Errorf("hex decode of "+
"preimage failed: %v", err)
return nil, lntypes.Preimage{},
fmt.Errorf("hex decode of preimage failed: %v", err)
}

return mac, preimage, nil
}

// SetHeader sets the provided authentication elements as the default/standard
// HTTP header for the L402 protocol.
func SetHeader(header *http.Header, mac *macaroon.Macaroon,
func SetHeader(header *http.Header, mac macaroon.Slice,
preimage fmt.Stringer) error {

macBytes, err := mac.MarshalBinary()
Expand Down
5 changes: 4 additions & 1 deletion l402/server_interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,14 @@ func tokenFromContext(ctx context.Context) (*TokenID, error) {
}
log.Debugf("Auth header present in request: %s",
md.Get(HeaderAuthorization))
macaroon, _, err := FromHeader(header)
macaroons, _, err := FromHeader(header)
if err != nil {
return nil, fmt.Errorf("auth header extraction failed: %v", err)
}

// TODO: Be able to accept multiple macaroons
macaroon := macaroons[0]

// If there is an L402, decode and add it to the context.
identifier, err := DecodeIdentifier(bytes.NewBuffer(macaroon.Id()))
if err != nil {
Expand Down

0 comments on commit 9236532

Please sign in to comment.