15
15
package certapi
16
16
17
17
import (
18
+ "errors"
18
19
"net/http"
19
20
"time"
20
21
21
22
"github.com/dgrijalva/jwt-go"
22
23
"github.com/google/exposure-notifications-server/pkg/base64util"
23
24
"github.com/google/exposure-notifications-verification-server/pkg/api"
24
25
"github.com/google/exposure-notifications-verification-server/pkg/controller"
26
+ "github.com/google/exposure-notifications-verification-server/pkg/database"
25
27
"github.com/google/exposure-notifications-verification-server/pkg/jwthelper"
26
28
27
29
verifyapi "github.com/google/exposure-notifications-server/pkg/api/v1"
@@ -33,48 +35,50 @@ func (c *Controller) HandleCertificate() http.Handler {
33
35
34
36
authApp := controller .AuthorizedAppFromContext (ctx )
35
37
if authApp == nil {
38
+ c .logger .Errorf ("missing authorized app" )
36
39
controller .MissingAuthorizedApp (w , r , c .h )
37
40
return
38
41
}
39
42
40
43
publicKey , err := c .getPublicKey (ctx , c .config .TokenSigningKey )
41
44
if err != nil {
42
45
c .logger .Errorw ("failed to get public key" , "error" , err )
43
- c .h .RenderJSON (w , http .StatusInternalServerError , nil )
46
+ c .h .RenderJSON (w , http .StatusInternalServerError , api . InternalError () )
44
47
return
45
48
}
46
49
47
50
// Get the signer based on Key configuration.
48
51
signer , err := c .signer .NewSigner (ctx , c .config .CertificateSigningKey )
49
52
if err != nil {
50
53
c .logger .Errorw ("failed to get signer" , "error" , err )
51
- c .h .RenderJSON (w , http .StatusInternalServerError , nil )
54
+ c .h .RenderJSON (w , http .StatusInternalServerError , api . InternalError () )
52
55
return
53
56
}
54
57
55
58
var request api.VerificationCertificateRequest
56
59
if err := controller .BindJSON (w , r , & request ); err != nil {
57
- c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ))
60
+ c .logger .Errorf ("failed to parse json request" , "error" , err )
61
+ c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ).WithCode (api .ErrTokenInvalid ))
58
62
return
59
63
}
60
64
61
65
// Parse and validate the verification token.
62
66
tokenID , subject , err := c .validateToken (request .VerificationToken , publicKey )
63
67
if err != nil {
64
- c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ))
68
+ c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ). WithCode ( api . ErrTokenInvalid ) )
65
69
return
66
70
}
67
71
68
72
// Validate the HMAC length. SHA 256 HMAC must be 32 bytes in length.
69
73
hmacBytes , err := base64util .DecodeString (request .ExposureKeyHMAC )
70
74
if err != nil {
71
75
c .h .RenderJSON (w , http .StatusBadRequest ,
72
- api .Errorf ("exposure key HMAC is not a valid base64: %v" , err ))
76
+ api .Errorf ("exposure key HMAC is not a valid base64: %v" , err ). WithCode ( api . ErrHMACInvalid ) )
73
77
return
74
78
}
75
79
if len (hmacBytes ) != 32 {
76
80
c .h .RenderJSON (w , http .StatusBadRequest ,
77
- api .Errorf ("exposure key HMAC is not the correct length, want: 32 got: %v" , len (hmacBytes )))
81
+ api .Errorf ("exposure key HMAC is not the correct length, want: 32 got: %v" , len (hmacBytes )). WithCode ( api . ErrHMACInvalid ) )
78
82
return
79
83
}
80
84
@@ -99,15 +103,24 @@ func (c *Controller) HandleCertificate() http.Handler {
99
103
certificate , err := jwthelper .SignJWT (certToken , signer )
100
104
if err != nil {
101
105
c .logger .Errorw ("failed to sign certificate" , "error" , err )
102
- c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ))
106
+ c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ). WithCode ( api . ErrInternal ) )
103
107
return
104
108
}
105
109
106
110
// Do the transactional update to the database last so that if it fails, the
107
111
// client can retry.
108
112
if err := c .db .ClaimToken (authApp .RealmID , tokenID , subject ); err != nil {
109
113
c .logger .Errorw ("failed to claim token" , "tokenID" , tokenID , "error" , err )
110
- c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ))
114
+ switch {
115
+ case errors .Is (err , database .ErrTokenExpired ):
116
+ c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ).WithCode (api .ErrTokenExpired ))
117
+ case errors .Is (err , database .ErrTokenUsed ):
118
+ c .h .RenderJSON (w , http .StatusBadRequest , api .Errorf ("verification token invalid" ).WithCode (api .ErrTokenExpired ))
119
+ case errors .Is (err , database .ErrTokenMetadataMismatch ):
120
+ c .h .RenderJSON (w , http .StatusBadRequest , api .Errorf ("verification token invalid" ).WithCode (api .ErrTokenExpired ))
121
+ default :
122
+ c .h .RenderJSON (w , http .StatusBadRequest , api .Error (err ))
123
+ }
111
124
return
112
125
}
113
126
0 commit comments