Skip to content

Commit 10f3e88

Browse files
Fix up auth middleware
1 parent ccba16e commit 10f3e88

24 files changed

Lines changed: 212 additions & 167 deletions

api/auth_middleware.go

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -100,37 +100,57 @@ func (app *ApiServer) getAuthedWallet(c *fiber.Ctx) string {
100100
}
101101

102102
// Middleware to set authedUserId and authedWallet in context
103+
// Returns a 403 if either
104+
// - the user is not authorized to act on behalf of "myId"
105+
// - the user is not authorized to act on behalf of "requestedWallet"
103106
func (app *ApiServer) authMiddleware(c *fiber.Ctx) error {
104107
userId, wallet := app.recoverAuthorityFromSignatureHeaders(c)
105108
c.Locals("authedUserId", userId)
106109
c.Locals("authedWallet", wallet)
110+
fmt.Println("authMiddleware", userId, wallet)
111+
112+
myId := app.getMyId(c)
113+
requestedWallet := c.Params("wallet")
114+
115+
// Not authorized to act on behalf of myId
116+
if myId != 0 {
117+
if userId != myId && !app.isAuthorizedRequest(c.Context(), myId, wallet) {
118+
return fiber.NewError(
119+
fiber.StatusForbidden,
120+
fmt.Sprintf(
121+
"You are not authorized to make this request authedUserId=%d authedWallet=%s myId=%d",
122+
userId,
123+
wallet,
124+
myId,
125+
),
126+
)
127+
}
128+
}
129+
130+
// Not authorized to act on behalf of requestedWallet
131+
if requestedWallet != "" && wallet != "" {
132+
if !strings.EqualFold(requestedWallet, wallet) {
133+
return fiber.NewError(
134+
fiber.StatusForbidden,
135+
fmt.Sprintf(
136+
"You are not authorized to make this request authedUserId=%d authedWallet=%s requestedWallet=%s",
137+
userId,
138+
wallet,
139+
requestedWallet,
140+
),
141+
)
142+
}
143+
}
107144

108145
return c.Next()
109146
}
110147

111-
// Middleware that asserts the authedUserId is valid and is the same as the userId in
112-
// the request path or a managed user of the authedUserId
148+
// Middleware that asserts that there is an authedUserId
113149
func (app *ApiServer) requireAuthMiddleware(c *fiber.Ctx) error {
114150
authedUserId := app.getAuthedUserId(c)
115-
authedWallet := app.getAuthedWallet(c)
116-
myId := app.getMyId(c)
117-
wallet := c.Params("wallet")
118151
if authedUserId == 0 {
119152
return fiber.NewError(fiber.StatusUnauthorized, "You must be logged in to make this request")
120153
}
121154

122-
if myId != 0 && myId == authedUserId {
123-
return c.Next()
124-
}
125-
126-
if wallet != "" && strings.EqualFold(wallet, authedWallet) {
127-
return c.Next()
128-
}
129-
130-
if app.isAuthorizedRequest(c.Context(), myId, authedWallet) {
131-
return c.Next()
132-
}
133-
134-
msg := fmt.Sprintf("You are not authorized to make this request authedUserId=%d authedWallet=%s myId=%d wallet=%s", authedUserId, authedWallet, myId, wallet)
135-
return fiber.NewError(fiber.StatusForbidden, msg)
155+
return c.Next()
136156
}

api/auth_middleware_test.go

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,52 +29,81 @@ func TestRecoverAuthorityFromSignatureHeaders(t *testing.T) {
2929
assert.Equal(t, "0x7d273271690538cf855e5b3002a0dd8c154bb060", wallet)
3030
}
3131

