-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbpvalidator.go
More file actions
68 lines (62 loc) · 2.45 KB
/
Copy pathbpvalidator.go
File metadata and controls
68 lines (62 loc) · 2.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main
import (
"context"
"fmt"
"net/http"
"github.com/go-resty/resty/v2"
"github.com/hmchangw/chat/pkg/errcode"
"github.com/hmchangw/chat/pkg/natsutil"
"github.com/hmchangw/chat/pkg/principal"
)
// httpBotplatformValidator is the production BotplatformValidator: it POSTs
// the supplied authToken to {baseURL}/v1/auth/validate and unmarshals the
// {valid, principal} response. Resty handles timeout, TLS, and redirects;
// the Resty client is supplied externally (so main wires the shared
// restyutil instance).
type httpBotplatformValidator struct {
client *resty.Client
baseURL string
}
// newHTTPBotplatformValidator returns a validator that talks to the
// botplatform-service at baseURL. baseURL should be the public botplatform
// URL of the LOCAL site (validation is local-DB only — cross-site routing is
// the gateway's job).
func newHTTPBotplatformValidator(client *resty.Client, baseURL string) *httpBotplatformValidator {
return &httpBotplatformValidator{client: client, baseURL: baseURL}
}
// Validate POSTs to botplatform /v1/auth/validate. Returns:
// - a typed errcode.Unauthenticated on a 401 from upstream (caller will
// surface it to the client as 401 invalid_token).
// - a raw wrapped error on network failures or non-2xx/401 statuses
// (caller will surface it as 503 upstream_unavailable).
func (v *httpBotplatformValidator) Validate(ctx context.Context, authToken string) (principal.Principal, error) {
var body struct {
Valid bool `json:"valid"`
Principal principal.Principal `json:"principal"`
}
req := v.client.R().
SetContext(ctx).
SetBody(map[string]string{"authToken": authToken}).
SetResult(&body)
if id := natsutil.RequestIDFromContext(ctx); id != "" {
req = req.SetHeader(natsutil.RequestIDHeader, id)
}
resp, err := req.Post(v.baseURL + "/v1/auth/validate")
if err != nil {
return principal.Principal{}, fmt.Errorf("validate authToken: %w", err)
}
switch resp.StatusCode() {
case http.StatusOK:
if !body.Valid {
return principal.Principal{}, errcode.Unauthenticated("session token invalid",
errcode.WithReason(errcode.BotplatformInvalidToken))
}
return body.Principal, nil
case http.StatusUnauthorized:
return principal.Principal{}, errcode.Unauthenticated("session token invalid",
errcode.WithReason(errcode.BotplatformInvalidToken))
default:
return principal.Principal{}, fmt.Errorf("botplatform validate: HTTP %d: %s",
resp.StatusCode(), string(resp.Body()))
}
}