Documentation ¶
Overview ¶
Package authorization handles gRPC calls authorization via metadata, similary to the `Authorization` header (https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Authorization) in HTTP.
Index ¶
Examples ¶
Constants ¶
const (
// MetadataName is the name of the metadata that holds the authorization credential.
MetadataName = "authorization"
)
Variables ¶
var ( // ErrInvalidOptionValue is returned when using an invalid option value ErrInvalidOptionValue = errors.New("invalid option value") // ErrUnchecked is returned when no Authorization interceptor are in use ErrUnchecked = errors.New("authorization metadata is unchecked") // ErrMissing is returned when request was made without authorization metadata ErrMissing = errors.New("request has no authorization credentials") // ErrInvalid is returned when request was made with an invalid authorization metadata ErrInvalid = errors.New("authorization credentials are invalid") // ErrType is returned when trying to get authorization result as the wrong type ErrType = errors.New("authorization has the wrong type") // ErrInvalidMethod is returned when trying to use an invalid authorization method ErrInvalidMethod = errors.New("invalid authorization method") )
Functions ¶
func AppendToOutgoingContext ¶
func AppendToOutgoingContext(ctx context.Context, method, credential string) (context.Context, error)
AppendToOutgoingContext will return a new context with authentification metadata for a given method appended to the outgoing context. `method` must be a non empty string with lowercase alphanumeric characters, not containing whitespaces. If context's outgoing metadata already contains a credential, it is replaced,
func GetFromContext ¶
GetFromContext gets the authorization value, if request has been made with a valid metadata and passed throught interceptor and sets ir into `dest`. If not, can return ErrUnchecked, ErrMissing, ErrInvalid or ErrType
Example ¶
ExampleGetFromContext show how to get the `CredentialValidator` result in a gRPC method handler
package main import ( "context" "errors" "github.com/jucrouzet/grpcutils/pkg/authorization" ) func main() { var usr *User err := authorization.GetFromContext(ctx, &usr) if errors.Is(err, authorization.ErrMissing) { // No authorization was sent from client } if errors.Is(err, authorization.ErrInvalid) { // Authorization sent from client is invalid } if err != nil { // Another error (like wrong type or interceptor not used) } // usr is now the result of CredentialValidator is it returned a *User } var ctx context.Context type User struct { }
Output:
Types ¶
type Authorization ¶
type Authorization struct {
// contains filtered or unexported fields
}
Authorization handles authorization of methods via metadata
func New ¶
func New(opts ...Options) (*Authorization, error)
New creates a new instance of Authorization with specified options
Example ¶
ExampleNew creates a new gRPC server that checks authorization with the `basic` method
package main import ( "context" "google.golang.org/grpc" "github.com/jucrouzet/grpcutils/internal/pkg/foobar" "github.com/jucrouzet/grpcutils/pkg/authorization" ) func main() { // checkToken is a function that parses token, see the `WithMethodFunction` example a, err := authorization.New( authorization.WithMethodFunction("basic", checkToken), ) if err != nil { panic(err) } server := grpc.NewServer( grpc.UnaryInterceptor(a.UnaryInterceptor()), grpc.StreamInterceptor(a.StreamInterceptor()), ) foobar.RegisterDummyServiceServer(server, &foobar.UnimplementedDummyServiceServer{}) } func checkToken(ctx context.Context, token string) (any, error) { return "", nil }
Output:
func (*Authorization) StreamInterceptor ¶
func (a *Authorization) StreamInterceptor() grpc.StreamServerInterceptor
StreamInterceptor returns a gRPC server stream interceptor that sets logger in stream context
func (*Authorization) UnaryInterceptor ¶
func (a *Authorization) UnaryInterceptor() grpc.UnaryServerInterceptor
UnaryInterceptor returns a gRPC server unary interceptor that sets logger in call context
type CredentialValidator ¶
CredentialValidator is the function type for functions that validates credentials. The context passed is the unary or stream context, credential is the value/token provided by the caller. The value returned will be stored in the context and available in methods implementations by calling GetFromContext. The returned value type if correct must be the same as the one used in GetFromContext.
type Options ¶
type Options func(*Authorization) error
Options is the Authorization option functions type
func WithMethodFunction ¶
func WithMethodFunction(method string, fn CredentialValidator) Options
WithMethodFunction specifies a credential validation function to be used for a given authorization method. `method` must be a non empty string with lowercase alphanumeric characters, not containing whitespaces.
Example ¶
ExampleWithMethodFunction show how to define a `CredentialValidator` function that parses credentials
package main import ( "context" "github.com/jucrouzet/grpcutils/pkg/authorization" ) func main() { var credentialValidator authorization.CredentialValidator credentialValidator = func(ctx context.Context, credential string) (any, error) { userID, err := parseJWT(credential) if err != nil { return nil, err } user, err := getUserInDB(userID) if err != nil { return nil, err } return user, nil } // auth'd user can later be get (if valid token) with : // var usr *User // err := authorization.GetFromContext(ctx, &usr) authorization.New( authorization.WithMethodFunction("bearer", credentialValidator), ) } func parseJWT(tok string) (string, error) { return "", nil } func getUserInDB(userID string) (*User, error) { return nil, nil } type User struct { }
Output: