-
Notifications
You must be signed in to change notification settings - Fork 0
/
middleware.go
67 lines (58 loc) · 2.06 KB
/
middleware.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package auth
import (
"context"
"github.com/dgrijalva/jwt-go"
routing "github.com/go-ozzo/ozzo-routing/v2"
"github.com/go-ozzo/ozzo-routing/v2/auth"
"github.com/ujianmu/go-skeleton/internal/entity"
"github.com/ujianmu/go-skeleton/internal/errors"
"net/http"
)
// Handler returns a JWT-based authentication middleware.
func Handler(verificationKey string) routing.Handler {
return auth.JWT(verificationKey, auth.JWTOptions{TokenHandler: handleToken})
}
// handleToken stores the user identity in the request context so that it can be accessed elsewhere.
func handleToken(c *routing.Context, token *jwt.Token) error {
ctx := WithUser(
c.Request.Context(),
token.Claims.(jwt.MapClaims)["id"].(string),
token.Claims.(jwt.MapClaims)["name"].(string),
)
c.Request = c.Request.WithContext(ctx)
return nil
}
type contextKey int
const (
userKey contextKey = iota
)
// WithUser returns a context that contains the user identity from the given JWT.
func WithUser(ctx context.Context, id, name string) context.Context {
return context.WithValue(ctx, userKey, entity.User{ID: id, Name: name})
}
// CurrentUser returns the user identity from the given context.
// Nil is returned if no user identity is found in the context.
func CurrentUser(ctx context.Context) Identity {
if user, ok := ctx.Value(userKey).(entity.User); ok {
return user
}
return nil
}
// MockAuthHandler creates a mock authentication middleware for testing purpose.
// If the request contains an Authorization header whose value is "TEST", then
// it considers the user is authenticated as "Tester" whose ID is "100".
// It fails the authentication otherwise.
func MockAuthHandler(c *routing.Context) error {
if c.Request.Header.Get("Authorization") != "TEST" {
return errors.Unauthorized("")
}
ctx := WithUser(c.Request.Context(), "100", "Tester")
c.Request = c.Request.WithContext(ctx)
return nil
}
// MockAuthHeader returns an HTTP header that can pass the authentication check by MockAuthHandler.
func MockAuthHeader() http.Header {
header := http.Header{}
header.Add("Authorization", "TEST")
return header
}