mirror of
https://forgejo.merr.is/annika/jwtauth.git
synced 2025-12-13 18:45:30 -05:00
JWT Auth for go1.7
This commit is contained in:
parent
cf1ac5a102
commit
c97496f7ab
2 changed files with 25 additions and 23 deletions
33
jwtauth.go
33
jwtauth.go
|
|
@ -1,15 +1,14 @@
|
||||||
package jwtauth
|
package jwtauth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dgrijalva/jwt-go"
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
"github.com/pressly/chi"
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -59,14 +58,14 @@ func NewWithParser(alg string, parser *jwt.Parser, signKey []byte, verifyKey []b
|
||||||
// and respond to the client accordingly. A generic Authenticator
|
// and respond to the client accordingly. A generic Authenticator
|
||||||
// middleware is provided by this package, that will return a 401
|
// middleware is provided by this package, that will return a 401
|
||||||
// message for all unverified tokens, see jwtauth.Authenticator.
|
// message for all unverified tokens, see jwtauth.Authenticator.
|
||||||
func (ja *JwtAuth) Verifier(next chi.Handler) chi.Handler {
|
func (ja *JwtAuth) Verifier(next http.Handler) http.Handler {
|
||||||
return ja.Verify("")(next)
|
return ja.Verify("")(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ja *JwtAuth) Verify(paramAliases ...string) func(chi.Handler) chi.Handler {
|
func (ja *JwtAuth) Verify(paramAliases ...string) func(http.Handler) http.Handler {
|
||||||
return func(next chi.Handler) chi.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
hfn := func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
hfn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
@ -113,14 +112,14 @@ func (ja *JwtAuth) Verify(paramAliases ...string) func(chi.Handler) chi.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = ja.SetContext(ctx, token, err)
|
ctx = ja.SetContext(ctx, token, err)
|
||||||
next.ServeHTTPC(ctx, w, r)
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if token == nil || !token.Valid || token.Method != ja.signer {
|
if token == nil || !token.Valid || token.Method != ja.signer {
|
||||||
err = ErrUnauthorized
|
err = ErrUnauthorized
|
||||||
ctx = ja.SetContext(ctx, token, err)
|
ctx = ja.SetContext(ctx, token, err)
|
||||||
next.ServeHTTPC(ctx, w, r)
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,15 +127,15 @@ func (ja *JwtAuth) Verify(paramAliases ...string) func(chi.Handler) chi.Handler
|
||||||
if ja.IsExpired(token) {
|
if ja.IsExpired(token) {
|
||||||
err = ErrExpired
|
err = ErrExpired
|
||||||
ctx = ja.SetContext(ctx, token, err)
|
ctx = ja.SetContext(ctx, token, err)
|
||||||
next.ServeHTTPC(ctx, w, r)
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid! pass it down the context to an authenticator middleware
|
// Valid! pass it down the context to an authenticator middleware
|
||||||
ctx = ja.SetContext(ctx, token, err)
|
ctx = ja.SetContext(ctx, token, err)
|
||||||
next.ServeHTTPC(ctx, w, r)
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
}
|
}
|
||||||
return chi.HandlerFunc(hfn)
|
return http.HandlerFunc(hfn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,8 +193,10 @@ func (ja *JwtAuth) IsExpired(t *jwt.Token) bool {
|
||||||
// the Verifier middleware. The Authenticator sends a 401 Unauthorized response for
|
// the Verifier middleware. The Authenticator sends a 401 Unauthorized response for
|
||||||
// all unverified tokens and passes the good ones through. It's just fine until you
|
// all unverified tokens and passes the good ones through. It's just fine until you
|
||||||
// decide to write something similar and customize your client response.
|
// decide to write something similar and customize your client response.
|
||||||
func Authenticator(next chi.Handler) chi.Handler {
|
func Authenticator(next http.Handler) http.Handler {
|
||||||
return chi.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
if jwtErr, ok := ctx.Value("jwt.err").(error); ok {
|
if jwtErr, ok := ctx.Value("jwt.err").(error); ok {
|
||||||
if jwtErr != nil {
|
if jwtErr != nil {
|
||||||
http.Error(w, http.StatusText(401), 401)
|
http.Error(w, http.StatusText(401), 401)
|
||||||
|
|
@ -210,7 +211,7 @@ func Authenticator(next chi.Handler) chi.Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Token is authenticated, pass it through
|
// Token is authenticated, pass it through
|
||||||
next.ServeHTTPC(ctx, w, r)
|
next.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
"github.com/goware/jwtauth"
|
"github.com/goware/jwtauth"
|
||||||
"github.com/pressly/chi"
|
"github.com/pressly/chi"
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -33,7 +32,7 @@ func TestSimple(t *testing.T) {
|
||||||
|
|
||||||
r.Use(TokenAuth.Verifier, jwtauth.Authenticator)
|
r.Use(TokenAuth.Verifier, jwtauth.Authenticator)
|
||||||
|
|
||||||
r.Get("/", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("welcome"))
|
w.Write([]byte("welcome"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -78,8 +77,10 @@ func TestMore(t *testing.T) {
|
||||||
r.Group(func(r chi.Router) {
|
r.Group(func(r chi.Router) {
|
||||||
r.Use(TokenAuth.Verifier)
|
r.Use(TokenAuth.Verifier)
|
||||||
|
|
||||||
authenticator := func(next chi.Handler) chi.Handler {
|
authenticator := func(next http.Handler) http.Handler {
|
||||||
return chi.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
if jwtErr, ok := ctx.Value("jwt.err").(error); ok {
|
if jwtErr, ok := ctx.Value("jwt.err").(error); ok {
|
||||||
switch jwtErr {
|
switch jwtErr {
|
||||||
default:
|
default:
|
||||||
|
|
@ -103,19 +104,19 @@ func TestMore(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Token is authenticated, pass it through
|
// Token is authenticated, pass it through
|
||||||
next.ServeHTTPC(ctx, w, r)
|
next.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
r.Use(authenticator)
|
r.Use(authenticator)
|
||||||
|
|
||||||
r.Get("/admin", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
r.Get("/admin", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("protected"))
|
w.Write([]byte("protected"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Public routes
|
// Public routes
|
||||||
r.Group(func(r chi.Router) {
|
r.Group(func(r chi.Router) {
|
||||||
r.Get("/", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("welcome"))
|
w.Write([]byte("welcome"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue