...
1 package bearer
2
3 import (
4 "context"
5 "fmt"
6
7 "github.com/aws/smithy-go/middleware"
8 smithyhttp "github.com/aws/smithy-go/transport/http"
9 )
10
11
12 type Message interface{}
13
14
15
16
17 type Signer interface {
18 SignWithBearerToken(context.Context, Token, Message) (Message, error)
19 }
20
21
22
23 type AuthenticationMiddleware struct {
24 signer Signer
25 tokenProvider TokenProvider
26 }
27
28
29
30 func AddAuthenticationMiddleware(s *middleware.Stack, signer Signer, tokenProvider TokenProvider) error {
31 return s.Finalize.Add(
32 NewAuthenticationMiddleware(signer, tokenProvider),
33 middleware.After,
34 )
35 }
36
37
38 func NewAuthenticationMiddleware(signer Signer, tokenProvider TokenProvider) *AuthenticationMiddleware {
39 return &AuthenticationMiddleware{
40 signer: signer,
41 tokenProvider: tokenProvider,
42 }
43 }
44
45 const authenticationMiddlewareID = "BearerTokenAuthentication"
46
47
48 func (m *AuthenticationMiddleware) ID() string {
49 return authenticationMiddlewareID
50 }
51
52
53
54 func (m *AuthenticationMiddleware) HandleFinalize(
55 ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler,
56 ) (
57 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
58 ) {
59 token, err := m.tokenProvider.RetrieveBearerToken(ctx)
60 if err != nil {
61 return out, metadata, fmt.Errorf("failed AuthenticationMiddleware wrap message, %w", err)
62 }
63
64 signedMessage, err := m.signer.SignWithBearerToken(ctx, token, in.Request)
65 if err != nil {
66 return out, metadata, fmt.Errorf("failed AuthenticationMiddleware sign message, %w", err)
67 }
68
69 in.Request = signedMessage
70 return next.HandleFinalize(ctx, in)
71 }
72
73
74
75
76
77
78 type SignHTTPSMessage struct{}
79
80
81 func NewSignHTTPSMessage() *SignHTTPSMessage {
82 return &SignHTTPSMessage{}
83 }
84
85
86
87
88
89
90 func (SignHTTPSMessage) SignWithBearerToken(ctx context.Context, token Token, message Message) (Message, error) {
91 req, ok := message.(*smithyhttp.Request)
92 if !ok {
93 return nil, fmt.Errorf("expect smithy-go HTTP Request, got %T", message)
94 }
95
96 if !req.IsHTTPS() {
97 return nil, fmt.Errorf("bearer token with HTTP request requires HTTPS")
98 }
99
100 reqClone := req.Clone()
101 reqClone.Header.Set("Authorization", "Bearer "+token.Value)
102
103 return reqClone, nil
104 }
105
View as plain text