cidaasinterceptor

package module
v2.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 9, 2025 License: MIT Imports: 19 Imported by: 0

README

pipeline status coverage report License

Logo

About cidaas:

cidaas is a cloud-native Identity & Access Management platform for both Workforce IAM and Customer IAM (CIAM). It delivers standards-based Single Sign-On, passwordless authentication, multi-factor authentication, consent management, social/enterprise federation, API security for M2M/IoT, and optional identity verification—built to provide secure, low-friction access at scale.

About this project: cidaas-go-interceptor

The cidaas-go-interceptor is lightweight middleware for protecting Go services with cidaas-issued tokens.

  • Supported frameworks: net/http, gRPC, Fiber
  • What it does: validates OIDC/OAuth 2.0 tokens from cidaas and lets you enforce authorization based on scopes/groups/roles with minimal code.
  • Token types: Supports standard access tokens (JWT signature verification or introspection) and PAT (Personal Access Token) tokens (introspection only).

How to install

Version 1.x.x

go get github.com/Cidaas/go-interceptor

This version allows to secure your APIs by passing scopes or roles to the interceptor which can be either validated by introspecting the access token or checking its signature.

Version 2.x.x

go get github.com/Cidaas/go-interceptor/v2

This version allows to secure your APIs by passing security options to the interceptor which can be either validated by introspecting the access token or checking its signature. You can pass the following options to the interceptor:

For the signature validation only the scopes can be validated in a strict way

// SecurityOptions which should be passsed to restrict the api access
type SecurityOptions struct {
	Roles                 []string                 // roles which are allowed to access this api
	Scopes                []string                 // scopes which are allowed to acces this api
	Groups                []GroupValidationOptions // groups which are allowed to acces this api (only possible with introspect, not with signature verification)
	AllowAnonymousSub     bool                     // false (by default) indicates that tokens which have an anonymous sub are rejected, true indicates that tokens which have an ANONYMOUS sub are allowed (only possible with the signature check for now)
	StrictRoleValidation  bool                     // by default false, true indicates that all provided roles must match (only possible with introspect)
	StrictScopeValidation bool                     // by default false, true indicates that all provided scopes must match (also possible with the signature check)
	StrictGroupValidation bool                     // by default false, true indicates that all provided groups must match (only possible with introspect)
	StrictValidation      bool                     // by default false, true indicates that all provided roles, scopes and groups must match (the signature check just checks for the scopes)
}

// GroupValidationOptions provides options to allow API access only to certain groups
// Note: Group validation only works with token introspection, not with signature verification.
// Either GroupID or GroupType should be specified (not both) to define the group criteria.
type GroupValidationOptions struct {
	GroupID              string   `json:"groupId,omitempty"`              // the group id to match (use either GroupID or GroupType)
	GroupType            string   `json:"groupType,omitempty"`            // the group type to match (use either GroupID or GroupType)
	Roles                []string `json:"roles,omitempty"`                // the roles to match
	StrictRoleValidation bool     `json:"strictRoleValidation,omitempty"` // true indicates that all roles must match
	StrictValidation     bool     `json:"strictValidation,omitempty"`     // true indicates that the group id, group type and all roles must match
}
Breaking changes
  • Instead of passing the scopes and roles in order to verify the token, you now need to pass an object with different options, which is explained above
  • Now tokens which have NO SUB are rejected by default, if you want to allow this you need to enable the SecurityOptions.AllowAnonymousSub flag, which is false by default

Usage

The cidaas go interceptor can be used to secure APIs which use the net/http package, the fiber web framework, or gRPC in golang.

gRPC

The gRPC interceptor provides OAuth 2.0 token validation for gRPC services. It supports both signature verification and token introspection methods.

Basic Setup
package main

import (
    "net"
    "log"

    cidaasinterceptor "github.com/Cidaas/go-interceptor/v2"
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
)

func main() {
    // Initialize CIDAAS interceptor
    cidaasOpts := cidaasinterceptor.Options{
        BaseURI:  "https://your-cidaas-instance.cidaas.de",
        ClientID: "your-client-id", // Optional
        Debug:    false,            // Enable for debugging
    }

    grpcInterceptor, err := cidaasinterceptor.NewGrpcInterceptor(cidaasOpts)
    if err != nil {
        log.Fatal().Err(err).Msg("Failed to initialize CIDAAS gRPC interceptor")
    }

    // Create gRPC server with interceptor
    grpcServer := grpc.NewServer(
        grpc.UnaryInterceptor(grpcInterceptor.VerifyTokenByIntrospect(defaultSecurityOpts)),
    )

    // Register your services
    // yourpb.RegisterYourServiceServer(grpcServer, &YourService{})

    // Enable reflection for debugging
    reflection.Register(grpcServer)

    // Start server
    lis, err := net.Listen("tcp", ":9090")
    if err != nil {
        log.Fatal().Err(err).Msg("Failed to listen")
    }

    log.Info().Msg("Starting gRPC server on :9090")
    if err := grpcServer.Serve(lis); err != nil {
        log.Fatal().Err(err).Msg("Failed to serve gRPC")
    }
}
Security Options Configuration
// Default security options for basic authentication
defaultSecurityOpts := cidaasinterceptor.SecurityOptions{
    Scopes:                []string{"vault:kms_read", "vault:kms_manage"},
    Roles:                 []string{"admin", "user"},
    StrictScopeValidation: false, // Allow any of the scopes
    StrictRoleValidation:  false, // Allow any of the roles
    AllowAnonymousSub:     false, // Reject anonymous tokens
}

// Strict validation - all scopes and roles must match
strictSecurityOpts := cidaasinterceptor.SecurityOptions{
    Scopes:                []string{"vault:kms_read", "vault:kms_manage"},
    Roles:                 []string{"admin"},
    StrictScopeValidation: true,  // All scopes must be present
    StrictRoleValidation:  true,  // All roles must be present
    AllowAnonymousSub:     false,
}
Token Validation Methods

1. Signature Verification (JWT)

// Verify token by signature (faster, no network calls)
interceptor := grpcInterceptor.VerifyTokenBySignature(cidaasinterceptor.SecurityOptions{
    Scopes:                []string{"vault:kms_read"},
    StrictScopeValidation: true,
    AllowAnonymousSub:     false,
})

grpcServer := grpc.NewServer(grpc.UnaryInterceptor(interceptor))

2. Token Introspection (OAuth 2.0)

// Verify token by introspection (more secure, validates token status)
// Note: Group validation only works with introspection, not with signature verification
interceptor := grpcInterceptor.VerifyTokenByIntrospect(cidaasinterceptor.SecurityOptions{
	Scopes:                []string{"vault:kms_read", "vault:kms_manage"},
	Roles:                 []string{"admin", "user"},
		Groups:                []cidaasinterceptor.GroupValidationOptions{
			{
				GroupID:   "vault-users", // Use either GroupID or GroupType, not both
				Roles:     []string{"user"},
			},
		},
	StrictScopeValidation: false,
	StrictRoleValidation:  false,
	StrictGroupValidation: false,
})

grpcServer := grpc.NewServer(grpc.UnaryInterceptor(interceptor))
Accessing Token Data in Service Methods
type VaultService struct {
    pb.UnimplementedVaultServiceServer
}

func (s *VaultService) GetSecret(ctx context.Context, req *pb.GetSecretRequest) (*pb.GetSecretResponse, error) {
    // Get token data from context
    tokenData, ok := cidaasinterceptor.GetTokenDataFromGrpcContext(ctx)
    if !ok {
        return nil, status.Error(codes.Internal, "token data not found in context")
    }

    // Access subject (user ID)
    userID := tokenData.Sub

    // Access audience (client ID)
    clientID := tokenData.Aud

    // Your business logic here
    secret, err := s.getSecretForUser(userID, req.SecretId)
    if err != nil {
        return nil, status.Errorf(codes.Internal, "failed to get secret: %v", err)
    }

    return &pb.GetSecretResponse{
        Secret: secret,
    }, nil
}

// Helper functions for common token data access
func (s *VaultService) CreateKey(ctx context.Context, req *pb.CreateKeyRequest) (*pb.CreateKeyResponse, error) {
    // Get subject directly
    userID, ok := cidaasinterceptor.GetSubFromGrpcContext(ctx)
    if !ok {
        return nil, status.Error(codes.Internal, "user ID not found in context")
    }

    // Get audience directly
    clientID, ok := cidaasinterceptor.GetAudFromGrpcContext(ctx)
    if !ok {
        return nil, status.Error(codes.Internal, "client ID not found in context")
    }

    // Your business logic here
    return s.createKeyForUser(userID, req), nil
}
Client Authentication

