diff options
author | tjpcc <tjp@ctrl-c.club> | 2023-01-20 10:58:35 -0700 |
---|---|---|
committer | tjpcc <tjp@ctrl-c.club> | 2023-01-20 10:58:35 -0700 |
commit | 8229f31f70ecdbe03d03c96cba17d6ee85397bca (patch) | |
tree | 5c51a1bdd9366a69fd1cf03dcdd1c41e49bcb6e2 /contrib/tlsauth/gemini.go | |
parent | a1c186878d228bada894a6fd580bfc4eb9da2ffa (diff) |
"tlsauth" contrib package
This package adds authentication middlewares via TLS client
certificates.
Diffstat (limited to 'contrib/tlsauth/gemini.go')
-rw-r--r-- | contrib/tlsauth/gemini.go | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/contrib/tlsauth/gemini.go b/contrib/tlsauth/gemini.go new file mode 100644 index 0000000..0db89de --- /dev/null +++ b/contrib/tlsauth/gemini.go @@ -0,0 +1,58 @@ +package tlsauth + +import ( + "context" + + "tildegit.org/tjp/gus" + "tildegit.org/tjp/gus/gemini" +) + +// GeminiAuth builds an authentication middleware from approval criteria. +// +// If a request does not contain a client certificate it will be rejected +// with a "60 certificate required" response. If the client identity does +// not pass the approver it will be rejected with "62 certificate invalid". +func GeminiAuth(approver Approver) gus.Middleware { + return func(inner gus.Handler) gus.Handler { + return func(ctx context.Context, request *gus.Request) *gus.Response { + identity := Identity(request) + if identity == nil { + return geminiMissingCert(ctx, request) + } + if !approver(identity) { + return geminiCertNotAuthorized(ctx, request) + } + + return inner(ctx, request) + } + } +} + +// GeminiOptionalAuth builds auth middleware which doesn't require an identity. +// +// If there is no client certificate the request will pass through the middleware. +// It will only be rejected with "62 certificate invalid" if there *is* a client +// certificate, but it fails the approval. +func GeminiOptionalAuth(approver Approver) gus.Middleware { + return func(inner gus.Handler) gus.Handler { + return func(ctx context.Context, request *gus.Request) *gus.Response { + identity := Identity(request) + if identity != nil && !approver(identity) { + return geminiCertNotAuthorized(ctx, request) + } + + return inner(ctx, request) + } + } +} + +// GeminiRequireCertificate is a middleware that only requires a client certificate. +var GeminiRequireCertificate = GeminiAuth(Allow) + +func geminiMissingCert(_ context.Context, _ *gus.Request) *gus.Response { + return gemini.RequireCert("A client certificate is required.") +} + +func geminiCertNotAuthorized(_ context.Context, _ *gus.Request) *gus.Response { + return gemini.CertAuthFailure("Client certificate not authorized.") +} |