feat(appcheck): Verify one-time tokens for replay protection - #774
feat(appcheck): Verify one-time tokens for replay protection#774yvonnep165 wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the VerifyOneTimeToken method to the App Check client, enabling stateful verification and consumption of one-time tokens. It also adds the AlreadyConsumed field to DecodedAppCheckToken and integrates HTTP client options. Feedback on the tests suggests using a helper function to instantiate *bool pointers to reduce verbosity, and restoring the mutated global verifyURLFormat variable to prevent potential race conditions and side effects.
| tests := []struct { | ||
| name string | ||
| backendResponse string | ||
| backendStatus int | ||
| wantAlreadyConsumed *bool | ||
| wantErr bool | ||
| }{ | ||
| { | ||
| name: "success_not_consumed", | ||
| backendResponse: `{"alreadyConsumed": false}`, | ||
| backendStatus: http.StatusOK, | ||
| wantAlreadyConsumed: func() *bool { b := false; return &b }(), | ||
| }, | ||
| { | ||
| name: "success_already_consumed", | ||
| backendResponse: `{"alreadyConsumed": true}`, | ||
| backendStatus: http.StatusOK, | ||
| wantAlreadyConsumed: func() *bool { b := true; return &b }(), | ||
| }, |
There was a problem hiding this comment.
Using inline anonymous functions to create *bool values is verbose and repetitive. Defining a simple helper function boolPtr makes the test cases much cleaner and more readable.
boolPtr := func(b bool) *bool { return &b }
tests := []struct {
name string
backendResponse string
backendStatus int
wantAlreadyConsumed *bool
wantErr bool
}{
{
name: "success_not_consumed",
backendResponse: "{\"alreadyConsumed\": false}",
backendStatus: http.StatusOK,
wantAlreadyConsumed: boolPtr(false),
},
{
name: "success_already_consumed",
backendResponse: "{\"alreadyConsumed\": true}",
backendStatus: http.StatusOK,
wantAlreadyConsumed: boolPtr(true),
},| })) | ||
| defer backend.Close() | ||
|
|
||
| verifyURLFormat = backend.URL + "/v1beta/projects/%s:verifyAppCheckToken" |
There was a problem hiding this comment.
Mutating the global variable verifyURLFormat inside the test loop can lead to race conditions if tests are run in parallel. Additionally, it leaves the global variable mutated after the test finishes, which can affect other tests in the same package. Consider restoring the original value of verifyURLFormat using defer.
oldVerifyURLFormat := verifyURLFormat
defer func() { verifyURLFormat = oldVerifyURLFormat }()
verifyURLFormat = backend.URL + "/v1beta/projects/%s:verifyAppCheckToken"
This PR introduces the
VerifyOneTimeTokenmethod to theappcheckpackage, enabling stateful replay protection for Firebase App Check.VerifyOneTimeTokenthat first performs local, stateless JWT verification followed by a statefulPOSTrequest to backend endpoint to consume the token.AlreadyConsumed(*bool) field to theDecodedAppCheckTokenstruct.option.ClientOptionfrom the main app initialization down tointernal.AppCheckConfig.