Clients must include the Bearer token in the gRPC metadata:

// Client-side code
import (
    "context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/metadata"
)

func callSecureService(client pb.VaultServiceClient, token string) error {
    // Add token to metadata
    md := metadata.New(map[string]string{
        "authorization": "Bearer " + token,
    })
    ctx := metadata.NewOutgoingContext(context.Background(), md)

    // Make authenticated call
    resp, err := client.GetSecret(ctx, &pb.GetSecretRequest{
        SecretId: "my-secret",
    })
    if err != nil {
        return err
    }

    return nil
}
Error Handling

The interceptor returns appropriate gRPC error codes:

  • codes.Unauthenticated: Invalid or missing token
  • codes.PermissionDenied: Token valid but insufficient permissions
  • codes.Internal: Configuration or network errors
// Handle authentication errors in your service
func (s *VaultService) SecureOperation(ctx context.Context, req *pb.SecureRequest) (*pb.SecureResponse, error) {
    tokenData, ok := cidaasinterceptor.GetTokenDataFromGrpcContext(ctx)
    if !ok {
        return nil, status.Error(codes.Unauthenticated, "authentication required")
    }

    // Check if user has specific permissions
    if !s.hasPermission(tokenData.Sub, "admin") {
        return nil, status.Error(codes.PermissionDenied, "insufficient permissions")
    }

    // Proceed with operation
    return s.performSecureOperation(req), nil
}
Advanced Configuration

Per-Endpoint Security Validation:

The gRPC interceptor supports per-endpoint security validation, allowing you to define different security requirements for each API endpoint.

func main() {
    cidaasOpts := cidaasinterceptor.Options{
        BaseURI:  "https://your-cidaas-instance.cidaas.de",
        ClientID: "your-client-id",
        Debug:    true,
    }

    grpcInterceptor, err := cidaasinterceptor.NewGrpcInterceptor(cidaasOpts)
    if err != nil {
        log.Fatal().Err(err).Msg("Failed to initialize interceptor")
    }

    // Define per-endpoint security requirements
    endpointSecurity := func(fullMethod string) cidaasinterceptor.SecurityOptions {
        switch fullMethod {
        case "/vault.VaultService/Encrypt":
            return cidaasinterceptor.SecurityOptions{
                Scopes:                []string{"vault:kms_manage"},
                StrictScopeValidation: true,
            }
        case "/vault.VaultService/Decrypt":
            return cidaasinterceptor.SecurityOptions{
                Scopes:                []string{"vault:kms_read"},
                StrictScopeValidation: true,
            }
        case "/vault.VaultService/GenerateKey":
            return cidaasinterceptor.SecurityOptions{
                Scopes:                []string{"vault:kms_manage"},
                Groups:                []cidaasinterceptor.GroupValidationOptions{
                    {
                        GroupID:   "key-management",
                        Roles:     []string{"admin", "key_manager"},
                        StrictRoleValidation: false,
                    },
                },
                StrictScopeValidation: true,
                StrictGroupValidation: false,
            }
        case "/vault.VaultService/DeleteKey":
            return cidaasinterceptor.SecurityOptions{
                Scopes:                []string{"vault:kms_manage"},
                Roles:                 []string{"admin"},
                StrictScopeValidation: true,
                StrictRoleValidation:  true, // Must have admin role
            }
        case "/vault.VaultService/Health":
            return cidaasinterceptor.SecurityOptions{
                AllowAnonymousSub: true, // Public endpoint
            }
        default:
            // Default security for unknown endpoints
            return cidaasinterceptor.SecurityOptions{
                Scopes:                []string{"vault:kms_read"},
                StrictScopeValidation: false,
            }
        }
    }

    // Create gRPC server with per-endpoint validation
    grpcServer := grpc.NewServer(
        grpc.UnaryInterceptor(
            grpcInterceptor.VerifyTokenByIntrospectWithEndpointValidation(endpointSecurity),
        ),
    )

    // Register services
    // pb.RegisterVaultServiceServer(grpcServer, &VaultService{})
}

