github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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  
    13  	"gopkg.in/macaroon-bakery.v1/httpbakery"
    14  )
    15  
    16  const authMethod = "juju_userpass"
    17  
    18  // Visitor is a httpbakery.Visitor that will login directly
    19  // to the Juju controller using password authentication. This
    20  // only applies when logging in as a local user.
    21  type Visitor struct {
    22  	username    string
    23  	getPassword func(string) (string, error)
    24  }
    25  
    26  // NewVisitor returns a new Visitor.
    27  func NewVisitor(username string, getPassword func(string) (string, error)) *Visitor {
    28  	return &Visitor{
    29  		username:    username,
    30  		getPassword: getPassword,
    31  	}
    32  }
    33  
    34  // VisitWebPage is part of the httpbakery.Visitor interface.
    35  func (v *Visitor) VisitWebPage(client *httpbakery.Client, methodURLs map[string]*url.URL) error {
    36  	methodURL := methodURLs[authMethod]
    37  	if methodURL == nil {
    38  		return httpbakery.ErrMethodNotSupported
    39  	}
    40  
    41  	password, err := v.getPassword(v.username)
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	// POST to the URL with username and password.
    47  	resp, err := client.PostForm(methodURL.String(), url.Values{
    48  		"user":     {v.username},
    49  		"password": {password},
    50  	})
    51  	if err != nil {
    52  		return err
    53  	}
    54  	defer resp.Body.Close()
    55  
    56  	if resp.StatusCode == http.StatusOK {
    57  		return nil
    58  	}
    59  	var jsonError httpbakery.Error
    60  	if err := json.NewDecoder(resp.Body).Decode(&jsonError); err != nil {
    61  		return errors.Annotate(err, "unmarshalling error")
    62  	}
    63  	return &jsonError
    64  }