32-
func TestRequireAuthMiddleware(t *testing.T) {
33-
// Create a dummy endpoint to test the requireAuthMiddleware
32+
func TestAuthorized(t *testing.T) {
33+
// Create a dummy endpoint to test the authMiddleware
3434
testApp := fiber.New()
35-
testApp.Get("/", app.resolveMyIdMiddleware, app.authMiddleware, app.requireAuthMiddleware, func(c *fiber.Ctx) error {
35+
testApp.Get("/", app.resolveMyIdMiddleware, app.authMiddleware, func(c *fiber.Ctx) error {
36+
return c.SendStatus(fiber.StatusOK)
37+
})
38+
testApp.Get("/account/:wallet", app.resolveMyIdMiddleware, app.authMiddleware, func(c *fiber.Ctx) error {
3639
return c.SendStatus(fiber.StatusOK)
3740
})
38-
39-
// Unauthorized when no auth headers
40-
req1 := httptest.NewRequest("GET", "/", nil)
41-
res, err := testApp.Test(req1, -1)
42-
assert.NoError(t, err)
43-
assert.Equal(t, fiber.StatusUnauthorized, res.StatusCode)
4441

4542
// Forbidden when not authorized
46-
req2 := httptest.NewRequest("GET", "/?user_id=1", nil)
43+
req := httptest.NewRequest("GET", "/?user_id=7eP5n", nil)
4744
// wallet: 0x681c616ae836ceca1effe00bd07f2fdbf9a082bc
48-
req2.Header.Set("Encoded-Data-Message", "signature:1745543704165")
49-
req2.Header.Set("Encoded-Data-Signature", "0x4af765948dccd72026f1059a59c7a6a1172628255d7d387d1590c0fe43961c5908fc6011443805ca0dbd39156300c04dc21bbfa9adce50acea9ad29a7e2fde2a1b")
50-
res, err = testApp.Test(req2, -1)
45+
req.Header.Set("Encoded-Data-Message", "signature:1745543704165")
46+
req.Header.Set("Encoded-Data-Signature", "0x4af765948dccd72026f1059a59c7a6a1172628255d7d387d1590c0fe43961c5908fc6011443805ca0dbd39156300c04dc21bbfa9adce50acea9ad29a7e2fde2a1b")
47+
res, err := testApp.Test(req, -1)
5148
assert.NoError(t, err)
5249
assert.Equal(t, fiber.StatusForbidden, res.StatusCode)
5350

5451
// Forbidden when grant is revoked
55-
req3 := httptest.NewRequest("GET", "/?user_id=1", nil)
52+
req = httptest.NewRequest("GET", "/?user_id=7eP5n", nil)
5653
// wallet: 0xc451c1f8943b575158310552b41230c61844a1c1
57-
req3.Header.Set("Encoded-Data-Message", "signature:1745542789211")
58-
req3.Header.Set("Encoded-Data-Signature", "0xffd5f92c0d253c7222cd407cf3398fac664530ef968bd4435ea698ba1daee1d73353330848b65d212eeeaae9f41e177e49078c4efa1131e5e517090626f6dd961c")
59-
res, err = testApp.Test(req3, -1)
54+
req.Header.Set("Encoded-Data-Message", "signature:1745542789211")
55+
req.Header.Set("Encoded-Data-Signature", "0xffd5f92c0d253c7222cd407cf3398fac664530ef968bd4435ea698ba1daee1d73353330848b65d212eeeaae9f41e177e49078c4efa1131e5e517090626f6dd961c")
56+
res, err = testApp.Test(req, -1)
6057
assert.NoError(t, err)
6158
assert.Equal(t, fiber.StatusForbidden, res.StatusCode)
6259

6360
// Authorized when grant is approved
64-
req4 := httptest.NewRequest("GET", "/?user_id=1", nil)
61+
req = httptest.NewRequest("GET", "/?user_id=7eP5n", nil)
6562
// wallet: 0x5f1a372b28956c8363f8bc3a231a6e9e1186ead8
66-
req4.Header.Set("Encoded-Data-Message", "signature:1745544459796")
67-
req4.Header.Set("Encoded-Data-Signature", "0x1c9cb405d8437d28ff5596918551f7a45f981e81618d65ee10892313292a8c7a325af002231d115b28ca2d244b082abe1bde4a7d9610f8140d3738a9be5c4fd91b")
68-
res, err = testApp.Test(req4, -1)
63+
req.Header.Set("Encoded-Data-Message", "signature:1745544459796")
64+
req.Header.Set("Encoded-Data-Signature", "0x1c9cb405d8437d28ff5596918551f7a45f981e81618d65ee10892313292a8c7a325af002231d115b28ca2d244b082abe1bde4a7d9610f8140d3738a9be5c4fd91b")
65+
res, err = testApp.Test(req, -1)
6966
assert.NoError(t, err)
7067
assert.Equal(t, fiber.StatusOK, res.StatusCode)
7168

7269
// Authorized when own user
73-
req5 := httptest.NewRequest("GET", "/?user_id=1", nil)
70+
req = httptest.NewRequest("GET", "/?user_id=7eP5n", nil)
7471
// wallet: 0x7d273271690538cf855e5b3002a0dd8c154bb060
75-
req5.Header.Set("Encoded-Data-Message", "signature:1744763856446")
76-
req5.Header.Set("Encoded-Data-Signature", "0xbb202be3a7f3a0aa22c1458ef6a3f2f8360fb86791c7b137e8562df0707825c11fa1db01096efd2abc5e6613c4d1e8d4ae1e2b993abdd555fe270c1b17bff0d21c")
77-
res, err = testApp.Test(req5, -1)
72+
req.Header.Set("Encoded-Data-Message", "signature:1744763856446")
73+
req.Header.Set("Encoded-Data-Signature", "0xbb202be3a7f3a0aa22c1458ef6a3f2f8360fb86791c7b137e8562df0707825c11fa1db01096efd2abc5e6613c4d1e8d4ae1e2b993abdd555fe270c1b17bff0d21c")
74+
res, err = testApp.Test(req, -1)
75+
assert.NoError(t, err)
76+
assert.Equal(t, fiber.StatusOK, res.StatusCode)
77+
78+
// Forbidden when not authorized to act on behalf of requested wallet
79+
req = httptest.NewRequest("GET", "/account/0x111c616ae836ceca1effe00bd07f2fdbf9a082bc", nil)
80+
// wallet: 0x681c616ae836ceca1effe00bd07f2fdbf9a082bc
81+
req.Header.Set("Encoded-Data-Message", "signature:1745543704165")
82+
req.Header.Set("Encoded-Data-Signature", "0x4af765948dccd72026f1059a59c7a6a1172628255d7d387d1590c0fe43961c5908fc6011443805ca0dbd39156300c04dc21bbfa9adce50acea9ad29a7e2fde2a1b")
83+
res, err = testApp.Test(req, -1)
84+
assert.NoError(t, err)
85+
assert.Equal(t, fiber.StatusForbidden, res.StatusCode)
86+
87+
// Authorized when requesting wallet matches authed wallet
88+
req = httptest.NewRequest("GET", "/account/0x681c616ae836ceca1effe00bd07f2fdbf9a082bc", nil)
89+
// wallet: 0x681c616ae836ceca1effe00bd07f2fdbf9a082bc
90+
req.Header.Set("Encoded-Data-Message", "signature:1745543704165")
91+
req.Header.Set("Encoded-Data-Signature", "0x4af765948dccd72026f1059a59c7a6a1172628255d7d387d1590c0fe43961c5908fc6011443805ca0dbd39156300c04dc21bbfa9adce50acea9ad29a7e2fde2a1b")
92+
res, err = testApp.Test(req, -1)
7893
assert.NoError(t, err)
7994
assert.Equal(t, fiber.StatusOK, res.StatusCode)
8095
}
96+
97+
func TestRequireAuthMiddleware(t *testing.T) {
98+
// Create a dummy endpoint to test the requireAuthMiddleware
99+
testApp := fiber.New()
100+
testApp.Get("/", app.resolveMyIdMiddleware, app.authMiddleware, app.requireAuthMiddleware, func(c *fiber.Ctx) error {
101+
return c.SendStatus(fiber.StatusOK)
102+
})
103+
104+
// Unauthorized when no auth headers
105+
req1 := httptest.NewRequest("GET", "/", nil)
106+
res, err := testApp.Test(req1, -1)
107+
assert.NoError(t, err)
108+
assert.Equal(t, fiber.StatusUnauthorized, res.StatusCode)
109+
}

api/dbv1/access.go

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dbv1
22

33
import (
44
"context"
5+
"fmt"
56
)
67

78
type Access struct {
@@ -12,31 +13,28 @@ type Access struct {
1213
func (q *Queries) GetTrackAccess(
1314
ctx context.Context,
1415
myId int32,
15-
authedUserId int32,
16-
authedWallet string,
17-
isAuthorizedRequest func(ctx context.Context, userId int32, authedWallet string) bool,
1816
conditions *AccessGate,
1917
track *GetTracksRow,
2018
user *FullUser,
2119
) bool {
22-
// No track? no access.
20+
fmt.Println("GetTrackAccess", myId, user.UserID)
21+
// No track? no access
2322
if track == nil || user == nil {
2423
return false
2524
}
2625

27-
// no conditions means open access
26+
// No conditions means open access
2827
if conditions == nil {
2928
return true
3029
}
3130

32-
// I always have access to my own content
33-
if authedUserId != 0 && authedUserId == myId {
34-
return true
31+
// No myId? no access. we need to know who you are if there are conditions.
32+
if myId == 0 {
33+
return false
3534
}
3635

37-
// If I was granted access to this track (manager, approved app, etc)
38-
// I should have access to it.
39-
if authedWallet != "" && isAuthorizedRequest(ctx, myId, authedWallet) {
36+
// You always have access to your own content
37+
if myId == user.UserID {
4038
return true
4139
}
4240

@@ -138,9 +136,6 @@ func (q *Queries) GetTrackAccess(
138136
func (q *Queries) GetPlaylistAccess(
139137
ctx context.Context,
140138
myId int32,
141-
authedUserId int32,
142-
authedWallet string,
143-
isAuthorizedRequest func(ctx context.Context, userId int32, authedWallet string) bool,
144139
conditions *AccessGate,
145140
playlist *GetPlaylistsRow,
146141
user *FullUser,
@@ -156,13 +151,7 @@ func (q *Queries) GetPlaylistAccess(
156151
}
157152

158153
// I always have access to my own content
159-
if authedUserId != 0 && authedUserId == myId {
160-
return true
161-
}
162-
163-
// If I was granted access to this playlist (manager, approved app, etc)
164-
// I should have access to it.
165-
if authedWallet != "" && isAuthorizedRequest(ctx, myId, authedWallet) {
154+
if myId != 0 && myId == user.UserID {
166155
return true
167156
}
168157

api/dbv1/full_playlists.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ import (
1010

1111
type FullPlaylistsParams struct {
1212
GetPlaylistsParams
13-
AuthedUserId int32
14-
AuthedWallet string
15-
IsAuthorizedRequest func(ctx context.Context, userId int32, authedWallet string) bool
1613
}
1714

1815
type FullPlaylist struct {
@@ -98,9 +95,6 @@ func (q *Queries) FullPlaylistsKeyed(ctx context.Context, arg FullPlaylistsParam
9895
streamAccess := q.GetPlaylistAccess(
9996
ctx,
10097
arg.MyID.(int32),
101-
arg.AuthedUserId,
102-
arg.AuthedWallet,
103-
arg.IsAuthorizedRequest,
10498
playlist.StreamConditions,
10599
&playlist,
106100
&user)

api/dbv1/full_tracks.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ import (
1212

1313
type FullTracksParams struct {
1414
GetTracksParams
15-
AuthedUserId int32
16-
AuthedWallet string
17-
IsAuthorizedRequest func(ctx context.Context, userId int32, authedWallet string) bool
1815
}
1916

2017
type FullTrack struct {
@@ -120,9 +117,6 @@ func (q *Queries) FullTracksKeyed(ctx context.Context, arg FullTracksParams) (ma
120117
downloadAccess := q.GetTrackAccess(
121118
ctx,
122119
arg.MyID.(int32),
123-
arg.AuthedUserId,
124-
arg.AuthedWallet,
125-
arg.IsAuthorizedRequest,
126120
downloadConditions,
127121
&track,
128122
&user,
@@ -132,9 +126,6 @@ func (q *Queries) FullTracksKeyed(ctx context.Context, arg FullTracksParams) (ma
132126
streamAccess := downloadAccess || q.GetTrackAccess(
133127
ctx,
134128
arg.MyID.(int32),
135-
arg.AuthedUserId,
136-
arg.AuthedWallet,
137-
arg.IsAuthorizedRequest,
138129
track.StreamConditions,
139130
&track,
140131
&user,

api/dbv1/parallel.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@ import (
77
)
88

99
type ParallelParams struct {
10-
UserIds []int32
11-
TrackIds []int32
12-
PlaylistIds []int32
13-
MyID int32
14-
AuthedUserId int32
15-
AuthedWallet string
16-
IsAuthorizedRequest func(ctx context.Context, userId int32, authedWallet string) bool
10+
UserIds []int32
11+
TrackIds []int32
12+
PlaylistIds []int32
13+
MyID int32
1714
}
1815

1916
type ParallelResult struct {
@@ -48,9 +45,6 @@ func (q *Queries) Parallel(ctx context.Context, arg ParallelParams) (*ParallelRe
4845
Ids: arg.TrackIds,
4946
MyID: arg.MyID,
5047
},
51-
AuthedUserId: arg.AuthedUserId,
52-
AuthedWallet: arg.AuthedWallet,
53-
IsAuthorizedRequest: arg.IsAuthorizedRequest,
5448
})
5549
return err
5650
})
@@ -64,9 +58,6 @@ func (q *Queries) Parallel(ctx context.Context, arg ParallelParams) (*ParallelRe
6458
Ids: arg.PlaylistIds,
6559
MyID: arg.MyID,
6660
},
67-
AuthedUserId: arg.AuthedUserId,
68-
AuthedWallet: arg.AuthedWallet,
69-
IsAuthorizedRequest: arg.IsAuthorizedRequest,
7061
})
7162
return err
7263
})

api/server_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func Test200UnAuthed(t *testing.T) {
160160
u += "?user_id=7eP5n"
161161
}
162162

163-
status, _ = testGet(t, u)
163+
status, _ = testGetWithWallet(t, u, "0x7d273271690538cf855e5b3002a0dd8c154bb060")
164164
require.Equal(t, 200, status, u+" "+string(body))
165165
}
166166
}

api/testdata/signatures.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ var TestSignatures = map[string]SignatureData{
1212
Message: "signature:1744763856446",
1313
Signature: "0xbb202be3a7f3a0aa22c1458ef6a3f2f8360fb86791c7b137e8562df0707825c11fa1db01096efd2abc5e6613c4d1e8d4ae1e2b993abdd555fe270c1b17bff0d21c",
1414
},
15+
"0xc3d1d41e6872ffbd15c473d14fc3a9250be5b5e0": {
16+
Message: "signature:1746224298871",
17+
Signature: "0x00cc53200e1ee98248cd5556293e4a7ec70bfcde2a1e8e7aedbff471ac0ca8a0354d50e9bc62fbe32ad1d48dfe414ea99711030e88ba788e5bc607fef6c295311b",
18+
},
19+
"0x4954d18926ba0ed9378938444731be4e622537b2": {
20+
Message: "signature:1746226663660",
21+
Signature: "0x8035c0154bc68de4c0e57bfe8b2adc880f04c0754c32677f895f63a15d2b5cb5720f89b5cc9acf079e3058485b10d50ae83a6b2f19080aeafb46890b43e297c51c",
22+
},
23+
"0x855d28d495ec1b06364bb7a521212753e2190b95": {
24+
Message: "signature:1746226936204",
25+
Signature: "0xc2f6fd9c5837b481ac1ee3339a8a83267b36af5a53262d78b759fc810fa814ed0dee8e62a9b911e32b4586ca38f890f31fe83be24fe44f32c9b07d13d1906b2f1b",
26+
},
1527
}
1628

1729
// GetSignatureData returns the message and signature for a given test wallet address

api/testdata/user_fixtures.csv

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
user_id,handle,handle_lc,is_deactivated,wallet,playlist_library
22
1,rayjacobson,rayjacobson,f,0x7d273271690538cf855e5b3002a0dd8c154bb060,"{""contents"":[{""type"":""playlist"",""playlist_id"":""123""},{""type"":""explore_playlist"",""playlist_id"":""Audio NFTs""},{""type"":""folder"",""id"":""bbcae31a-7cd2-4a1a-8b54-fdc979a34435"",""name"":""My Nested Playlists"",""contents"":[{""type"":""playlist"",""playlist_id"":""345""}]}]}"
33
2,stereosteve,stereosteve,f,0x1234567890abcdef,
4-
3,someseller,someseller,f,0x234567890abcdef1,
5-
4,accesstester,accesstester,f,0x34567890abcdef12,
4+
3,someseller,someseller,f,0xc3d1d41e6872ffbd15c473d14fc3a9250be5b5e0,
5+
4,accesstester,accesstester,f,0x4954d18926ba0ed9378938444731be4e622537b2,
66
5,guyintrending,guyintrending,f,0x34567890abcdef13,
77
6,TracksByPermalink,tracksbypermalink,f,0xffffffffff,
88
7,PlaylistsByPermalink,playlistsbypermalink,f,0xffffffffff,
99
8,AlbumsByPermalink,albumsbypermalink,f,0xffffffffff,
10+
11,somebuyer,somebuyer,f,0x855d28d495ec1b06364bb7a521212753e2190b95,
1011
91,badguy,badguy,t,0x4567890abcdef123,
1112
100,authtest1,authtest1,f,0x681c616ae836ceca1effe00bd07f2fdbf9a082bc,
1213
101,authtest2,authtest2,f,0xc451c1f8943b575158310552b41230c61844a1c1,

0 commit comments

Comments
 (0)