~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/gomaasapi/oauth.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012-2016 Canonical Ltd.
 
2
// Licensed under the LGPLv3, see LICENCE file for details.
 
3
 
 
4
package gomaasapi
 
5
 
 
6
import (
 
7
        "crypto/rand"
 
8
        "fmt"
 
9
        "net/http"
 
10
        "net/url"
 
11
        "strconv"
 
12
        "strings"
 
13
        "time"
 
14
)
 
15
 
 
16
// Not a true uuidgen, but at least creates same length random
 
17
func generateNonce() (string, error) {
 
18
        randBytes := make([]byte, 16)
 
19
        _, err := rand.Read(randBytes)
 
20
        if err != nil {
 
21
                return "", err
 
22
        }
 
23
        return fmt.Sprintf("%16x", randBytes), nil
 
24
}
 
25
 
 
26
func generateTimestamp() string {
 
27
        return strconv.Itoa(int(time.Now().Unix()))
 
28
}
 
29
 
 
30
type OAuthSigner interface {
 
31
        OAuthSign(request *http.Request) error
 
32
}
 
33
 
 
34
type OAuthToken struct {
 
35
        ConsumerKey    string
 
36
        ConsumerSecret string
 
37
        TokenKey       string
 
38
        TokenSecret    string
 
39
}
 
40
 
 
41
// Trick to ensure *plainTextOAuthSigner implements the OAuthSigner interface.
 
42
var _ OAuthSigner = (*plainTextOAuthSigner)(nil)
 
43
 
 
44
type plainTextOAuthSigner struct {
 
45
        token *OAuthToken
 
46
        realm string
 
47
}
 
48
 
 
49
func NewPlainTestOAuthSigner(token *OAuthToken, realm string) (OAuthSigner, error) {
 
50
        return &plainTextOAuthSigner{token, realm}, nil
 
51
}
 
52
 
 
53
// OAuthSignPLAINTEXT signs the provided request using the OAuth PLAINTEXT
 
54
// method: http://oauth.net/core/1.0/#anchor22.
 
55
func (signer plainTextOAuthSigner) OAuthSign(request *http.Request) error {
 
56
 
 
57
        signature := signer.token.ConsumerSecret + `&` + signer.token.TokenSecret
 
58
        nonce, err := generateNonce()
 
59
        if err != nil {
 
60
                return err
 
61
        }
 
62
        authData := map[string]string{
 
63
                "realm":                  signer.realm,
 
64
                "oauth_consumer_key":     signer.token.ConsumerKey,
 
65
                "oauth_token":            signer.token.TokenKey,
 
66
                "oauth_signature_method": "PLAINTEXT",
 
67
                "oauth_signature":        signature,
 
68
                "oauth_timestamp":        generateTimestamp(),
 
69
                "oauth_nonce":            nonce,
 
70
                "oauth_version":          "1.0",
 
71
        }
 
72
        // Build OAuth header.
 
73
        var authHeader []string
 
74
        for key, value := range authData {
 
75
                authHeader = append(authHeader, fmt.Sprintf(`%s="%s"`, key, url.QueryEscape(value)))
 
76
        }
 
77
        strHeader := "OAuth " + strings.Join(authHeader, ", ")
 
78
        request.Header.Add("Authorization", strHeader)
 
79
        return nil
 
80
}