auth
auth/client/client.go
Use an environment variable to set the JWT secret. When setting up the authd server, populate the JWT secret using a JWT_SECRET environment variable. Incidentally, we also included the subscriptions scope, for testing purposes while creating code.secondbit.org/ducky/subscriptions. We now also log the port we're listening on, listen on all interfaces (instead of just 127.0.0.1), and changed the port to 9000 instead of 8080.
1 package client
3 import (
4 "bytes"
5 "encoding/json"
6 "errors"
7 "io"
8 "net/http"
9 "strings"
10 "time"
12 "code.secondbit.org/auth.hg"
13 "code.secondbit.org/uuid.hg"
14 )
16 var (
17 ErrNilClient = errors.New("nil client wrapper")
18 ErrNilHTTPClient = errors.New("nil client")
19 )
21 type Client struct {
22 client *http.Client
23 address string
24 ID uuid.ID
25 }
27 func New(address string, id uuid.ID) *Client {
28 address = strings.TrimRight(address, "/")
29 return &Client{
30 address: address,
31 client: &http.Client{},
32 ID: id,
33 }
34 }
36 func (c *Client) do(method, url string, request interface{}, scopes []string, subject uuid.ID) (auth.Response, error) {
37 if c == nil {
38 return auth.Response{}, ErrNilClient
39 }
40 if c.client == nil {
41 return auth.Response{}, ErrNilHTTPClient
42 }
43 var response auth.Response
44 if !strings.HasPrefix(url, "http") {
45 url = strings.TrimLeft(url, "/")
46 url = "/" + url
47 url = c.address + url
48 }
49 var body io.Reader
50 if request != nil {
51 data, err := json.Marshal(request)
52 if err != nil {
53 return response, err
54 }
55 body = bytes.NewBuffer(data)
56 }
57 req, err := http.NewRequest(method, url, body)
58 if err != nil {
59 return response, err
60 }
61 req.Header.Set("Ducky-Scope", strings.Join(scopes, " "))
62 req.Header.Set("Ducky-Issuer", c.ID.String())
63 if subject != nil {
64 req.Header.Set("Ducky-Subject", subject.String())
65 }
66 req.Header.Set("Ducky-Expires", time.Now().Add(time.Hour).String())
67 req.Header.Set("Ducky-Issued-At", time.Now().String())
68 req.Header.Set("Ducky-Not-Before", time.Now().Add(-5*time.Minute).String())
69 resp, err := c.client.Do(req)
70 if err != nil {
71 return response, err
72 }
73 defer resp.Body.Close()
74 switch resp.Header.Get("Content-Type") {
75 case "application/json":
76 dec := json.NewDecoder(resp.Body)
77 err = dec.Decode(&response)
78 if err != nil {
79 return response, err
80 }
81 default:
82 dec := json.NewDecoder(resp.Body)
83 err = dec.Decode(&response)
84 if err != nil {
85 return response, err
86 }
87 }
88 return response, nil
89 }
91 func (c *Client) Get(url string, scopes []string, subject uuid.ID) (auth.Response, error) {
92 return c.do("GET", url, nil, scopes, subject)
93 }