blob: 920960de878b4190987621de9c19fc5f7cf1443d [file] [log] [blame]
David K. Bainbridge528b3182017-01-23 08:51:59 -08001// Copyright 2012-2016 Canonical Ltd.
2// Licensed under the LGPLv3, see LICENCE file for details.
3
4package gomaasapi
5
6import (
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
17func 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
26func generateTimestamp() string {
27 return strconv.Itoa(int(time.Now().Unix()))
28}
29
30type OAuthSigner interface {
31 OAuthSign(request *http.Request) error
32}
33
34type 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.
42var _ OAuthSigner = (*plainTextOAuthSigner)(nil)
43
44type plainTextOAuthSigner struct {
45 token *OAuthToken
46 realm string
47}
48
49func 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.
55func (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}