Multiple Interceptors with Different Security Levels:

func main() {
    cidaasOpts := cidaasinterceptor.Options{
        BaseURI:  "https://your-cidaas-instance.cidaas.de",
        ClientID: "your-client-id",
        Debug:    true,
    }

    grpcInterceptor, err := cidaasinterceptor.NewGrpcInterceptor(cidaasOpts)
    if err != nil {
        log.Fatal().Err(err).Msg("Failed to initialize interceptor")
    }

    // Create interceptors for different security levels
    adminInterceptor := grpcInterceptor.VerifyTokenByIntrospect(cidaasinterceptor.SecurityOptions{
        Roles:                []string{"admin"},
        StrictRoleValidation: true,
    })

    userInterceptor := grpcInterceptor.VerifyTokenByIntrospect(cidaasinterceptor.SecurityOptions{
        Scopes:                []string{"vault:read", "vault:write"},
        StrictScopeValidation: false,
    })

    // Use different interceptors for different services
    adminServer := grpc.NewServer(grpc.UnaryInterceptor(adminInterceptor))
    userServer := grpc.NewServer(grpc.UnaryInterceptor(userInterceptor))

    // Register services
    // pb.RegisterAdminServiceServer(adminServer, &AdminService{})
    // pb.RegisterUserServiceServer(userServer, &UserService{})
}

Debug Mode:

cidaasOpts := cidaasinterceptor.Options{
    BaseURI:  "https://your-cidaas-instance.cidaas.de",
    ClientID: "your-client-id",
    Debug:    true, // Enable debug logging
}

When debug mode is enabled, the interceptor logs:

  • Token scopes and roles
  • Validation decisions
  • Introspection requests and responses
  • JWKS key retrieval

net/http

The following examples will show how to use the interceptor if you are using the net/http package for your APIs.

Attached an example how to secure an API with scopes and roles based on the signature of a token:

Version 1.x.x
func get(w http.ResponseWriter, r *http.Request) {
	// set response to ok and return Status ok and response
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(respJSON))
	return
}

func main() {
	r := mux.NewRouter()
	api := r.PathPrefix("/api/v1").Subrouter()
	// Base URI is mandatory, ClientID is optional, if ClientID is set the interceptor will only allow requests from this Client
	cidaasInterceptor, err := cidaasinterceptor.New(cidaasinterceptor.Options{BaseURI: "https://base.cidaas.de", ClientID: "clientID"})
	if err != nil {
		log.Panicf("Initialization of cidaas interceptor failed! Error: %v", err)
		panic("Panic!")
	}
	getHandler := http.HandlerFunc(get)
	api.Handle("/", cidaasInterceptor.VerifyTokenBySignature(getHandler, []string{"profile", "cidaas:api_scope"}, []string{"role:Admin"})).Methods(http.MethodGet)
	log.Fatal(http.ListenAndServe(":8080", r))
}
Version 2.x.x
func get(w http.ResponseWriter, r *http.Request) {
	// set response to ok and return Status ok and response
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(respJSON))
	return
}

func main() {
	r := mux.NewRouter()
	api := r.PathPrefix("/api/v2").Subrouter()
	// Base URI is mandatory, ClientID is optional, if ClientID is set the interceptor will only allow requests from this Client
	cidaasInterceptor, err := cidaasinterceptor.New(cidaasinterceptor.Options{BaseURI: "https://base.cidaas.de", ClientID: "clientID"})
	if err != nil {
		log.Panicf("Initialization of cidaas interceptor failed! Error: %v", err)
		panic("Panic!")
	}
	getHandler := http.HandlerFunc(get)
	api.Handle("/", cidaasInterceptor.VerifyTokenBySignature(getHandler, cidaasinterceptor.SecurityOptions{
		Scopes: []string{"your scope"},
		Roles: []string{"role:Admin"},
	})).Methods(http.MethodGet)
	api.Handle("/user", cidaasInterceptor.VerifyTokenBySignature(getHandler, cidaasinterceptor.SecurityOptions{
		AllowAnonymousSub: true, // add this flag if you want to allow tokens with an anonymous sub
		Scopes: []string{"your scope"},
		Roles: []string{"role:Admin"},
	})).Methods(http.MethodGet)
	log.Fatal(http.ListenAndServe(":8080", r))
}

