github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/authentication/visitor.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package authentication
     5  
     6  import (
     7  	"encoding/json"
     8  	"net/http"
     9  	"net/url"
    10  
    11  	"github.com/juju/errors"
    12  	"gopkg.in/macaroon-bakery.v2-unstable/httpbakery"
    13  )
    14  
    15  const authMethod = "juju_userpass"
    16  
    17  // Visitor is a httpbakery.Visitor that will login directly
    18  // to the Juju controller using password authentication. This
    19  // only applies when logging in as a local user.
    20  type Visitor struct {
    21  	username    string
    22  	getPassword func(string) (string, error)
    23  }
    24  
    25  // NewVisitor returns a new Visitor.
    26  func NewVisitor(username string, getPassword func(string) (string, error)) *Visitor {
    27  	return &Visitor{
    28  		username:    username,
    29  		getPassword: getPassword,
    30  	}
    31  }
    32  
    33  // VisitWebPage is part of the httpbakery.Visitor interface.
    34  func (v *Visitor) VisitWebPage(client *httpbakery.Client, methodURLs map[string]*url.URL) error {
    35  	methodURL := methodURLs[authMethod]
    36  	if methodURL == nil {
    37  		return httpbakery.ErrMethodNotSupported
    38  	}
    39  
    40  	password, err := v.getPassword(v.username)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	// POST to the URL with username and password.
    46  	resp, err := client.PostForm(methodURL.String(), url.Values{
    47  		"user":     {v.username},
    48  		"password": {password},
    49  	})
    50  	if err != nil {
    51  		return err
    52  	}
    53  	defer resp.Body.Close()
    54  
    55  	if resp.StatusCode == http.StatusOK {
    56  		return nil
    57  	}
    58  	var jsonError httpbakery.Error
    59  	if err := json.NewDecoder(resp.Body).Decode(&jsonError); err != nil {
    60  		return errors.Annotate(err, "unmarshalling error")
    61  	}
    62  	return &jsonError
    63  }