Documentation ¶
Index ¶
- Constants
- Variables
- func AddDischargeHandler(mux *http.ServeMux, rootPath string, svc *bakery.Service, ...)
- func CheckRequest(svc *bakery.Service, req *http.Request, assert map[string]string, ...) (map[string]string, error)
- func CheckRequestM(svc *bakery.Service, req *http.Request, assert map[string]string, ...) (map[string]string, macaroon.Slice, error)
- func Checkers(req *http.Request) checkers.Checker
- func DefaultGetError(httpResp *http.Response) error
- func ErrorToResponse(err error) (int, interface{})
- func GetInteractionMethods(client httprequest.Doer, u *url.URL) (map[string]*url.URL, error)
- func IsDischargeError(err error) bool
- func IsInteractionError(err error) bool
- func MacaroonsForURL(jar http.CookieJar, u *url.URL) []macaroon.Slice
- func NewCookie(ms macaroon.Slice) (*http.Cookie, error)
- func NewDischargeRequiredError(m *macaroon.Macaroon, path string, originalErr error) error
- func NewDischargeRequiredErrorForRequest(m *macaroon.Macaroon, path string, originalErr error, req *http.Request) error
- func NewHTTPClient() *http.Client
- func NewInteractionRequiredError(visitURL, waitURL string, originalErr error, req *http.Request) error
- func OpenWebBrowser(url *url.URL) error
- func PublicKeyForLocation(client *http.Client, url string) (*bakery.PublicKey, error)
- func RequestMacaroons(req *http.Request) []macaroon.Slice
- func SameClientIPAddrCaveat(req *http.Request) checkers.Caveat
- func SetCookie(jar http.CookieJar, url *url.URL, ms macaroon.Slice) error
- func WriteDischargeRequiredError(w http.ResponseWriter, m *macaroon.Macaroon, path string, originalErr error)
- func WriteDischargeRequiredErrorForRequest(w http.ResponseWriter, m *macaroon.Macaroon, path string, originalErr error, ...)
- type Client
- func (c *Client) AcquireDischarge(originalLocation string, cav macaroon.Caveat) (*macaroon.Macaroon, error)
- func (c *Client) DischargeAll(m *macaroon.Macaroon) (macaroon.Slice, error)
- func (c *Client) Do(req *http.Request) (*http.Response, error)
- func (c *Client) DoWithBody(req *http.Request, body io.ReadSeeker) (*http.Response, error)
- func (c *Client) DoWithBodyAndCustomError(req *http.Request, body io.ReadSeeker, ...) (*http.Response, error)
- func (c *Client) HandleError(reqURL *url.URL, err error) error
- type DischargeAcquirer
- type DischargeError
- type Error
- type ErrorCode
- type ErrorInfo
- type InteractionError
- type PublicKeyRing
- type Visitor
- type WaitResponse
Constants ¶
const ( ErrBadRequest = ErrorCode("bad request") ErrDischargeRequired = ErrorCode("macaroon discharge required") ErrInteractionRequired = ErrorCode("interaction required") )
const BakeryProtocolHeader = "Bakery-Protocol-Version"
BakeryProtocolHeader is the header that HTTP clients should set to determine the bakery protocol version. If it is 0 or missing, a discharge-required error response will be returned with HTTP status 407; if it is 1, the response will have status 401 with the WWW-Authenticate header set to "Macaroon".
const MacaroonsHeader = "Macaroons"
MacaroonsHeader is the key of the HTTP header that can be used to provide a macaroon for request authorization.
const ( // UserInteractionMethod is the methodURLs key used for a URL // that should be visited in a user's web browser. This is also // the URL that can be used to fetch the available login methods // (with an appropriate Accept header). UserInteractionMethod = "interactive" )
Variables ¶
var ErrMethodNotSupported = errgo.New("interaction method not supported")
ErrMethodNotSupported is the error that a Visitor implementation should return if it does not support any of the interaction methods.
Functions ¶
func AddDischargeHandler ¶
func AddDischargeHandler(mux *http.ServeMux, rootPath string, svc *bakery.Service, checker func(req *http.Request, cavId, cav string) ([]checkers.Caveat, error))
AddDischargeHandler adds handlers to the given ServeMux to serve third party caveat discharges using the given service.
The handlers are added under the given rootPath, which must be non-empty.
The check function is used to check whether a client making the given request should be allowed a discharge for the given caveat. If it does not return an error, the caveat will be discharged, with any returned caveats also added to the discharge macaroon. If it returns an error with a *Error cause, the error will be marshaled and sent back to the client.
The name space served by DischargeHandler is as follows. All parameters can be provided either as URL attributes or form attributes. The result is always formatted as a JSON object.
On failure, all endpoints return an error described by the Error type.
POST /discharge
params: id: id of macaroon to discharge location: location of original macaroon (optional (?)) ?? flow=redirect|newwindow result on success (http.StatusOK): { Macaroon *macaroon.Macaroon }
GET /publickey
result: public key of service expiry time of key
func CheckRequest ¶
func CheckRequest(svc *bakery.Service, req *http.Request, assert map[string]string, checker checkers.Checker) (map[string]string, error)
CheckRequest checks that the given http request contains at least one valid macaroon minted by the given service, using checker to check any first party caveats. It returns an error with a *bakery.VerificationError cause if the macaroon verification failed.
The assert map holds any required attributes of "declared" attributes, overriding any inferences made from the macaroons themselves. It has a similar effect to adding a checkers.DeclaredCaveat for each key and value, but the error message will be more useful.
It adds all the standard caveat checkers to the given checker.
It returns any attributes declared in the successfully validated request.
func CheckRequestM ¶
func CheckRequestM(svc *bakery.Service, req *http.Request, assert map[string]string, checker checkers.Checker) (map[string]string, macaroon.Slice, error)
CheckRequestM is like CheckRequest except that on success it also returns the set of macaroons that was successfully checked. The "M" suffix is for backward compatibility reasons - in a later bakery version, the signature of CheckRequest will be changed to return the macaroon slice and CheckRequestM will be removed.
func Checkers ¶
Checkers implements the standard HTTP-request checkers. It does not include the "declared" checker, as that must be added for each individual set of macaroons that are checked.
func DefaultGetError ¶
DefaultGetError is the default error unmarshaler used by Client.DoWithBody.
func ErrorToResponse ¶
ErrorToResponse returns the HTTP status and an error body to be marshaled as JSON for the given error. This allows a third party package to integrate bakery errors into their error responses when they encounter an error with a *bakery.Error cause.
func GetInteractionMethods ¶
GetInteractionMethods queries a URL as found in an ErrInteractionRequired VisitURL field to find available interaction methods.
It does this by sending a GET request to the URL with the Accept header set to "application/json" and parsing the resulting response as a map[string]string.
It uses the given Doer to execute the HTTP GET request.
func IsDischargeError ¶
IsDischargeError reports whether err is a *DischargeError.
func IsInteractionError ¶
IsInteractionError reports whether err is an *InteractionError.
func MacaroonsForURL ¶
MacaroonsForURL returns any macaroons associated with the given URL in the given cookie jar.
func NewCookie ¶
NewCookie takes a slice of macaroons and returns them encoded as a cookie. The slice should contain a single primary macaroon in its first element, and any discharges after that.
func NewDischargeRequiredError ¶
NewDischargeRequiredError returns an error of type *Error that reports the given original error and includes the given macaroon.
The returned macaroon will be declared as valid for the given URL path and may be relative. When the client stores the discharged macaroon as a cookie this will be the path associated with the cookie. See ErrorInfo.MacaroonPath for more information.
func NewDischargeRequiredErrorForRequest ¶
func NewDischargeRequiredErrorForRequest(m *macaroon.Macaroon, path string, originalErr error, req *http.Request) error
NewDischargeRequiredErrorForRequest is like NewDischargeRequiredError except that it determines the client's bakery protocol version from the request and returns an error response appropriate for that.
This function should always be used in preference to NewDischargeRequiredError, because it enables in-browser macaroon discharge.
To request a particular cookie name:
err := NewDischargeRequiredErrorForRequest(...) err.(*httpbakery.Error).Info.CookieNameSuffix = cookieName
func NewHTTPClient ¶
NewHTTPClient returns an http.Client that ensures that headers are sent to the server even when the server redirects a GET request. The returned client also contains an empty in-memory cookie jar.
func NewInteractionRequiredError ¶
func NewInteractionRequiredError(visitURL, waitURL string, originalErr error, req *http.Request) error
NewInteractionRequiredError returns an error of type *Error that requests an interaction from the client in response to the given request. The originalErr value describes the original error - if it is nil, a default message will be provided.
See Error.ErrorInfo for more details of visitURL and waitURL.
This function should be used in preference to creating the Error value directly, as it sets the bakery protocol version correctly in the error.
func OpenWebBrowser ¶
OpenWebBrowser opens a web browser at the given URL. If the OS is not recognised, the URL is just printed to standard output.
func PublicKeyForLocation ¶
PublicKeyForLocation returns the public key from a macaroon discharge server running at the given location URL. Note that this is insecure if an http: URL scheme is used. If client is nil, http.DefaultClient will be used.
func RequestMacaroons ¶
RequestMacaroons returns any collections of macaroons from the header and cookies found in the request. By convention, each slice will contain a primary macaroon followed by its discharges.
func SameClientIPAddrCaveat ¶
SameClientIPAddrCaveat returns a caveat that will check that the remote IP address is the same as that in the given HTTP request.
func SetCookie ¶
SetCookie sets a cookie for the given URL on the given cookie jar that will holds the given macaroon slice. The macaroon slice should contain a single primary macaroon in its first element, and any discharges after that.
func WriteDischargeRequiredError ¶
func WriteDischargeRequiredError(w http.ResponseWriter, m *macaroon.Macaroon, path string, originalErr error)
WriteDischargeRequiredError creates an error using NewDischargeRequiredError and writes it to the given response writer, indicating that the client should discharge the macaroon to allow the original request to be accepted.
func WriteDischargeRequiredErrorForRequest ¶
func WriteDischargeRequiredErrorForRequest(w http.ResponseWriter, m *macaroon.Macaroon, path string, originalErr error, req *http.Request)
WriteDischargeRequiredErrorForRequest is like NewDischargeRequiredError but uses the given request to determine the protocol version appropriate for the client.
This function should always be used in preference to WriteDischargeRequiredError, because it enables in-browser macaroon discharge.
Types ¶
type Client ¶
type Client struct { // Client holds the HTTP client to use. It should have a cookie // jar configured, and when redirecting it should preserve the // headers (see NewHTTPClient). *http.Client // WebPageVisitor holds a Visitor that is called when the // discharge process requires further interaction. If this // is nil, VisitWebPage will be called; if that is also nil, no // interaction will be allowed. // // The VisitWebPage method will always be called with a map // containing a single entry with the key UserInteractionMethod, // holding the URL found in the InteractionRequired error's // VisitURL field. WebPageVisitor Visitor // VisitWebPage is called when WebPageVisitor is nil and // the discharge process requires further interaction. // // Note that this field is now deprecated in favour of // WebPageVisitor, which will take priority if set. VisitWebPage func(*url.URL) error // Key holds the client's key. If set, the client will try to // discharge third party caveats with the special location // "local" by using this key. See bakery.DischargeAllWithKey and // bakery.LocalThirdPartyCaveat for more information Key *bakery.KeyPair // DischargeAcquirer holds the object that will be used to obtain // third-party discharges. If nil, the Client itself will be used. DischargeAcquirer DischargeAcquirer }
Client holds the context for making HTTP requests that automatically acquire and discharge macaroons.
func NewClient ¶
func NewClient() *Client
NewClient returns a new Client containing an HTTP client created with NewHTTPClient and leaves all other fields zero.
func (*Client) AcquireDischarge ¶
func (c *Client) AcquireDischarge(originalLocation string, cav macaroon.Caveat) (*macaroon.Macaroon, error)
AcquireDischarge implements DischargeAcquirer by requesting a discharge macaroon from the caveat location as an HTTP URL.
func (*Client) DischargeAll ¶
DischargeAll attempts to acquire discharge macaroons for all the third party caveats in m, and returns a slice containing all of them bound to m.
If the discharge fails because a third party refuses to discharge a caveat, the returned error will have a cause of type *DischargeError. If the discharge fails because visitWebPage returns an error, the returned error will have a cause of *InteractionError.
The returned macaroon slice will not be stored in the client cookie jar (see SetCookie if you need to do that).
func (*Client) Do ¶
Do sends the given HTTP request and returns its response. If the request fails with a discharge-required error, any required discharge macaroons will be acquired, and the request will be repeated with those attached. Do may add headers to req.Header.
If the required discharges were refused by a third party, an error with a *DischargeError cause will be returned.
Note that because the request may be retried, no body may be provided in the request, otherwise the contents will be lost when retrying. For requests with a body (for example PUT or POST methods), use DoWithBody instead.
If interaction is required by the user, the visitWebPage function is called with a URL to be opened in a web browser. If visitWebPage returns an error, an error with a *InteractionError cause will be returned. See OpenWebBrowser for a possible implementation of visitWebPage.
func (*Client) DoWithBody ¶
DoWithBody is like Do except that the given body is used for the body of the HTTP request, and reset to its start by seeking if the request is retried. It is an error if req.Body is non-zero.
Note that, unlike the request body passed to http.NewRequest, the body will not be closed even if implements io.Closer.
Do may add headers to req.Header.
func (*Client) DoWithBodyAndCustomError ¶
func (c *Client) DoWithBodyAndCustomError(req *http.Request, body io.ReadSeeker, getError func(resp *http.Response) error) (*http.Response, error)
DoWithBodyAndCustomError is like DoWithBody except it allows a client to specify a custom error function, getError, which is called on the HTTP response and may return a non-nil error if the response holds an error. If the cause of the returned error is a *Error value and its code is ErrDischargeRequired, the macaroon in its Info field will be discharged and the request will be repeated with the discharged macaroon. If getError returns nil, it should leave the response body unchanged.
If getError is nil, DefaultGetError will be used.
This method can be useful when dealing with APIs that return their errors in a format incompatible with Error, but the need for it should be avoided when creating new APIs, as it makes the endpoints less amenable to generic tools.
func (*Client) HandleError ¶
HandleError tries to resolve the given error, which should be a response to the given URL, by discharging any macaroon contained in it. That is, if the error cause is an *Error and its code is ErrDischargeRequired, then it will try to discharge err.Info.Macaroon. If the discharge succeeds, the discharged macaroon will be saved to the client's cookie jar and ResolveError will return nil.
For any other kind of error, the original error will be returned.
type DischargeAcquirer ¶
type DischargeAcquirer interface { // AcquireDischarge should return a discharge macaroon for the given third // party caveat. The firstPartyLocation holds the location of the original // macaroon. AcquireDischarge(firstPartyLocation string, cav macaroon.Caveat) (*macaroon.Macaroon, error) }
DischargeAcquirer can be implemented by clients that want to customize the discharge-acquisition process used by a Client.
type DischargeError ¶
type DischargeError struct { // Reason holds the underlying remote error that caused the // discharge to fail. Reason *Error }
DischargeError represents the error when a third party discharge is refused by a server.
func (*DischargeError) Error ¶
func (e *DischargeError) Error() string
type Error ¶
type Error struct { Code ErrorCode `json:",omitempty"` Message string `json:",omitempty"` Info *ErrorInfo `json:",omitempty"` // contains filtered or unexported fields }
Error holds the type of a response from an httpbakery HTTP request, marshaled as JSON.
Note: Do not construct Error values with ErrDischargeRequired or ErrInteractionRequired codes directly - use the NewDischargeRequiredErrorForRequest or NewInteractionRequiredError functions instead.
type ErrorCode ¶
type ErrorCode string
ErrorCode holds an error code that classifies an error returned from a bakery HTTP handler.
type ErrorInfo ¶
type ErrorInfo struct { // Macaroon may hold a macaroon that, when // discharged, may allow access to a service. // This field is associated with the ErrDischargeRequired // error code. Macaroon *macaroon.Macaroon `json:",omitempty"` // MacaroonPath holds the URL path to be associated // with the macaroon. The macaroon is potentially // valid for all URLs under the given path. // If it is empty, the macaroon will be associated with // the original URL from which the error was returned. MacaroonPath string `json:",omitempty"` // CookieNameSuffix holds the desired cookie name suffix to be // associated with the macaroon. The actual name used will be // ("macaroon-" + CookieName). Clients may ignore this field - // older clients will always use ("macaroon-" + // macaroon.Signature() in hex). CookieNameSuffix string `json:",omitempty"` // VisitURL holds a URL that the client should visit // in a web browser to authenticate themselves. VisitURL string `json:",omitempty"` // WaitURL holds a URL that the client should visit // to acquire the discharge macaroon. A GET on // this URL will block until the client has authenticated, // and then it will return the discharge macaroon. WaitURL string `json:",omitempty"` }
ErrorInfo holds additional information provided by an error.
type InteractionError ¶
type InteractionError struct { // Reason holds the actual error returned from visitWebPage. Reason error }
InteractionError wraps an error returned by a call to visitWebPage.
func (*InteractionError) Error ¶
func (e *InteractionError) Error() string
type PublicKeyRing ¶
type PublicKeyRing struct {
// contains filtered or unexported fields
}
PublicKeyRing represents a public keyring that can interrogate remote services for their public keys. By default it refuses to use insecure URLs.
func NewPublicKeyRing ¶
func NewPublicKeyRing(client *http.Client, cache *bakery.PublicKeyRing) *PublicKeyRing
NewPublicKeyRing returns a new public keyring that uses the given client to find public keys and uses the given cache as a backing. If cache is nil, a new cache will be created. If client is nil, http.DefaultClient will be used.
func (*PublicKeyRing) AllowInsecure ¶
func (kr *PublicKeyRing) AllowInsecure()
AllowInsecure allows insecure URLs. This can be useful for testing purposes.
func (*PublicKeyRing) PublicKeyForLocation ¶
func (kr *PublicKeyRing) PublicKeyForLocation(loc string) (*bakery.PublicKey, error)
PublicKeyForLocation implements bakery.PublicKeyLocator by first looking in the backing cache and, if that fails, making an HTTP request to the public key associated with the given discharge location.
type Visitor ¶
Visitor represents a handler that can handle ErrInteractionRequired errors from a client's discharge request. The methodURLs parameter to VisitWebPage holds a set of possible ways to complete the discharge request. When called directly from Client, this will contain only a single entry with the UserInteractionMethod key, specifying that the associated URL should be opened in a web browser for the user to interact with.
See FallbackVisitor for a way to gain access to alternative methods.
A Visitor implementation should return ErrMethodNotSupported if it cannot handle any of the supplied methods.
var WebBrowserVisitor Visitor = webBrowserVisitor{}
WebBrowserVisitor holds an interactor that supports the "Interactive" method by opening a web browser at the required location.
func NewMultiVisitor ¶
NewMultiVisitor returns a Visitor that queries the discharger for available methods and then tries each of the given visitors in turn until one succeeds or fails with an error cause other than ErrMethodNotSupported.
type WaitResponse ¶
type WaitResponse struct {
Macaroon *macaroon.Macaroon
}
WaitResponse holds the type that should be returned by an HTTP response made to a WaitURL (See the ErrorInfo type).
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package agent enables non-interactive (agent) login using macaroons.
|
Package agent enables non-interactive (agent) login using macaroons. |
Package form enables interactive login without using a web browser.
|
Package form enables interactive login without using a web browser. |