Attached an example how to secure an API with scopes and roles based on an introspect call to the cidaas instance:

Version 1.x.x
func get(w http.ResponseWriter, r *http.Request) {
	// set response to ok and return Status ok and response
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(respJSON))
	return
}

func main() {
	r := mux.NewRouter()
	api := r.PathPrefix("/api/v1").Subrouter()
	// Base URI is mandatory, ClientID is optional, if ClientID is set the interceptor will only allow requests from this Client
	cidaasInterceptor, err := cidaasinterceptor.New(cidaasinterceptor.Options{BaseURI: "https://base.cidaas.de", ClientID: "clientID"})
	if err != nil {
		log.Panicf("Initialization of cidaas interceptor failed! Error: %v", err)
		panic("Panic!")
	}
	getHandler := http.HandlerFunc(get)
	api.Handle("", cidaasInterceptor.VerifyTokenByIntrospect(getHandler, []string{"profile", "cidaas:api_scope"}, nil)).Methods(http.MethodGet)
	log.Fatal(http.ListenAndServe(":8080", r))
}
Version 2.x.x
func get(w http.ResponseWriter, r *http.Request) {
    ...
	// set response to ok and return Status ok and response
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(respJSON))
	return
}

func main() {
	r := mux.NewRouter()
	api := r.PathPrefix("/api/v1").Subrouter()
	// Base URI is mandatory, ClientID is optional, if ClientID is set the interceptor will only allow requests from this Client
	cidaasInterceptor, err := cidaasinterceptor.New(cidaasinterceptor.Options{BaseURI: "https://base.cidaas.de", ClientID: "clientID"})
	if err != nil {
		log.Panicf("Initialization of cidaas interceptor failed! Error: %v", err)
		panic("Panic!")
	}
	getHandler := http.HandlerFunc(get)
	api.Handle("", cidaasInterceptor.VerifyTokenByIntrospect(getHandler, cidaasinterceptor.SecurityOptions{
		Scopes: []string{"your scope"},
		Roles: []string{"role:Admin"},
	})).Methods(http.MethodGet)
	log.Fatal(http.ListenAndServe(":8080", r))
}

Attached an example how to secure an API with groups based on an introspect call to the cidaas instance:

Note: Group validation only works with token introspection, not with signature verification. This is because group information is not available in JWT tokens and requires a call to the cidaas introspection endpoint.

Version 1.x.x

Not supported

Version 2.x.x
func get(w http.ResponseWriter, r *http.Request) {
    ...
	// set response to ok and return Status ok and response
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(respJSON))
	return
}

func main() {
	r := mux.NewRouter()
	api := r.PathPrefix("/api/v1").Subrouter()
	// Base URI is mandatory, ClientID is optional, if ClientID is set the interceptor will only allow requests from this Client
	cidaasInterceptor, err := cidaasinterceptor.New(cidaasinterceptor.Options{BaseURI: "https://base.cidaas.de", ClientID: "clientID"})
	if err != nil {
		log.Panicf("Initialization of cidaas interceptor failed! Error: %v", err)
		panic("Panic!")
	}
	getHandler := http.HandlerFunc(get)
	api.Handle("", cidaasInterceptor.VerifyTokenByIntrospect(getHandler, cidaasinterceptor.SecurityOptions{
		Groups: []cidaasinterceptor.GroupValidationOptions{
			{GroupID: "yourGroupID", GroupType: "department"},
		},
	})).Methods(http.MethodGet)
	api.Handle("/user", cidaasInterceptor.VerifyTokenByIntrospect(getHandler, cidaasinterceptor.SecurityOptions{
		AllowAnonymousSub: true, // add this flag if you want to allow tokens with an anonymous sub
		Groups: []cidaasinterceptor.GroupValidationOptions{{GroupID: "yourGroupID"}},
	})).Methods(http.MethodGet)
	log.Fatal(http.ListenAndServe(":8080", r))
}

Fiber

The following examples will show how to use the interceptor if you are using the fiber web framework for your APIs.

How to install
go get -u github.com/gofiber/fiber/v2

Attached an example how to secure an API with scopes and roles based on the signature token validation and also with the introspect call:

