README
¶
httpauthenticator
This package provides a wrapper around the http request and authenticates the sender of the request.
Server Usage
NewAuthenticator provides a handler that verifies provided credentials supporting multiple protocols.
-
Client Certificate authentication
The client includes a client certificate in its TLS connection that includes its clientID in the CN and role in the OU field. The certificate is signed by the Hub CA.
-
BASIC authentication. See also: https://www.alexedwards.net/blog/basic-authentication-in-go
Parse the Authorization header, where base64 is a function that encodes the "username:password" string in base64 format.
Authorization: Basic base64("username:password")
-
- Client performs GET request
- Server responds with 401, header: WWW-authenticate: Digest, and fields real, qop, algorithm, none and opaque.
- Client gets login credentials username and password from user
- Client repeats request including the header: "Authorization: Digest username="", realm=, nonce=, qop=, opaque=, algorithm=, response=, cnonce=, userhash=
-
JWT authentication
The client makes a login request providing its credentials and a requested Hash algorithm. The server returns a bearer token which is a hash of The default hash is MD5. A different algorithm can be configured. All future request include a Authentication header with bearer token:
Authorization: Bearer asldkasdwerpwoierwperowepr
pwStore := unpwstore.NewPasswordFileStore(path)
httpAuthenticator := authenticator.NewHttpAuthenticator(pwStore)
router.HandleFunc(path, httpauth.NewAuthHandler(httpAuthenticator.Authenticate))
For JWT authentication also add a login handler to obtain a token
router.HandleFunc("/login", httpauth.LoginHandler)
Client Usage
... todo .. describe authentication clients
Documentation
¶
Overview ¶
Package servetls with TLS server for use by plugins and testing
Index ¶
- Constants
- type BasicAuthenticator
- type CertAuthenticator
- type HttpAuthenticator
- func (hauth *HttpAuthenticator) AuthenticateRequest(resp http.ResponseWriter, req *http.Request) (userID string, match bool)
- func (hauth *HttpAuthenticator) EnableBasicAuth(validateCredentials func(loginName string, password string) bool)
- func (hauth *HttpAuthenticator) EnableJwtAuth(verificationKey *ecdsa.PublicKey)
- type JWTAuthenticator
- type JWTIssuer
- func (issuer *JWTIssuer) CreateJWTTokens(userID string) (accessToken string, refreshToken string, err error)
- func (issuer *JWTIssuer) DecodeToken(tokenString string) (jwtToken *jwt.Token, claims *JwtClaims, err error)
- func (issuer *JWTIssuer) HandleJWTLogin(resp http.ResponseWriter, req *http.Request)
- func (issuer *JWTIssuer) HandleJWTRefresh(resp http.ResponseWriter, req *http.Request)
- func (issuer *JWTIssuer) WriteJWTTokens(accessToken string, refreshToken string, cookieExpTime time.Time, ...) error
- type JwtClaims
- type TLSServer
- func (srv *TLSServer) AddHandler(path string, ...)
- func (srv *TLSServer) AddHandlerNoAuth(path string, handler func(resp http.ResponseWriter, req *http.Request))
- func (srv *TLSServer) EnableBasicAuth(validateCredentials func(loginName string, password string) bool)
- func (srv *TLSServer) EnableJwtAuth(verificationKey *ecdsa.PublicKey)
- func (srv *TLSServer) EnableJwtIssuer(issuerKey *ecdsa.PrivateKey, ...)
- func (srv *TLSServer) GetQueryInt(request *http.Request, paramName string, defaultValue int) (value int, err error)
- func (srv *TLSServer) GetQueryString(request *http.Request, paramName string, defaultValue string) string
- func (srv *TLSServer) Start() error
- func (srv *TLSServer) Stop()
- func (srv *TLSServer) WriteBadRequest(resp http.ResponseWriter, errMsg string)
- func (srv *TLSServer) WriteForbidden(resp http.ResponseWriter, errMsg string)
- func (srv *TLSServer) WriteInternalError(resp http.ResponseWriter, errMsg string)
- func (srv *TLSServer) WriteNotFound(resp http.ResponseWriter, errMsg string)
- func (srv *TLSServer) WriteNotImplemented(resp http.ResponseWriter, errMsg string)
- func (srv *TLSServer) WriteUnauthorized(resp http.ResponseWriter, errMsg string)
Constants ¶
const JwtRefreshCookieName = "authtoken"
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BasicAuthenticator ¶
type BasicAuthenticator struct {
// contains filtered or unexported fields
}
BasicAuthenticator decodes the authentication method used in the request and authenticates the user
func NewBasicAuthenticator ¶
func NewBasicAuthenticator(verifyUsernamePassword func(loginID, secret string) bool) *BasicAuthenticator
NewBasicAuthenticator creates a new HTTP Basic authenticator
verifyUsernamePassword is the handler that validates the loginID and secret
func (*BasicAuthenticator) AuthenticateRequest ¶
func (bauth *BasicAuthenticator) AuthenticateRequest(resp http.ResponseWriter, req *http.Request) (userID string, match bool)
AuthenticateRequest Checks in order: client certificate, JWT bearer, Basic Returns the authenticated userID or an error if authentication failed
type CertAuthenticator ¶
type CertAuthenticator struct { }
CertAuthenticator verifies the client certificate authentication is used This simply checks if a client certificate is active and assumes that having one is sufficient to pass auth
func NewCertAuthenticator ¶
func NewCertAuthenticator() *CertAuthenticator
NewCertAuthenticator creates a new HTTP authenticator Use .AuthenticateRequest() to authenticate the incoming request
func (*CertAuthenticator) AuthenticateRequest ¶
func (hauth *CertAuthenticator) AuthenticateRequest(resp http.ResponseWriter, req *http.Request) (userID string, ok bool)
AuthenticateRequest The real check happens by the TLS server that verifies it is signed by the CA. If the certificate is a plugin, then no userID is returned Returns the userID of the certificate (CN) or an error if no client certificate is used
type HttpAuthenticator ¶
type HttpAuthenticator struct { BasicAuth *BasicAuthenticator CertAuth *CertAuthenticator JwtAuth *JWTAuthenticator }
HttpAuthenticator chains the selected authenticators
func NewHttpAuthenticator ¶
func NewHttpAuthenticator() *HttpAuthenticator
NewHttpAuthenticator creates a container to apply HTTP request authenticators By default the certificate authenticator is enabled. Additional authenticators can be enabled using the Enable... functions
Use .AuthenticateRequest() to authenticate the incoming request
func (*HttpAuthenticator) AuthenticateRequest ¶
func (hauth *HttpAuthenticator) AuthenticateRequest(resp http.ResponseWriter, req *http.Request) (userID string, match bool)
AuthenticateRequest Checks in order: client certificate, JWT bearer, Basic Returns the authenticated userID or an error if authentication failed
func (*HttpAuthenticator) EnableBasicAuth ¶
func (hauth *HttpAuthenticator) EnableBasicAuth(validateCredentials func(loginName string, password string) bool)
EnableBasicAuth enables BASIC authentication Basic auth is a legacy authentication scheme and not recommended as it requires each service to have access to the credentials store. Use of JwtAuth is preferred.
validateCredentials is the function that verifies the given credentials
func (*HttpAuthenticator) EnableJwtAuth ¶
func (hauth *HttpAuthenticator) EnableJwtAuth(verificationKey *ecdsa.PublicKey)
EnableJwtAuth enables JWT authentication using asymmetric keys JWT tokens are included in the request header authorization field and signed by an issuing authentication server using the server's private key. The provided verification key is the server's public key needed to verify that signature.
type JWTAuthenticator ¶
type JWTAuthenticator struct {
// contains filtered or unexported fields
}
JWTAuthenticator verifies issued JWT tokens using the provided public certificate The application must use .AuthenticateRequest() to authenticate the incoming request using the access token.
func NewJWTAuthenticator ¶
func NewJWTAuthenticator(publicKey *ecdsa.PublicKey) *JWTAuthenticator
NewJWTAuthenticator creates a new JWT authenticator publicKey is the public key for verifying the private key signature
func (*JWTAuthenticator) AuthenticateRequest ¶
func (jauth *JWTAuthenticator) AuthenticateRequest(resp http.ResponseWriter, req *http.Request) (userID string, match bool)
AuthenticateRequest validates the access token The access token is provided in the request header using the Bearer schema:
Authorization: Bearer <token>
Returns the authenticated user and true if there is a match, of false if authentication failed
func (*JWTAuthenticator) DecodeToken ¶
func (jauth *JWTAuthenticator) DecodeToken(tokenString string) ( jwtToken *jwt.Token, claims *JwtClaims, err error)
DecodeToken and return its claims
If the token is invalid then claims will be empty and an error is returned If the token is valid but has an incorrect signature, the token and claims will be returned with an error
type JWTIssuer ¶
type JWTIssuer struct { // These can be modified at will AccessTokenValidity time.Duration RefreshTokenValidity time.Duration // contains filtered or unexported fields }
JWTIssuer issues JWT tokens
func NewJWTIssuer ¶
func NewJWTIssuer( issuerName string, signingKey *ecdsa.PrivateKey, verifyUsernamePassword func(loginID, secret string) bool, ) *JWTIssuer
NewJWTIssuer create a new issuer of JWT authentication tokens using asymmetric keys.
issuerName of the service issuing the token signingKey for generating tokens, or nil to generate a random 64 byte secret verifyUsernamePassword is the handler that validates the login credentials
func (*JWTIssuer) CreateJWTTokens ¶
func (issuer *JWTIssuer) CreateJWTTokens(userID string) (accessToken string, refreshToken string, err error)
CreateJWTTokens creates a new access and refresh token pair containing the userID. The result is written to the response and a refresh token is set securely in a client cookie.
userID is the login ID of the user to whom the token is assigned and will be included in the claims
func (*JWTIssuer) DecodeToken ¶
func (issuer *JWTIssuer) DecodeToken(tokenString string) ( jwtToken *jwt.Token, claims *JwtClaims, err error)
DecodeToken and return its claims Set error if token not valid
func (*JWTIssuer) HandleJWTLogin ¶
func (issuer *JWTIssuer) HandleJWTLogin(resp http.ResponseWriter, req *http.Request)
HandleJWTLogin handles a JWT login POST request. Attach this method to the router with the login route. For example:
> router.HandleFunc("/login", HandleJWTLogin)
The body contains provided userID and password This:
- returns a JWT access and refresh token pair
- sets a secure, httpOnly, sameSite refresh cookie with the name 'JwtRefreshCookieName'
func (*JWTIssuer) HandleJWTRefresh ¶
func (issuer *JWTIssuer) HandleJWTRefresh(resp http.ResponseWriter, req *http.Request)
HandleJWTRefresh refreshes the access/refresh token pair Attach this method to the router with the refresh route. For example:
> router.HandleFunc("/refresh", HandleJWTRefresh)
A valid refresh token must be provided in the client cookie or set in the authorization header ¶
This:
- Return unauthorized if no valid refresh token was found
- returns a JWT access and refresh token pair if the refresh token was valid
- sets a secure, httpOnly, sameSite refresh cookie with the name 'JwtRefreshCookieName'
func (*JWTIssuer) WriteJWTTokens ¶
func (issuer *JWTIssuer) WriteJWTTokens( accessToken string, refreshToken string, cookieExpTime time.Time, resp http.ResponseWriter) error
WriteJWTTokens writes the access and refresh tokens as response message and in a secure client cookie. The cookieExpTime should be set to the refresh token expiration time.
type JwtClaims ¶
type JwtClaims struct { Username string `json:"username"` jwt.StandardClaims }
JwtClaims this is temporary while figuring things out
type TLSServer ¶
type TLSServer struct {
// contains filtered or unexported fields
}
TLSServer is a simple TLS Server supporting BASIC, Jwt and client certificate authentication
func NewTLSServer ¶
func NewTLSServer(address string, port uint, serverCert *tls.Certificate, caCert *x509.Certificate, ) *TLSServer
NewTLSServer creates a new TLS Server instance with authentication support. Use AddHandler to handle incoming requests for the given route and indicate if authentication is required.
The following authentication methods are supported:
Certificate based auth using the caCert to verify client certificates Basic authentication if 'EnableBasicAuth' is used. JWT asymmetric token authentication if EnableJwtAuth is used. address server listening address port listening port serverCert Server TLS certificate caCert CA certificate to verify client certificates
returns TLS server for handling requests
func (*TLSServer) AddHandler ¶
func (srv *TLSServer) AddHandler(path string, handler func(userID string, resp http.ResponseWriter, req *http.Request))
AddHandler adds a new handler for a path.
The server authenticates the request before passing it to this handler. The handler's userID is that of the authenticated user, and is intended for authorization of the request. If authentication is not enabled then the userID is empty.
path to listen on. This supports wildcards handler to invoke with the request. The userID is only provided when an authenticator is used
func (*TLSServer) AddHandlerNoAuth ¶
func (srv *TLSServer) AddHandlerNoAuth(path string, handler func(resp http.ResponseWriter, req *http.Request))
AddHandlerNoAuth adds a new handler for a path that does not require authentication The server passes the request directly to the handler
path to listen on. This supports wildcards handler to invoke with the request. The userID is only provided when an authenticator is used
func (*TLSServer) EnableBasicAuth ¶
func (srv *TLSServer) EnableBasicAuth(validateCredentials func(loginName string, password string) bool)
EnableBasicAuth enables BASIC authentication on this server Basic auth is a legacy authentication scheme and not recommended as it requires each service to have access to the credentials store. Use of JwtAuth is preferred.
validateCredentials is the function that verifies the given credentials
func (*TLSServer) EnableJwtAuth ¶
EnableJwtAuth enables JWT authentication using asymmetric keys JWT tokens are included in the head authorization field and signed by an issuing authentication server using the server's private key. The provided verification key is the server's public key.
verificationKey is the public key to verify tokens. Use nil to use the server own public key
func (*TLSServer) EnableJwtIssuer ¶
func (srv *TLSServer) EnableJwtIssuer(issuerKey *ecdsa.PrivateKey, validateCredentials func(loginName string, password string) bool)
EnableJwtIssuer enables JWT token issuer using asymmetric keys Token are issued using the PUT /login request with payload carrying {username: , password:} Tokens are refreshed using the PUT /refresh request
The login/refresh paths are defined in tlsclient.DefaultJWTLoginPath, tlsclient.DefaultJWTRefreshPath
issuerKey is the private key used to sign the tokens. Use nil to use the server's private key validateCredentials is the handler that matches credentials with those in the credentials store
func (*TLSServer) GetQueryInt ¶
func (srv *TLSServer) GetQueryInt( request *http.Request, paramName string, defaultValue int) (value int, err error)
GetQueryInt reads the request query parameter and convert it to an integer
request is the request with the query parameter paramName is the name of the parameter defaultValue to use if parameter not provided
Returns an integer value, error if conversion failed (bad request)
func (*TLSServer) GetQueryString ¶
func (srv *TLSServer) GetQueryString( request *http.Request, paramName string, defaultValue string) string
GetQueryString reads the request query parameter and returns the first string
request is the request with the query parameter paramName is the name of the parameter defaultValue to use if parameter not provided
Returns a single string, with defaultValue if not found
func (*TLSServer) Start ¶
Start the TLS server using the provided CA and Server certificates. The server will request but not require a client certificate. If one is provided it must be valid.
func (*TLSServer) WriteBadRequest ¶
func (srv *TLSServer) WriteBadRequest(resp http.ResponseWriter, errMsg string)
WriteBadRequest logs and respond with bad request error status code and log error
func (*TLSServer) WriteForbidden ¶
func (srv *TLSServer) WriteForbidden(resp http.ResponseWriter, errMsg string)
WriteForbidden logs and respond with forbidden (403) code and log http error Use this when access a resource without sufficient credentials
func (*TLSServer) WriteInternalError ¶
func (srv *TLSServer) WriteInternalError(resp http.ResponseWriter, errMsg string)
WriteInternalError logs and responds with internal server error status code and log error
func (*TLSServer) WriteNotFound ¶
func (srv *TLSServer) WriteNotFound(resp http.ResponseWriter, errMsg string)
WriteNotFound logs and respond with 404 resource not found
func (*TLSServer) WriteNotImplemented ¶
func (srv *TLSServer) WriteNotImplemented(resp http.ResponseWriter, errMsg string)
WriteNotImplemented respond with 501 not implemented
func (*TLSServer) WriteUnauthorized ¶
func (srv *TLSServer) WriteUnauthorized(resp http.ResponseWriter, errMsg string)
WriteUnauthorized responds with unauthorized (401) status code and log http error Use this when login fails