-
Notifications
You must be signed in to change notification settings - Fork 0
/
user.go
79 lines (68 loc) · 2.26 KB
/
user.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
68
69
70
71
72
73
74
75
76
77
78
79
package middleware
import (
"context"
"strings"
"github.com/pkg/errors"
"github.com/stackrox/infra-auth-lib/auth"
v1 "github.com/stackrox/infra-auth-lib/generated/go/proto/api/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
type userContextKey struct{}
// UserEnricher enriches the given gRPC context with a v1.User struct, if
// possible. If there is no user, this function does not return an error, as
// anonymous API calls are a possibility. Authorization must be independently
// enforced.
func UserEnricher(cfg auth.OidcAuth) contextFunc {
return func(ctx context.Context, _ *grpc.UnaryServerInfo) (context.Context, error) {
// Extract request metadata (proxied http headers) from given context.
meta, ok := metadata.FromIncomingContext(ctx)
if !ok {
return nil, errors.New("failed to extract metadata from incoming context")
}
// Extract cookie key/value pairs from request metadata.
items := cookieValues(meta)
token, found := items["token"]
if !found {
return ctx, nil
}
// Validate the user JWT and extract the user and expiry properties.
user, err := cfg.ValidateUser(token)
if err != nil {
return ctx, nil
}
// Enrich the given context with the user.
return contextWithUser(ctx, user), nil
}
}
// UserFromContext extracts a v1.User from the given context, if one exists.
func UserFromContext(ctx context.Context) (*v1.User, bool) {
userValue := ctx.Value(userContextKey{})
if userValue == nil {
return nil, false
}
return userValue.(*v1.User), true
}
// contextWithUser returns the given context enriched with a v1.User.
func contextWithUser(ctx context.Context, user *v1.User) context.Context {
return context.WithValue(ctx, userContextKey{}, user)
}
// cookieValues converts cookies stored in the gRPC-Gateway metadata into a more usable form.
func cookieValues(meta metadata.MD) map[string]string {
cookies := meta.Get("grpcgateway-cookie")
items := make(map[string]string)
for _, cookie := range cookies {
for _, part := range strings.Split(cookie, ";") {
fields := strings.SplitN(part, "=", 2)
switch len(fields) {
case 2:
items[strings.TrimSpace(fields[0])] = strings.TrimSpace(fields[1])
case 1:
items[strings.TrimSpace(fields[0])] = ""
default:
continue
}
}
}
return items
}