...

Source file src/github.com/aws/smithy-go/auth/bearer/middleware.go

Documentation: github.com/aws/smithy-go/auth/bearer

     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  // Message is the middleware stack's request transport message value.
    12  type Message interface{}
    13  
    14  // Signer provides an interface for implementations to decorate a request
    15  // message with a bearer token. The signer is responsible for validating the
    16  // message type is compatible with the signer.
    17  type Signer interface {
    18  	SignWithBearerToken(context.Context, Token, Message) (Message, error)
    19  }
    20  
    21  // AuthenticationMiddleware provides the Finalize middleware step for signing
    22  // an request message with a bearer token.
    23  type AuthenticationMiddleware struct {
    24  	signer        Signer
    25  	tokenProvider TokenProvider
    26  }
    27  
    28  // AddAuthenticationMiddleware helper adds the AuthenticationMiddleware to the
    29  // middleware Stack in the Finalize step with the options provided.
    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  // NewAuthenticationMiddleware returns an initialized AuthenticationMiddleware.
    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  // ID returns the resolver identifier
    48  func (m *AuthenticationMiddleware) ID() string {
    49  	return authenticationMiddlewareID
    50  }
    51  
    52  // HandleFinalize implements the FinalizeMiddleware interface in order to
    53  // update the request with bearer token authentication.
    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  // SignHTTPSMessage provides a bearer token authentication implementation that
    74  // will sign the message with the provided bearer token.
    75  //
    76  // Will fail if the message is not a smithy-go HTTP request or the request is
    77  // not HTTPS.
    78  type SignHTTPSMessage struct{}
    79  
    80  // NewSignHTTPSMessage returns an initialized signer for HTTP messages.
    81  func NewSignHTTPSMessage() *SignHTTPSMessage {
    82  	return &SignHTTPSMessage{}
    83  }
    84  
    85  // SignWithBearerToken returns a copy of the HTTP request with the bearer token
    86  // added via the "Authorization" header, per RFC 6750, https://datatracker.ietf.org/doc/html/rfc6750.
    87  //
    88  // Returns an error if the request's URL scheme is not HTTPS, or the request
    89  // message is not an smithy-go HTTP Request pointer type.
    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