forked from dgrijalva/jwt-go
/
appengine.go
95 lines (75 loc) · 2.06 KB
/
appengine.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// +build appengine
package jwt
import (
"crypto"
"crypto/rsa"
"crypto/sha256"
"appengine"
)
// Implements the built-in AppEngine signing method
// This method uses a private key unique to your AppEngine
// application and the key may rotate from time to time.
// https://cloud.google.com/appengine/docs/go/reference#SignBytes
// https://cloud.google.com/appengine/docs/go/appidentity/#Go_Asserting_identity_to_other_systems
type SigningMethodAppEngine struct{}
type certificates []appengine.Certificate
func init() {
RegisterSigningMethod("AppEngine", func() SigningMethod {
return &SigningMethodAppEngine{}
})
}
func (s *SigningMethodAppEngine) Alg() string {
return "AppEngine"
}
// Implements the Sign method from SigningMethod
// For this signing method, a valid appengine.Context must be
// passed as the key.
func (s *SigningMethodAppEngine) Sign(signingString string, key interface{}) (string, error) {
var ctx appengine.Context
switch k := key.(type) {
case appengine.Context:
ctx = k
default:
return "", ErrInvalidKey
}
_, signature, err := appengine.SignBytes(ctx, []byte(signingString))
if err != nil {
return "", err
}
return EncodeSegment(signature), nil
}
// Implements the Verify method from SigningMethod
// For this signing method, a valid appengine.Context must be
// passed as the key.
func (s *SigningMethodAppEngine) Verify(signingString, signature string, key interface{}) error {
var ctx appengine.Context
switch k := key.(type) {
case appengine.Context:
ctx = k
default:
return ErrInvalidKey
}
var sig []byte
var err error
if sig, err = DecodeSegment(signature); err != nil {
return err
}
var certs certificates
certs, err = appengine.PublicCertificates(ctx)
if err != nil {
return err
}
hasher := sha256.New()
hasher.Write([]byte(signingString))
var certErr error
for _, cert := range certs {
rsaKey, err := ParseRSAPublicKeyFromPEM(cert.Data)
if err != nil {
return err
}
if certErr = rsa.VerifyPKCS1v15(rsaKey, crypto.SHA256, hasher.Sum(nil), sig); certErr == nil {
return nil
}
}
return certErr
}