Skip to content

Commit 7632d2f

Browse files
Merge pull request #386 from supertokens/feat/network-interceptor-hook
feat: Added network interceptor hook
2 parents 583b953 + 488f492 commit 7632d2f

28 files changed

+384
-123
lines changed

.github/workflows/enforce-go-mod-tidy.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ jobs:
99
# When using actions/checkout in a custom container, the directory is not treated as a git repo and does not have a .git directory, therefore we need to initialize it as a git repo. This will allows us to track changes made after go mod tidy runs
1010
- name: Create a new git repository
1111
run: git init && git add --all && git -c user.name='test' -c user.email='[email protected]' commit -m 'init for pr action'
12+
- name: Install latest go
13+
run: wget https://go.dev/dl/go1.21.3.linux-amd64.tar.gz && rm -rf /usr/local/go && tar -C /usr/local -xzf go*.tar.gz && export PATH=$PATH:/usr/local/go/bin && rm go1.21.3.linux-amd64.tar.gz
1214
- name: Go mod tidy for root project
1315
run: go mod tidy
1416
- name: Go mod tidy for example apps

.github/workflows/pre-commit-hook-run.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ jobs:
2020
with:
2121
node-version: '12'
2222
- run: git init && git add --all && git -c user.name='test' -c user.email='[email protected]' commit -m 'init for pr action'
23+
- name: Install latest go
24+
run: wget https://go.dev/dl/go1.21.3.linux-amd64.tar.gz && rm -rf /usr/local/go && tar -C /usr/local -xzf go*.tar.gz && export PATH=$PATH:/usr/local/go/bin && rm go1.21.3.linux-amd64.tar.gz
2325
- run: ./hooks/pre-commit.sh

.github/workflows/tests.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ jobs:
5050
run: cd ../supertokens-root && ./loadModules
5151
- name: Setting up supertokens-root test environment
5252
run: cd ../supertokens-root && bash ./utils/setupTestEnvLocal
53+
- name: Install latest go
54+
run: wget https://go.dev/dl/go1.21.3.linux-amd64.tar.gz && rm -rf /usr/local/go && tar -C /usr/local -xzf go*.tar.gz && export PATH=$PATH:/usr/local/go/bin && rm go1.21.3.linux-amd64.tar.gz
5355
- name: Run tests
5456
run: go test ./... -p 1 -v count=1
5557
env:

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [unreleased]
99

10+
## [0.16.6] - 2023-11-3
11+
12+
- Added `NetworkInterceptor` to the `ConnectionInfo` config.
13+
- This can be used to capture/modify all the HTTP requests sent to the core.
14+
- Solves the issue - https://github.com/supertokens/supertokens-core/issues/865
1015

1116
## [0.16.5] - 2023-11-1
1217

recipe/dashboard/api/analyticsPOST.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func AnalyticsPost(apiInterface dashboardmodels.APIInterface, tenantId string, o
7676
return analyticsPostResponse{}, err
7777
}
7878

79-
response, err := querier.SendGetRequest("/telemetry", nil)
79+
response, err := querier.SendGetRequest("/telemetry", nil, userContext)
8080
if err != nil {
8181
// We don't send telemetry events if this fails
8282
return analyticsPostResponse{

recipe/dashboard/api/search/tagsGet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func SearchTagsGet(apiImplementation dashboardmodels.APIInterface, tenantId stri
3232
return searchTagsResponse{}, querierErr
3333
}
3434

35-
apiResponse, apiErr := querier.SendGetRequest("/user/search/tags", nil)
35+
apiResponse, apiErr := querier.SendGetRequest("/user/search/tags", nil, userContext)
3636
if apiErr != nil {
3737
return searchTagsResponse{}, apiErr
3838
}

recipe/dashboard/api/signInPost.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func SignInPost(apiInterface dashboardmodels.APIInterface, options dashboardmode
5252
apiResponse, apiErr := querier.SendPostRequest("/recipe/dashboard/signin", map[string]interface{}{
5353
"email": *readBody.Email,
5454
"password": *readBody.Password,
55-
})
55+
}, userContext)
5656

5757
if apiErr != nil {
5858
return apiErr

recipe/dashboard/api/signOutPost.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func SignOutPost(apiInterface dashboardmodels.APIInterface, tenantId string, opt
3232

3333
_, apiError := querier.SendDeleteRequest("/recipe/dashboard/session", map[string]interface{}{}, map[string]string{
3434
"sessionId": sessionIdFromHeader,
35-
})
35+
}, userContext)
3636

3737
if apiError != nil {
3838
return signOutPostResponse{}, apiError

recipe/dashboard/recipeimplementation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func makeRecipeImplementation(querier supertokens.Querier) dashboardmodels.Recip
4141

4242
verifyResponse, err := querier.SendPostRequest("/recipe/dashboard/session/verify", map[string]interface{}{
4343
"sessionId": authHeaderValue,
44-
})
44+
}, userContext)
4545

