Repository navigation
Expand file tree
/
Copy pathpresentation.go
More file actions
101 lines (85 loc) · 2.99 KB
/
Copy pathpresentation.go
File metadata and controls
101 lines (85 loc) · 2.99 KB
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package auth
import (
"context"
"crypto/sha256"
"strings"
"unicode"
)
type explicitFrameCredentialKey struct{}
type explicitFrameCredential struct {
scheme string
digest [sha256.Size]byte
}
// ParseExplicitFrameCredential parses a protocol frame's selected credential.
// You can supply a bare token, Bearer <token>, or DPoP <token>. The returned
// scheme is canonical, and token bytes are preserved after splitting fields.
// Proofs must use the transport's existing proof channel.
func ParseExplicitFrameCredential(presentation string) (scheme, token string, err error) {
if strings.IndexFunc(presentation, unicode.IsControl) >= 0 {
return "", "", ErrInvalidCredentials
}
fields := strings.Fields(presentation)
switch len(fields) {
case 1:
if strings.EqualFold(fields[0], "Bearer") || strings.EqualFold(fields[0], "DPoP") {
return "", "", ErrInvalidCredentials
}
scheme, token = "Bearer", fields[0]
case 2:
scheme, token = fields[0], fields[1]
default:
return "", "", ErrInvalidCredentials
}
scheme, ok := explicitFrameScheme(scheme, token)
if !ok {
return "", "", ErrInvalidCredentials
}
return scheme, token, nil
}
// WithExplicitFrameCredential records a credential received in a protocol
// frame after request middleware. Call it only from trusted transport code,
// using the same parsed scheme and token you put in the Authorization header.
// Never create this marker from request headers, cookies, or claims.
//
// The marker stores a digest, preserves the parent context, and grants no
// identity. Providers must still validate the credential and any required proof.
func WithExplicitFrameCredential(ctx context.Context, scheme, token string) (context.Context, error) {
scheme, ok := explicitFrameScheme(scheme, token)
if !ok {
return ctx, ErrInvalidCredentials
}
return context.WithValue(ctx, explicitFrameCredentialKey{}, explicitFrameCredential{
scheme: scheme,
digest: sha256.Sum256([]byte(token)),
}), nil
}
// MatchesExplicitFrameCredential reports whether trusted transport code marked
// this exact scheme and token as an explicit frame presentation. Only check
// credentials extracted from a valid Authorization presentation. A match does
// not authenticate the token or promote credentials read from cookie fallback.
func MatchesExplicitFrameCredential(ctx context.Context, scheme, token string) bool {
if ctx == nil {
return false
}
scheme, ok := explicitFrameScheme(scheme, token)
if !ok {
return false
}
marker, ok := ctx.Value(explicitFrameCredentialKey{}).(explicitFrameCredential)
return ok && marker.scheme == scheme && marker.digest == sha256.Sum256([]byte(token))
}
func explicitFrameScheme(scheme, token string) (string, bool) {
if token == "" || strings.IndexFunc(token, func(r rune) bool {
return unicode.IsSpace(r) || unicode.IsControl(r)
}) >= 0 {
return "", false
}
switch {
case strings.EqualFold(scheme, "Bearer"):
return "Bearer", true
case strings.EqualFold(scheme, "DPoP"):
return "DPoP", true
default:
return "", false
}
}