identity.go raw
1 package internal
2
3 import (
4 "context"
5 "fmt"
6 "io"
7 "net/http"
8 "strings"
9
10 "github.com/go-acme/lego/v4/providers/dns/internal/errutils"
11 )
12
13 type token string
14
15 const tokenKey token = "token"
16
17 // login Logs in as API user.
18 // Authenticates and receives a token to be used in for subsequent requests.
19 // https://docs.bluecatnetworks.com/r/Address-Manager-Legacy-v1-API-Guide/GET/v1/login/9.5.0
20 func (c *Client) login(ctx context.Context) (string, error) {
21 endpoint := c.createEndpoint("login")
22
23 q := endpoint.Query()
24 q.Set("username", c.username)
25 q.Set("password", c.password)
26 endpoint.RawQuery = q.Encode()
27
28 req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
29 if err != nil {
30 return "", err
31 }
32
33 resp, err := c.HTTPClient.Do(req)
34 if err != nil {
35 return "", errutils.NewHTTPDoError(req, err)
36 }
37
38 defer func() { _ = resp.Body.Close() }()
39
40 if resp.StatusCode != http.StatusOK {
41 return "", errutils.NewUnexpectedResponseStatusCodeError(req, resp)
42 }
43
44 raw, err := io.ReadAll(resp.Body)
45 if err != nil {
46 return "", errutils.NewReadResponseError(req, resp.StatusCode, err)
47 }
48
49 authResp := string(raw)
50 if strings.Contains(authResp, "Authentication Error") {
51 return "", fmt.Errorf("request failed: %s", strings.Trim(authResp, `"`))
52 }
53
54 // Upon success, API responds with "Session Token-> BAMAuthToken: dQfuRMTUxNjc3MjcyNDg1ODppcGFybXM= <- for User : username"
55 tok := c.tokenExp.FindString(authResp)
56
57 return tok, nil
58 }
59
60 // Logout Logs out of the current API session.
61 // https://docs.bluecatnetworks.com/r/Address-Manager-Legacy-v1-API-Guide/GET/v1/logout/9.5.0
62 func (c *Client) Logout(ctx context.Context) error {
63 if getToken(ctx) == "" {
64 // nothing to do
65 return nil
66 }
67
68 endpoint := c.createEndpoint("logout")
69
70 req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
71 if err != nil {
72 return err
73 }
74
75 resp, err := c.doAuthenticated(ctx, req)
76 if err != nil {
77 return errutils.NewHTTPDoError(req, err)
78 }
79
80 defer func() { _ = resp.Body.Close() }()
81
82 if resp.StatusCode != http.StatusOK {
83 return errutils.NewUnexpectedResponseStatusCodeError(req, resp)
84 }
85
86 raw, err := io.ReadAll(resp.Body)
87 if err != nil {
88 return errutils.NewReadResponseError(req, resp.StatusCode, err)
89 }
90
91 authResp := string(raw)
92 if !strings.Contains(authResp, "successfully") {
93 return fmt.Errorf("request failed to delete session: %s", strings.Trim(authResp, `"`))
94 }
95
96 return nil
97 }
98
99 func (c *Client) CreateAuthenticatedContext(ctx context.Context) (context.Context, error) {
100 tok, err := c.login(ctx)
101 if err != nil {
102 return nil, err
103 }
104
105 return context.WithValue(ctx, tokenKey, tok), nil
106 }
107
108 func getToken(ctx context.Context) string {
109 tok, ok := ctx.Value(tokenKey).(string)
110 if !ok {
111 return ""
112 }
113
114 return tok
115 }
116