4646
if err != nil {
4747
return false, err
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
package emailpassword
2+
3+
import (
4+
"bytes"
5+
"net/http"
6+
"net/http/httptest"
7+
"net/url"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/supertokens/supertokens-golang/recipe/userroles"
12+
"github.com/supertokens/supertokens-golang/supertokens"
13+
"github.com/supertokens/supertokens-golang/test/unittesting"
14+
)
15+
16+
var isNetworkIntercepted = false
17+
18+
func TestNetworkInterceptorDuringSignIn(t *testing.T) {
19+
configValue := supertokens.TypeInput{
20+
Supertokens: &supertokens.ConnectionInfo{
21+
ConnectionURI: "http://localhost:8080",
22+
NetworkInterceptor: func(request *http.Request, context supertokens.UserContext) *http.Request {
23+
isNetworkIntercepted = true
24+
return request
25+
},
26+
},
27+
AppInfo: supertokens.AppInfo{
28+
AppName: "SuperTokens",
29+
APIDomain: "api.supertokens.io",
30+
WebsiteDomain: "supertokens.io",
31+
},
32+
RecipeList: []supertokens.Recipe{
33+
Init(nil),
34+
},
35+
}
36+
BeforeEach()
37+
38+
unittesting.StartUpST("localhost", "8080")
39+
40+
defer AfterEach()
41+
42+
err := supertokens.Init(configValue)
43+
44+
if err != nil {
45+
t.Error(err.Error())
46+
}
47+
48+
mux := http.NewServeMux()
49+
testServer := httptest.NewServer(supertokens.Middleware(mux))
50+
defer testServer.Close()
51+
52+
res, err := unittesting.SignInRequest("[email protected]", "validpass123", testServer.URL)
53+
54+
if err != nil {
55+
t.Error(err.Error())
56+
}
57+
58+
assert.Equal(t, 200, res.StatusCode)
59+
assert.Equal(t, true, isNetworkIntercepted)
60+
}
61+
62+
func TestNetworkInterceptorNotSet(t *testing.T) {
63+
isNetworkIntercepted = false
64+
configValue := supertokens.TypeInput{
65+
Supertokens: &supertokens.ConnectionInfo{
66+
ConnectionURI: "http://localhost:8080",
67+
},
68+
AppInfo: supertokens.AppInfo{
69+
AppName: "SuperTokens",
70+
APIDomain: "api.supertokens.io",
71+
WebsiteDomain: "supertokens.io",
72+
},
73+
RecipeList: []supertokens.Recipe{
74+
Init(nil),
75+
},
76+
}
77+
BeforeEach()
78+
79+
unittesting.StartUpST("localhost", "8080")
80+
81+
defer AfterEach()
82+
83+
err := supertokens.Init(configValue)
84+
85+
if err != nil {
86+
t.Error(err.Error())
87+
}
88+
89+
mux := http.NewServeMux()
90+
testServer := httptest.NewServer(supertokens.Middleware(mux))
91+
defer testServer.Close()
92+
93+
res, err := unittesting.SignInRequest("[email protected]", "validpass123", testServer.URL)
94+
95+
if err != nil {
96+
t.Error(err.Error())
97+
}
98+
99+
assert.Equal(t, 200, res.StatusCode)
100+
assert.Equal(t, false, isNetworkIntercepted)
101+
}
102+
103+
func TestNetworkInterceptorIncorrectCoreURL(t *testing.T) {
104+
isNetworkIntercepted = false
105+
configValue := supertokens.TypeInput{
106+
Supertokens: &supertokens.ConnectionInfo{
107+
ConnectionURI: "http://localhost:8080",
108+
NetworkInterceptor: func(request *http.Request, context supertokens.UserContext) *http.Request {
109+
isNetworkIntercepted = true
110+
newRequest := request
111+
newRequest.URL.Path = "/public/recipe/incorrect/path"
112+
return newRequest
113+
},
114+
},
115+
AppInfo: supertokens.AppInfo{
116+
AppName: "SuperTokens",
117+
APIDomain: "api.supertokens.io",
118+
WebsiteDomain: "supertokens.io",
119+
},
120+
RecipeList: []supertokens.Recipe{
121+
Init(nil),
122+
},
123+
}
124+
BeforeEach()
125+
126+
unittesting.StartUpST("localhost", "8080")
127+
128+
defer AfterEach()
129+
130+
err := supertokens.Init(configValue)
131+
132+
if err != nil {
133+
t.Error(err.Error())
134+
}
135+
136+
mux := http.NewServeMux()
137+
testServer := httptest.NewServer(supertokens.Middleware(mux))
138+
defer testServer.Close()
139+
140+
_, err = SignIn("public", "[email protected]", "validpass123")
141+
142+
assert.NotNil(t, err, "there should be an error")
143+
assert.Contains(t, err.Error(), "status code: 404")
144+
assert.Equal(t, true, isNetworkIntercepted)
145+
}
146+
147+
func TestNetworkInterceptorIncorrectQueryParams(t *testing.T) {
148+
isNetworkIntercepted = false
149+
configValue := supertokens.TypeInput{
150+
Supertokens: &supertokens.ConnectionInfo{
151+
ConnectionURI: "http://localhost:8080",
152+
NetworkInterceptor: func(r *http.Request, context supertokens.UserContext) *http.Request {
153+
isNetworkIntercepted = true
154+
newRequest := r
155+
q := url.Values{}
156+
newRequest.URL.RawQuery = q.Encode()
157+
return newRequest
158+
},
159+
},
160+
AppInfo: supertokens.AppInfo{
161+
AppName: "SuperTokens",
162+
APIDomain: "api.supertokens.io",
163+
WebsiteDomain: "supertokens.io",
164+
},
165+
RecipeList: []supertokens.Recipe{
166+
Init(nil),
167+
userroles.Init(nil),
168+
},
169+
}
170+
BeforeEach()
171+
172+
unittesting.StartUpST("localhost", "8080")
173+
174+
defer AfterEach()
175+
176+
supertokens.Init(configValue)
177+
178+
mux := http.NewServeMux()
179+
testServer := httptest.NewServer(supertokens.Middleware(mux))
180+
defer testServer.Close()
181+
182+
resp, _ := SignUp("public", "[email protected]", "validpass123")
183+
_, err := userroles.GetRolesForUser("public", resp.OK.User.ID)
184+
assert.NotNil(t, err, "should err, because userId is not passed")
185+
assert.Contains(t, err.Error(), "status code: 400")
186+
assert.Equal(t, true, isNetworkIntercepted)
187+
}
188+
189+
func TestNetworkInterceptorRequestBody(t *testing.T) {
190+
isNetworkIntercepted = false
191+
configValue := supertokens.TypeInput{
192+
Supertokens: &supertokens.ConnectionInfo{
193+
ConnectionURI: "http://localhost:8080",
194+
NetworkInterceptor: func(r *http.Request, context supertokens.UserContext) *http.Request {
195+
isNetworkIntercepted = true
196+
newBody := bytes.NewReader([]byte(`{"newKey": "newValue"}`))
197+
req, _ := http.NewRequest(r.Method, r.URL.String(), newBody)
198+
req.Header = r.Header
199+
return req
200+
},
201+
},
202+
AppInfo: supertokens.AppInfo{
203+
AppName: "SuperTokens",
204+
APIDomain: "api.supertokens.io",
205+
WebsiteDomain: "supertokens.io",
206+
},
207+
RecipeList: []supertokens.Recipe{
208+
Init(nil),
209+
},
210+
}
211+
BeforeEach()
212+
213+
unittesting.StartUpST("localhost", "8080")
214+
215+
defer AfterEach()
216+
217+
supertokens.Init(configValue)
218+
219+
mux := http.NewServeMux()
220+
testServer := httptest.NewServer(supertokens.Middleware(mux))
221+
defer testServer.Close()
222+
223+
_, err := SignIn("public", "[email protected]", "validpass123")
224+
assert.NotNil(t, err, "should err, because request body is incorrect")
225+
assert.Contains(t, err.Error(), "status code: 400")
226+
assert.Equal(t, true, isNetworkIntercepted)
227+
}

0 commit comments

Comments
 (0)