Version 1.x.x
func CreateApp() (*fiber.App, error) {
	interceptor, err := cidaasinterceptor.NewFiberInterceptor(cidaasinterceptor.Options{
		BaseURI:  BaseUrl,
		ClientID: Client_id,
	})
	if err != nil {
		ls.Fatal().Err(err).Msg("can't initialize interceptor")
	}
	app := fiber.New()
	root := app.Group(fmt.Sprintf("/%s", base.ServiceName))
	root.Post("/user", interceptor.VerifyTokenBySignature([]string{"profile", "cidaas:api_scope"}, []string{"role:Admin"}), handler.UserHandler)
	root.Post("/user", interceptor.VerifyTokenByIntrospect([]string{"profile", "cidaas:api_scope"}, []string{"role:Admin"}), handler.UserHandler)
	return app, nil
}

func main()  {
    app, err := CreateApp()
	if err != nil {
		panic(err)
    }
	app.Listen(":3000")
}
Version 2.x.x
func CreateApp() (*fiber.App, error) {
	interceptor, err := cidaasinterceptor.NewFiberInterceptor(cidaasinterceptor.Options{
		BaseURI:  BaseUrl,
		ClientID: Client_id,
	})
	if err != nil {
		ls.Fatal().Err(err).Msg("can't initialize interceptor")
	}
	app := fiber.New()
	root := app.Group(fmt.Sprintf("/%s", base.ServiceName))
	root.Post("/user", interceptor.VerifyTokenBySignature(cidaasinterceptor.SecurityOptions{
		Scopes: []string{"your scope"},
		Roles: []string{"role:Admin"},
	}), handler.UserHandler)
	root.Post("/groups", interceptor.VerifyTokenBySignature(cidaasinterceptor.SecurityOptions{
		AllowAnonymousSub: true, // add this flag if you want to allow tokens with an anonymous sub
		Scopes: []string{"your scope"},
		Roles: []string{"role:Admin"},
	}), handler.UserHandler)
	root.Post("/user", interceptor.VerifyTokenByIntrospect(cidaasinterceptor.SecurityOptions{
		Scopes: []string{"your scope"},
		Roles: []string{"role:Admin"},
	}), handler.UserHandler)
	return app, nil
}

func main()  {
    app, err := CreateApp()
	if err != nil {
		panic(err)
    }
	app.Listen(":3000")
}

Attached an example how to secure an API with groups with the introspect call:

Version 1.x.x

Not supported

Version 2.x.x
func CreateApp() (*fiber.App, error) {
	interceptor, err := cidaasinterceptor.NewFiberInterceptor(cidaasinterceptor.Options{
		BaseURI:  BaseUrl,
		ClientID: Client_id,
	})
	if err != nil {
		ls.Fatal().Err(err).Msg("can't initialize interceptor")
	}
	app := fiber.New()
	root := app.Group(fmt.Sprintf("/%s", base.ServiceName))
	root.Post("/user", interceptor.VerifyTokenByIntrospect(cidaasinterceptor.SecurityOptions{
		Groups: []cidaasinterceptor.GroupValidationOptions{{GroupID: "yourGroupID"}},
	}), handler.UserHandler)
	return app, nil
}

func main()  {
    app, err := CreateApp()
	if err != nil {
		panic(err)
    }
	app.Listen(":3000")
}

Attached an example how to secure an API with PAT (Personal Access Token) tokens:

Note: PAT tokens can only be validated via token introspection, not with signature verification. PAT tokens must have TokenTypeHint set to "pat". The PAT interceptor uses fiber.Handler directly, similar to FiberInterceptor.

Version 2.x.x
func CreateApp() (*fiber.App, error) {
	patInterceptor, err := cidaasinterceptor.NewPatInterceptor(cidaasinterceptor.Options{
		BaseURI:  BaseUrl,
		ClientID: Client_id,
	})
	if err != nil {
		ls.Fatal().Err(err).Msg("can't initialize interceptor")
	}

	app := fiber.New()
	root := app.Group(fmt.Sprintf("/%s", base.ServiceName))
	root.Post("/user", patInterceptor.VerifyTokenByIntrospect(cidaasinterceptor.SecurityOptions{
		Groups: []cidaasinterceptor.GroupValidationOptions{{GroupID: "yourGroupID"}},
	}), handler.UserHandler)
	return app, nil
}

