9
"gopkg.in/macaroon-bakery.v1/bakery/checkers"
12
type httpContext struct {
16
// Checkers implements the standard HTTP-request checkers.
17
// It does not include the "declared" checker, as that
18
// must be added for each individual set of macaroons
20
func Checkers(req *http.Request) checkers.Checker {
23
checkers.CondClientIPAddr: c.clientIPAddr,
24
checkers.CondClientOrigin: c.clientOrigin,
28
// clientIPAddr implements the IP client address checker
29
// for an HTTP request.
30
func (c httpContext) clientIPAddr(_, addr string) error {
31
ip := net.ParseIP(addr)
33
return errgo.Newf("cannot parse IP address in caveat")
35
if c.req.RemoteAddr == "" {
36
return errgo.Newf("client has no remote address")
38
reqIP, err := requestIPAddr(c.req)
40
return errgo.Mask(err)
43
return errgo.Newf("client IP address mismatch, got %s", reqIP)
48
// clientOrigin implements the Origin header checker
49
// for an HTTP request.
50
func (c httpContext) clientOrigin(_, origin string) error {
51
if reqOrigin := c.req.Header.Get("Origin"); reqOrigin != origin {
52
return errgo.Newf("request has invalid Origin header; got %q", reqOrigin)
57
// SameClientIPAddrCaveat returns a caveat that will check that
58
// the remote IP address is the same as that in the given HTTP request.
59
func SameClientIPAddrCaveat(req *http.Request) checkers.Caveat {
60
if req.RemoteAddr == "" {
61
return checkers.ErrorCaveatf("client has no remote IP address")
63
ip, err := requestIPAddr(req)
65
return checkers.ErrorCaveatf("%v", err)
67
return checkers.ClientIPAddrCaveat(ip)
70
func requestIPAddr(req *http.Request) (net.IP, error) {
71
reqHost, _, err := net.SplitHostPort(req.RemoteAddr)
73
return nil, errgo.Newf("cannot parse host port in remote address: %v", err)
75
ip := net.ParseIP(reqHost)
77
return nil, errgo.Newf("invalid IP address in remote address %q", req.RemoteAddr)