Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect HTTP status code when macaroon is not provided over REST API #2332

Closed
Kixunil opened this issue Dec 16, 2018 · 12 comments
Closed

Incorrect HTTP status code when macaroon is not provided over REST API #2332

Kixunil opened this issue Dec 16, 2018 · 12 comments

Comments

@Kixunil
Copy link
Contributor

Kixunil commented Dec 16, 2018

Background

The HTTP error code returned by lnd using REST API is not correct. It returns 500 Internal server error instead of 4xx. This is confusing when debugging.

Your environment

  • version of lnd 0.5.1
  • which operating system (uname -a on *Nix) Linux <redacted> 3.16.0-4-amd64 #1 SMP Debian 3.16.51-3 (2017-12-13) x86_64 GNU/Linux

Steps to reproduce

  • Configure restlisten=127.0.0.1:9737
  • Run wget --content-on-error --no-check-certificate -O - https://127.0.0.1:9737/v1/getinfo

Expected behaviour

Error 403 Forbidden or other reasonable 4xx error is returned.

Actual behaviour

500 Internal server error is returned

Ironically, since error 500 means there's something broken with the server, it's strictly true (server sending bad status code), but it doesn't help at all.

@philippgille
Copy link
Contributor

Just adding some info here: I think a 401 would be the most appropriate:

401 Unauthorized
Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response.

Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#Client_error_responses

More details: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401

The specific difference to 403 is that a 401 means "try again with credentials", while 403 means "I got your credentials but they don't allow you to access the requested resource".

So when no macaroons are sent, the server should respond with "try again with credentials" - i.e. 401.

@Kixunil
Copy link
Contributor Author

Kixunil commented Feb 2, 2019

I was thinking about it but many browsers automatically assume basic authentication (but maybe only with some additional header?), so I'm unsure if it's actually suitable.

@philippgille
Copy link
Contributor

I think that depends on the WWW-Authenticate header, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate.

There's a link to a list of alternative standard authentication schemes (alternatives to Basic), but I'm not sure if macaroons fit to any of those: https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml

It seems to be okay to define your own scheme, so maybe Macaroon can be used? See https://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-19#section-4.4.

@Kixunil
Copy link
Contributor Author

Kixunil commented Feb 3, 2019

In that case, I agree for it to return 401. It should be made sure to return 403 in case of invalid macaroon.

@wiz
Copy link

wiz commented Mar 21, 2019

Ah this really got me today 😓

@philippgille
Copy link
Contributor

I might give this a shot on the weekend, but I might need some guidance for my first code contribution.

@philippgille
Copy link
Contributor

philippgille commented Mar 23, 2019

Before I create a PR I'd love to get feedback from someone who knows the LND code base regarding if I'm on the right track:

  • LND uses grpc-gateway, it gets started here or here
  • grpc-gateway has default mappings for gRPC errors (see here)
    • codes.Unauthenticated maps to http.StatusUnauthorized, codes.PermissionDenied to http.StatusForbidden, only unmapped errors are http.StatusInternalServerError
      • This indicates that maybe some function in LND doesn't return the correct gRPC error code

Digging deeper:

So the solution seems to be to let ValidateMacaroon() return a Go error via gRPC's status.Error() (see GoDoc) with using the proper gRPC error code (either PermissionDenied or Unauthenticated according to above comments) (see GoDoc), as well as probably customizing the gateway response for the proper WWW-Authenticate header.

I looked for tests that would need to be extended and found TestValidateMacaroon in service_test.go (see here). I didn't find any tests for the gateway yet though.

P.S.: I didn't debug into the code yet, I just went through the code in an editor.

@halseth
Copy link
Contributor

halseth commented Mar 27, 2019

@philippgille Good detective work!

From looking at how grpc intereptors are used, what you might need is for the error from macaroon validation to conform to the GRPCStatus interface: https://github.com/grpc/grpc-go/blob/master/status/status.go#L126

@philippgille
Copy link
Contributor

@halseth: Thanks for letting me know that I'm on the right track!

what you might need is for the error from macaroon validation to conform to the GRPCStatus interface

Yes, my proposal was to use gRPC's status.Error(...):

So the solution seems to be to let ValidateMacaroon() return a Go error via gRPC's status.Error() (see GoDoc)

And according to the GoDoc of status.FromError() that you linked to:

FromError returns a Status representing err if it was produced from this package

This should be exactly what we need.

I'll work on a PR then :)

@saubyk
Copy link
Collaborator

saubyk commented Nov 1, 2023

Closing this issue, based on the last comment on the linked pr: #2863

@saubyk saubyk closed this as completed Nov 1, 2023
@Kixunil
Copy link
Contributor Author

Kixunil commented Nov 1, 2023

@saubyk I ran the reproduction steps again on 0.17 and it's still broken. I might be able to look into making a PR soon.

@saubyk
Copy link
Collaborator

saubyk commented Nov 1, 2023

Hi @Kixunil thanks for volunteering a pr. Feel free to reopen once you have the pr up. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants