Documentation ¶
Overview ¶
Example ¶
Example is a package-level documentation example.
package main import ( "fmt" "net/http" "net/http/httptest" "github.com/danikarik/guard" ) func main() { var ( secret = []byte("9ae55e7ad6c6d3a78312567840588eff0ece5a9be9e2d6e36a6e5b5547361ecb") userID = "user_id" accessCookieName = "access_token" csrfCookieName = "csrf_token" csrfHeaderName = "X-CSRF-TOKEN" ) // Create a new guard instance with unsecured cookie for testing purpose. grd, _ := guard.NewGuard(secret, guard.WithAccessCookieName(accessCookieName), guard.WithCSRFCookieName(csrfCookieName), guard.WithCSRFHeaderName(csrfHeaderName), guard.WithSecure(false), ) // mainHandler responds 200 var mainHandler = func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } // loginHandler sets auth cookie. var loginHandler = func(w http.ResponseWriter, r *http.Request) { if err := grd.Authenticate(w, userID); err != nil { http.Error(w, "cannot set cookie", http.StatusBadRequest) return } } // protected responds 200 if cookie is set var protectedHandler = func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } // auth middleware checks cookie with guard instance. var authRequired = func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/protected" { next.ServeHTTP(w, r) return } sub, err := grd.Validate(r) if err != nil { switch err { case guard.ErrInvalidAccessToken: http.Error(w, "invalid access token", http.StatusUnauthorized) return case guard.ErrInvalidCSRFToken: http.Error(w, "invalid csrf token", http.StatusBadRequest) return default: http.Error(w, err.Error(), http.StatusInternalServerError) return } } // Lookup subject if sub != userID { http.Error(w, "invalid user id", http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) } // Create a new router. mux := http.NewServeMux() mux.HandleFunc("/", mainHandler) mux.HandleFunc("/login", loginHandler) mux.HandleFunc("/protected", protectedHandler) // Insert our middleware before the router handlerChain := authRequired(mux) // Request public endpoint req, _ := http.NewRequest("GET", "/", nil) rr := httptest.NewRecorder() handlerChain.ServeHTTP(rr, req) fmt.Println(rr.Code) // Request protected endpoint without cookie req, _ = http.NewRequest("GET", "/protected", nil) rr = httptest.NewRecorder() handlerChain.ServeHTTP(rr, req) fmt.Println(rr.Code) // Request login endpoint req, _ = http.NewRequest("GET", "/login", nil) rr = httptest.NewRecorder() handlerChain.ServeHTTP(rr, req) // Set access and csrf cookie and repeat request req, _ = http.NewRequest("GET", "/protected", nil) for _, cookie := range rr.Result().Cookies() { if cookie.Name == csrfCookieName { // Set csrf cookie value into header req.Header.Set(csrfHeaderName, cookie.Value) } else { // Save access token cookie req.AddCookie(cookie) } } rr = httptest.NewRecorder() handlerChain.ServeHTTP(rr, req) fmt.Println(rr.Code) }
Output: 200 401 200
Index ¶
- Variables
- type Guard
- type Option
- func WithAccessCookieName(name string) Option
- func WithCSRFCookieName(name string) Option
- func WithCSRFHeaderName(name string) Option
- func WithDomain(name string) Option
- func WithIssuer(name string) Option
- func WithPath(path string) Option
- func WithSecure(flag bool) Option
- func WithTTL(ttl time.Duration) Option
- type UserClaims
Examples ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ( // ErrNilStandardClaims returned by UserClaims.Valid if there is no standard claims found. ErrNilStandardClaims = errors.New("guard: standard claims cannot be nil") // ErrEmptyCSRFToken returned by UserClaims.Valid if csrf token is empty. ErrEmptyCSRFToken = errors.New("guard: empty CSRF token") )
View Source
var ( // ErrEmptySecret when NewGuard takes empty secret. ErrEmptySecret = errors.New("guard: empty signing secret") // ErrEmptySubject when Authenticate takes empty subject. ErrEmptySubject = errors.New("guard: empty subject") // ErrInvalidAccessToken when Validate cannot get access token cookie. ErrInvalidAccessToken = errors.New("guard: missing or malformed access token") // ErrInvalidCSRFToken when Validate cannot get csrf token or token mismatches with original. ErrInvalidCSRFToken = errors.New("guard: missing or invalid csrf token") // ErrUnexpectedSigningMethod when signing method differs from default. ErrUnexpectedSigningMethod = errors.New("guard: unexpected signing method") )
View Source
var ( // ErrEmptyCookieName raises if WithAccessCookieName or WithCSRFCookieName gets empty cookie name. ErrEmptyCookieName = errors.New("guard: cookie name cannot be blank") // ErrEmptyHeaderName raises if WithCSRFHeaderName gets empty header name. ErrEmptyHeaderName = errors.New("guard: header name cannot be blank") // ErrInvalidCookiePath raises if WithPath gets invalid cookie path. ErrInvalidCookiePath = errors.New("guard: invalid cookie path") // ErrInvalidCookieTTL raises if WithTTL gets zero cookie expiration duration. ErrInvalidCookieTTL = errors.New("guard: cookie expiration cannot be zero") )
Functions ¶
This section is empty.
Types ¶
type Guard ¶
type Guard struct {
// contains filtered or unexported fields
}
Guard is used to authenticate response and validate request.
func (*Guard) Authenticate ¶
func (g *Guard) Authenticate(w http.ResponseWriter, subject string) error
Authenticate saves subject into access token cookie with csrf token.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures a Guard.
func WithAccessCookieName ¶
WithAccessCookieName sets access cookie name.
func WithCSRFCookieName ¶
WithCSRFCookieName sets csrf cookie name.
func WithCSRFHeaderName ¶
WithCSRFHeaderName sets csrf header name.
type UserClaims ¶
type UserClaims struct { *jwt.StandardClaims CSRFToken string `json:"csrfToken"` }
UserClaims holds default jwt claims and csrf token.
func (*UserClaims) Valid ¶
func (c *UserClaims) Valid() error
Valid checks whether claims are valid or not.
Click to show internal directories.
Click to hide internal directories.