func main() {
	app, err := CreateApp()
	if err != nil {
		panic(err)
	}
	app.Listen(":3000")
}

Documentation

Index

Constants

View Source
const FiberTokenDataKey = "tokendata"

FiberTokenDataKey key to access the token data ofthe request context

View Source
const GrpcTokenDataKey = "grpc_tokendata"

GrpcTokenDataKey key to access the token data in gRPC context

Variables

This section is empty.

Functions

func GetAudFromGrpcContext added in v2.1.0

func GetAudFromGrpcContext(ctx context.Context) (string, bool)

GetAudFromGrpcContext retrieves the audience (aud) from gRPC context

func GetSubFromGrpcContext added in v2.1.0

func GetSubFromGrpcContext(ctx context.Context) (string, bool)

GetSubFromGrpcContext retrieves the subject (sub) from gRPC context

Types

type CidaasInterceptor

type CidaasInterceptor struct {
	Options Options
	// contains filtered or unexported fields
}

CidaasInterceptor to secure APIs based on OAuth 2.0 for the net/http based api requests

func New

func New(opts Options) (*CidaasInterceptor, error)

New returns a newly constructed cidaasInterceptor instance with the provided options

func (*CidaasInterceptor) VerifyTokenByIntrospect

func (m *CidaasInterceptor) VerifyTokenByIntrospect(next http.Handler, apiOptions SecurityOptions) http.Handler

VerifyTokenByIntrospect (check for exp time, issuer and scopes, roles and groups)

func (*CidaasInterceptor) VerifyTokenBySignature

func (m *CidaasInterceptor) VerifyTokenBySignature(next http.Handler, apiOptions SecurityOptions) http.Handler

VerifyTokenBySignature (check for exp time and scopes and roles, no groups)

type ContextKey

type ContextKey int

ContextKey used to add request context

const TokenDataKey ContextKey = 3941119

TokenDataKey used to add the token data to the request context

type FiberInterceptor

type FiberInterceptor struct {
	Options Options
	// contains filtered or unexported fields
}

FiberInterceptor to secure APIs based on OAuth 2.0 with fiber

func NewFiberInterceptor

func NewFiberInterceptor(opts Options) (*FiberInterceptor, error)

NewFiberInterceptor returns a newly constructed cidaasInterceptor instance with the provided options

func (*FiberInterceptor) VerifyTokenByIntrospect

func (m *FiberInterceptor) VerifyTokenByIntrospect(apiOptions SecurityOptions) fiber.Handler

VerifyTokenByIntrospect (check for exp time, issuer and scopes and roles)

func (*FiberInterceptor) VerifyTokenBySignature

func (m *FiberInterceptor) VerifyTokenBySignature(apiOptions SecurityOptions) fiber.Handler

VerifyTokenBySignature (check for exp time and scopes and roles)

type GroupDetails

type GroupDetails struct {
	GroupID   string   `json:"groupId,omitempty"`   // group id
	GroupType string   `json:"groupType,omitempty"` // group type
	Roles     []string `json:"roles,omitempty"`     // roles of user in this group
}

GroupDetails represents the group details returned in token

type GroupValidationOptions

type GroupValidationOptions struct {
	GroupID              string   `json:"groupId,omitempty"`              // the group id to match
	GroupType            string   `json:"groupType,omitempty"`            // the group type to match
	Roles                []string `json:"roles,omitempty"`                // the roles to match
	StrictRoleValidation bool     `json:"strictRoleValidation,omitempty"` // true indicates that all roles must match
	StrictValidation     bool     `json:"strictValidation,omitempty"`     // true indicates that the group id, group type and all roles must match
}

GroupValidationOptions provides options to allow API access only to certain groups

type GrpcInterceptor added in v2.1.0

type GrpcInterceptor struct {
	Options Options
	// contains filtered or unexported fields
}

GrpcInterceptor to secure gRPC APIs based on OAuth 2.0

func NewGrpcInterceptor added in v2.1.0

func NewGrpcInterceptor(opts Options) (*GrpcInterceptor, error)

NewGrpcInterceptor returns a newly constructed gRPC interceptor instance with the provided options

