mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
109 lines
3.3 KiB
Go
109 lines
3.3 KiB
Go
package basicauth
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/kataras/iris/v12/context"
|
|
)
|
|
|
|
type (
|
|
// ErrHTTPVersion is fired when Options.HTTPSOnly was enabled
|
|
// and the current request is a plain http one.
|
|
ErrHTTPVersion struct{}
|
|
|
|
// ErrCredentialsForbidden is fired when Options.MaxTries have been consumed
|
|
// by the user and the client is forbidden to retry at least for "Age" time.
|
|
ErrCredentialsForbidden struct {
|
|
Username string
|
|
Password string
|
|
Tries int
|
|
Age time.Duration
|
|
}
|
|
|
|
// ErrCredentialsMissing is fired when the authorization header is empty or malformed.
|
|
ErrCredentialsMissing struct {
|
|
Header string
|
|
|
|
AuthenticateHeader string
|
|
AuthenticateHeaderValue string
|
|
Code int
|
|
}
|
|
|
|
// ErrCredentialsInvalid is fired when the user input does not match with an existing user.
|
|
ErrCredentialsInvalid struct {
|
|
Username string
|
|
Password string
|
|
CurrentTries int
|
|
|
|
AuthenticateHeader string
|
|
AuthenticateHeaderValue string
|
|
Code int
|
|
}
|
|
|
|
// ErrCredentialsExpired is fired when the username:password combination is valid
|
|
// but the memory stored user has been expired.
|
|
ErrCredentialsExpired struct {
|
|
Username string
|
|
Password string
|
|
|
|
AuthenticateHeader string
|
|
AuthenticateHeaderValue string
|
|
Code int
|
|
}
|
|
)
|
|
|
|
func (e ErrHTTPVersion) Error() string {
|
|
return "http version not supported"
|
|
}
|
|
|
|
func (e ErrCredentialsForbidden) Error() string {
|
|
return fmt.Sprintf("credentials: forbidden <%s:%s> for <%s> after <%d> attempts", e.Username, e.Password, e.Age, e.Tries)
|
|
}
|
|
|
|
func (e ErrCredentialsMissing) Error() string {
|
|
if e.Header != "" {
|
|
return fmt.Sprintf("credentials: malformed <%s>", e.Header)
|
|
}
|
|
|
|
return "empty credentials"
|
|
}
|
|
|
|
func (e ErrCredentialsInvalid) Error() string {
|
|
return fmt.Sprintf("credentials: invalid <%s:%s> current tries <%d>", e.Username, e.Password, e.CurrentTries)
|
|
}
|
|
|
|
func (e ErrCredentialsExpired) Error() string {
|
|
return fmt.Sprintf("credentials: expired <%s:%s>", e.Username, e.Password)
|
|
}
|
|
|
|
// DefaultErrorHandler is the default error handler for the Options.ErrorHandler field.
|
|
func DefaultErrorHandler(ctx *context.Context, err error) {
|
|
switch e := err.(type) {
|
|
case ErrHTTPVersion:
|
|
ctx.StopWithStatus(http.StatusHTTPVersionNotSupported)
|
|
case ErrCredentialsForbidden:
|
|
// If a (proxy) server receives valid credentials that are inadequate to access a given resource,
|
|
// the server should respond with the 403 Forbidden status code.
|
|
// Unlike 401 Unauthorized or 407 Proxy Authentication Required, authentication is impossible for this user.
|
|
ctx.StopWithStatus(http.StatusForbidden)
|
|
case ErrCredentialsMissing:
|
|
unauthorize(ctx, e.AuthenticateHeader, e.AuthenticateHeaderValue, e.Code)
|
|
case ErrCredentialsInvalid:
|
|
unauthorize(ctx, e.AuthenticateHeader, e.AuthenticateHeaderValue, e.Code)
|
|
case ErrCredentialsExpired:
|
|
unauthorize(ctx, e.AuthenticateHeader, e.AuthenticateHeaderValue, e.Code)
|
|
default:
|
|
// This will never happen.
|
|
ctx.StopWithText(http.StatusInternalServerError, "unknown error: %v", err)
|
|
}
|
|
}
|
|
|
|
// unauthorize sends a 401 status code (or 407 if Proxy was set to true)
|
|
// which client should catch and prompt for username:password credentials.
|
|
func unauthorize(ctx *context.Context, authHeader, authHeaderValue string, code int) {
|
|
ctx.Header(authHeader, authHeaderValue)
|
|
ctx.StopWithStatus(code)
|
|
}
|