Documentation
¶
Overview ¶
Package connectauth provides a flexible authentication interceptor for github.com/bufbuild/connect-go.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"github.com/akshayjshah/connectauth"
"github.com/bufbuild/connect-go"
"google.golang.org/protobuf/types/known/emptypb"
)
// TestServiceHandler is an interface describing the server-side implementation
// of our example RPC service. It would typically be generated from a protobuf
// schema.
type TestServiceHandler interface {
GetEmpty(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[emptypb.Empty], error)
}
// NewTestServiceHandler constructs an HTTP handler. It would typically be
// generated from a protobuf schema.
func NewTestServiceHandler(svc TestServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
const root = "/connectauth.example.v1.TestService/"
mux := http.NewServeMux()
mux.Handle(root+"GetEmpty", connect.NewUnaryHandler(
root+"GetEmpty",
svc.GetEmpty,
opts...,
))
return root, mux
}
// service implements TestServiceHandler. You'd typically hand-write this to
// implement your service's application logic.
type service struct{}
func (s *service) GetEmpty(
ctx context.Context,
_ *connect.Request[emptypb.Empty],
) (*connect.Response[emptypb.Empty], error) {
// Your application logic has access to the authenticated identity.
fmt.Println(connectauth.GetIdentity(ctx))
return connect.NewResponse(&emptypb.Empty{}), nil
}
func main() {
// We express our authentication logic with a small function.
authenticate := func(_ context.Context, req *connectauth.Request) (any, error) {
const magic = "open-sesame"
if req.Header.Get("Authorization") != "Bearer "+magic {
// If authentication fails, we return an error. connectauth.Errorf is a
// convenient shortcut to produce an error coded with
// connect.CodeUnauthenticated.
return nil, connectauth.Errorf("try %q as a bearer token instead", magic)
}
// Once we've authenticated the request, we can return the authenticated
// identity. The identity gets attached to the context passed to subsequent
// interceptors and our service implementation.
return "Ali Baba", nil
}
mux := http.NewServeMux()
mux.Handle(NewTestServiceHandler(
&service{},
connect.WithInterceptors(connectauth.New(authenticate)),
))
http.ListenAndServe(":8080", mux)
}
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Errorf ¶
Errorf is a convenience function that returns an error coded with connect.CodeUnauthenticated.
func GetIdentity ¶
GetIdentity retrieves the authenticated identity, if any, from the request context.
Types ¶
type Interceptor ¶
type Interceptor struct {
// contains filtered or unexported fields
}
Interceptor is a server-side authentication interceptor. In addition to rejecting unauthenticated requests, it can optionally attach an identity to context of authenticated requests.
func New ¶
New constructs a new Interceptor using the supplied authentication function. The authentication function must return an error if the request cannot be authenticated. The error is typically produced with Errorf, but any error will do.
If requests are successfully authenticated, the authentication function may return the authenticated identity. The identity will be attached to the context, so subsequent interceptors and application code may access it with GetIdentity.
Authentication functions must be safe to call concurrently.
func (*Interceptor) WrapStreamingClient ¶ added in v0.1.1
func (i *Interceptor) WrapStreamingClient(next connect.StreamingClientFunc) connect.StreamingClientFunc
WrapStreamingClient implements connect.Interceptor with a no-op.
func (*Interceptor) WrapStreamingHandler ¶
func (i *Interceptor) WrapStreamingHandler(next connect.StreamingHandlerFunc) connect.StreamingHandlerFunc
WrapStreamingHandler implements connect.Interceptor.