func (*GrpcInterceptor) VerifyTokenByIntrospect added in v2.1.0

func (m *GrpcInterceptor) VerifyTokenByIntrospect(apiOptions SecurityOptions) grpc.UnaryServerInterceptor

VerifyTokenByIntrospect returns a gRPC unary interceptor that validates tokens by introspection

func (*GrpcInterceptor) VerifyTokenByIntrospectWithEndpointValidation added in v2.1.1

func (m *GrpcInterceptor) VerifyTokenByIntrospectWithEndpointValidation(endpointSecurity func(string) SecurityOptions) grpc.UnaryServerInterceptor

VerifyTokenByIntrospectWithEndpointValidation returns a gRPC unary interceptor that validates tokens by introspection with per-endpoint security options

func (*GrpcInterceptor) VerifyTokenBySignature added in v2.1.0

func (m *GrpcInterceptor) VerifyTokenBySignature(apiOptions SecurityOptions) grpc.UnaryServerInterceptor

VerifyTokenBySignature returns a gRPC unary interceptor that validates tokens by signature

func (*GrpcInterceptor) VerifyTokenBySignatureWithEndpointValidation added in v2.1.1

func (m *GrpcInterceptor) VerifyTokenBySignatureWithEndpointValidation(endpointSecurity func(string) SecurityOptions) grpc.UnaryServerInterceptor

VerifyTokenBySignatureWithEndpointValidation returns a gRPC unary interceptor that validates tokens by signature with per-endpoint security options

type JSONWebKey

type JSONWebKey struct {
	Kty string `json:"kty"`
	Kid string `json:"kid"`
	Use string `json:"use"`
	N   string `json:"n"`
	E   string `json:"e"`
	Alg string `json:"alg"`
}

JSONWebKey struct containing data of a key to verify a signature of token

type Jwks

type Jwks struct {
	Keys []JSONWebKey `json:"keys"`
}

Jwks struct containing a list of keys to verify a signature of token

type Options

type Options struct {
	BaseURI  string
	ClientID string
	Debug    bool
}

Options passed to the Interceptor (Base URI, ClientID)

type PatInterceptor added in v2.2.0

type PatInterceptor struct {
	Options Options
	// contains filtered or unexported fields
}

PatInterceptor to secure APIs based on OAuth 2.0 with PAT (Personal Access Token) support PAT tokens can only be validated via introspection API

func NewPatInterceptor added in v2.2.0

func NewPatInterceptor(opts Options) (*PatInterceptor, error)

NewPatInterceptor returns a newly constructed PAT interceptor instance with the provided options

func (*PatInterceptor) VerifyTokenByIntrospect added in v2.2.0

func (m *PatInterceptor) VerifyTokenByIntrospect(apiOptions SecurityOptions) fiber.Handler

VerifyTokenByIntrospect (check for exp time, issuer and scopes, roles and groups) using the accesspass-srv/passes/pat/introspect endpoint

type SecurityOptions

type SecurityOptions struct {
	Roles                 []string                 // roles which are allowed to access this api
	Scopes                []string                 // scopes which are allowed to acces this api
	Groups                []GroupValidationOptions // groups which are allowed to acces this api (only possible with introspect)
	AllowAnonymousSub     bool                     // false (by default) indicates that tokens which have an anonymous sub are rejected, true indicates that tokens which have an ANONYMOUS sub are allowed (only possible with the signature check for now)
	StrictRoleValidation  bool                     // by default false, true indicates that all provided roles must match (only possible with introspect)
	StrictScopeValidation bool                     // by default false, true indicates that all provided scopes must match (also possible with the signature check)
	StrictGroupValidation bool                     // by default false, true indicates that all provided groups must match (only possible with introspect)
	StrictValidation      bool                     // by default false, true indicates that all provided roles, scopes and groups must match (the signature check just checks for the scopes)
}

SecurityOptions which should be passsed to restrict the api access

type TokenData

type TokenData struct {
	Sub string
	Aud string
}

TokenData which can be accessed via the request context and provides the resolved information about the aud and the sub of the token

func GetTokenDataFromGrpcContext added in v2.1.0

func GetTokenDataFromGrpcContext(ctx context.Context) (*TokenData, bool)

GetTokenDataFromGrpcContext retrieves token data from gRPC context

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL