auth: send LSAT and L402 Authorization headers

Again, as with WWW-Authenticate header, existing aperture instances
expect LSAT, and the protocol defines it is L402, so send both, LSAT
first, to maintain backward compatibility.

The header "Authorization: LSAT..." can be removed in the future,
when all aperture instances are upgraded.
This commit is contained in:
Boris Nagaev
2024-04-16 16:56:59 -03:00
parent 709463fe5b
commit fb02e3f030
2 changed files with 55 additions and 18 deletions

View File

@@ -100,11 +100,33 @@ func TestL402Authenticator(t *testing.T) {
result: false, result: false,
}, },
{ {
id: "valid auth header", id: "valid auth header (both LSAT and L402)",
header: &http.Header{ header: &http.Header{
l402.HeaderAuthorization: []string{ l402.HeaderAuthorization: []string{
"LSAT " + testMacBase64 + ":" + "LSAT " + testMacBase64 + ":" +
testPreimage, testPreimage,
"L402 " + testMacBase64 + ":" +
testPreimage,
},
},
result: true,
},
{
id: "valid auth header (LSAT only)",
header: &http.Header{
l402.HeaderAuthorization: []string{
"LSAT " + testMacBase64 + ":" +
testPreimage,
},
},
result: true,
},
{
id: "valid auth header (L402 only)",
header: &http.Header{
l402.HeaderAuthorization: []string{
"L402 " + testMacBase64 + ":" +
testPreimage,
}, },
}, },
result: true, result: true,

View File

@@ -27,13 +27,15 @@ const (
) )
var ( var (
authRegex = regexp.MustCompile("LSAT (.*?):([a-f0-9]{64})") authRegex = regexp.MustCompile("(LSAT|L402) (.*?):([a-f0-9]{64})")
authFormat = "LSAT %s:%s" authFormatLegacy = "LSAT %s:%s"
authFormat = "L402 %s:%s"
) )
// FromHeader tries to extract authentication information from HTTP headers. // FromHeader tries to extract authentication information from HTTP headers.
// There are two supported formats that can be sent in three different header // There are two supported formats that can be sent in four different header
// fields: // fields:
// 0. Authorization: LSAT <macBase64>:<preimageHex>
// 1. Authorization: L402 <macBase64>:<preimageHex> // 1. Authorization: L402 <macBase64>:<preimageHex>
// 2. Grpc-Metadata-Macaroon: <macHex> // 2. Grpc-Metadata-Macaroon: <macHex>
// 3. Macaroon: <macHex> // 3. Macaroon: <macHex>
@@ -49,21 +51,27 @@ func FromHeader(header *http.Header) (*macaroon.Macaroon, lntypes.Preimage, erro
case header.Get(HeaderAuthorization) != "": case header.Get(HeaderAuthorization) != "":
// Parse the content of the header field and check that it is in // Parse the content of the header field and check that it is in
// the correct format. // the correct format.
authHeader = header.Get(HeaderAuthorization) var matches []string
log.Debugf("Trying to authorize with header value [%s].", authHeaders := header.Values(HeaderAuthorization)
authHeader) for _, authHeader := range authHeaders {
log.Debugf("Trying to authorize with header value "+
"[%s].", authHeader)
if !authRegex.MatchString(authHeader) { if !authRegex.MatchString(authHeader) {
return nil, lntypes.Preimage{}, fmt.Errorf("invalid "+ continue
"auth header format: %s", authHeader)
} }
matches := authRegex.FindStringSubmatch(authHeader) matches = authRegex.FindStringSubmatch(authHeader)
if len(matches) != 3 { if len(matches) != 4 {
continue
}
}
if len(matches) != 4 {
return nil, lntypes.Preimage{}, fmt.Errorf("invalid "+ return nil, lntypes.Preimage{}, fmt.Errorf("invalid "+
"auth header format: %s", authHeader) "auth header format: %s", authHeader)
} }
// Decode the content of the two parts of the header value. // Decode the content of the two parts of the header value.
macBase64, preimageHex := matches[1], matches[2] macBase64, preimageHex := matches[2], matches[3]
macBytes, err := base64.StdEncoding.DecodeString(macBase64) macBytes, err := base64.StdEncoding.DecodeString(macBase64)
if err != nil { if err != nil {
return nil, lntypes.Preimage{}, fmt.Errorf("base64 "+ return nil, lntypes.Preimage{}, fmt.Errorf("base64 "+
@@ -134,10 +142,17 @@ func SetHeader(header *http.Header, mac *macaroon.Macaroon,
if err != nil { if err != nil {
return err return err
} }
value := fmt.Sprintf( macStr := base64.StdEncoding.EncodeToString(macBytes)
authFormat, base64.StdEncoding.EncodeToString(macBytes), preimageStr := preimage.String()
preimage.String(),
) // Send "Authorization: LSAT..." header before sending
header.Set(HeaderAuthorization, value) // "Authorization: L402" header to be compatible with old aperture.
// TODO: remove this after aperture is upgraded everywhere.
legacyValue := fmt.Sprintf(authFormatLegacy, macStr, preimageStr)
header.Set(HeaderAuthorization, legacyValue)
value := fmt.Sprintf(authFormat, macStr, preimageStr)
header.Add(HeaderAuthorization, value)
return nil return nil
} }