make auth an interface
This commit is contained in:
parent
fac9e3fab2
commit
91099eb13e
5 changed files with 42 additions and 21 deletions
|
@ -10,9 +10,13 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CheckAPIKey validates the provided key and returns the API key record.
|
type apiKeyAuth interface {
|
||||||
// An error is returned if validation fails for any reason.
|
// CheckAPIKey validates the provided key and returns the API key record.
|
||||||
func (a *Authenticator) CheckAPIKey(ctx context.Context, key string) (*database.ApiKey, error) {
|
// An error is returned if validation fails for any reason.
|
||||||
|
CheckAPIKey(ctx context.Context, key string) (*database.ApiKey, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *authenticator) CheckAPIKey(ctx context.Context, key string) (*database.ApiKey, error) {
|
||||||
keyUuid, err := uuid.Parse(key)
|
keyUuid, err := uuid.Parse(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Str("apikey", key).Msg("cannot parse key")
|
log.Error().Str("apikey", key).Msg("cannot parse key")
|
||||||
|
|
|
@ -8,14 +8,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Authenticator performs API key and user JWT authentication.
|
// Authenticator performs API key and user JWT authentication.
|
||||||
type Authenticator struct {
|
type Authenticator interface {
|
||||||
|
jwtAuth
|
||||||
|
apiKeyAuth
|
||||||
|
}
|
||||||
|
|
||||||
|
type authenticator struct {
|
||||||
domain string
|
domain string
|
||||||
jwt *jwtauth.JWTAuth
|
jwt *jwtauth.JWTAuth
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAuthenticator creates a new Authenticator with the provided JWT secret and cookie domain.
|
// NewAuthenticator creates a new Authenticator with the provided JWT secret and cookie domain.
|
||||||
func NewAuthenticator(jwtSecret string, domain string) *Authenticator {
|
func NewAuthenticator(jwtSecret string, domain string) Authenticator {
|
||||||
return &Authenticator{
|
return &authenticator{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
jwt: jwtauth.New("HS256", []byte(jwtSecret), nil),
|
jwt: jwtauth.New("HS256", []byte(jwtSecret), nil),
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,27 +15,40 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type jwtAuth interface {
|
||||||
|
// Authenticated returns whether the request is authenticated. It also returns the claims.
|
||||||
|
Authenticated(r *http.Request) (claims, bool)
|
||||||
|
|
||||||
|
// Login attempts to return a JWT for the provided user and password.
|
||||||
|
Login(ctx context.Context, username, password string) (token string, err error)
|
||||||
|
|
||||||
|
// InstallVerifyMiddleware installs the JWT verifier middleware to the provided chi Router.
|
||||||
|
InstallVerifyMiddleware(r chi.Router)
|
||||||
|
|
||||||
|
// InstallAuthMiddleware installs the JWT authenticator middleware to the provided chi Router.
|
||||||
|
InstallAuthMiddleware(r chi.Router)
|
||||||
|
|
||||||
|
// InstallRoutes installs the auth route to the provided chi Router.
|
||||||
|
InstallRoutes(r chi.Router)
|
||||||
|
}
|
||||||
|
|
||||||
type claims map[string]interface{}
|
type claims map[string]interface{}
|
||||||
|
|
||||||
// Authenticated returns whether the request is authenticated. It also returns the claims.
|
func (a *authenticator) Authenticated(r *http.Request) (claims, bool) {
|
||||||
func (a *Authenticator) Authenticated(r *http.Request) (claims, bool) {
|
|
||||||
// TODO: check IP against ACL, or conf.Public, and against map of routes
|
// TODO: check IP against ACL, or conf.Public, and against map of routes
|
||||||
tok, cl, err := jwtauth.FromContext(r.Context())
|
tok, cl, err := jwtauth.FromContext(r.Context())
|
||||||
return cl, err != nil && tok != nil
|
return cl, err != nil && tok != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallVerifyMiddleware installs the JWT verifier middleware to the provided chi Router.
|
func (a *authenticator) InstallVerifyMiddleware(r chi.Router) {
|
||||||
func (a *Authenticator) InstallVerifyMiddleware(r chi.Router) {
|
|
||||||
r.Use(jwtauth.Verifier(a.jwt))
|
r.Use(jwtauth.Verifier(a.jwt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallVerifyMiddleware installs the JWT authenticator middleware to the provided chi Router.
|
func (a *authenticator) InstallAuthMiddleware(r chi.Router) {
|
||||||
func (a *Authenticator) InstallAuthMiddleware(r chi.Router) {
|
|
||||||
r.Use(jwtauth.Authenticator(a.jwt))
|
r.Use(jwtauth.Authenticator(a.jwt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login attempts to return a JWT for the provided user and password.
|
func (a *authenticator) Login(ctx context.Context, username, password string) (token string, err error) {
|
||||||
func (a *Authenticator) Login(ctx context.Context, username, password string) (token string, err error) {
|
|
||||||
q := database.New(database.FromCtx(ctx))
|
q := database.New(database.FromCtx(ctx))
|
||||||
users, err := q.GetUsers(ctx)
|
users, err := q.GetUsers(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -64,7 +77,7 @@ func (a *Authenticator) Login(ctx context.Context, username, password string) (t
|
||||||
return a.newToken(found.ID), nil
|
return a.newToken(found.ID), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Authenticator) newToken(uid int32) string {
|
func (a *authenticator) newToken(uid int32) string {
|
||||||
claims := claims{
|
claims := claims{
|
||||||
"user_id": uid,
|
"user_id": uid,
|
||||||
}
|
}
|
||||||
|
@ -76,12 +89,11 @@ func (a *Authenticator) newToken(uid int32) string {
|
||||||
return tokenString
|
return tokenString
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallRoutes installs the auth route to the provided chi Router.
|
func (a *authenticator) InstallRoutes(r chi.Router) {
|
||||||
func (a *Authenticator) InstallRoutes(r chi.Router) {
|
|
||||||
r.Post("/auth", a.routeAuth)
|
r.Post("/auth", a.routeAuth)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Authenticator) routeAuth(w http.ResponseWriter, r *http.Request) {
|
func (a *authenticator) routeAuth(w http.ResponseWriter, r *http.Request) {
|
||||||
err := r.ParseForm()
|
err := r.ParseForm()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
|
|
@ -18,11 +18,11 @@ import (
|
||||||
|
|
||||||
// HTTPIngestor is an ingestor that accepts calls over HTTP.
|
// HTTPIngestor is an ingestor that accepts calls over HTTP.
|
||||||
type HTTPIngestor struct {
|
type HTTPIngestor struct {
|
||||||
auth *auth.Authenticator
|
auth auth.Authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHTTPIngestor creates a new HTTPIngestor. It requires an Authenticator.
|
// NewHTTPIngestor creates a new HTTPIngestor. It requires an Authenticator.
|
||||||
func NewHTTPIngestor(auth *auth.Authenticator) *HTTPIngestor {
|
func NewHTTPIngestor(auth auth.Authenticator) *HTTPIngestor {
|
||||||
return &HTTPIngestor{
|
return &HTTPIngestor{
|
||||||
auth: auth,
|
auth: auth,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
auth *auth.Authenticator
|
auth auth.Authenticator
|
||||||
conf *config.Config
|
conf *config.Config
|
||||||
db *database.DB
|
db *database.DB
|
||||||
r *chi.Mux
|
r *chi.Mux
|
||||||
|
|
Loading…
Reference in a new issue