mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-10-21 00:59:04 +02:00
fix: ignore trailing slash in resources
This commit is contained in:
@@ -88,6 +88,9 @@ func (s *Service) Get(ctx context.Context, tx *gorm.DB, id string) (api API, err
|
||||
}
|
||||
|
||||
func (s *Service) Create(ctx context.Context, input apiCreateDto) (api API, err error) {
|
||||
// Store one canonical resource identifier so trailing-slash variants cannot create separate audiences
|
||||
input.Resource = strings.TrimRight(input.Resource, "/")
|
||||
|
||||
// Reject the issuer as an audience so a custom API cannot impersonate Pocket ID's own identity tokens
|
||||
if isIssuerAudience(input.Resource, s.issuer) {
|
||||
return API{}, apperror.InvalidField("resource", "reserved", "is reserved by Pocket ID and cannot be used for a custom API")
|
||||
@@ -443,6 +446,9 @@ func (s *Service) DescribePermissions(ctx context.Context, audience string, keys
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Match scope information against the same canonical audience used during resource resolution
|
||||
audience = strings.TrimRight(audience, "/")
|
||||
|
||||
var permissions []Permission
|
||||
err := s.db.WithContext(ctx).
|
||||
Model(&Permission{}).
|
||||
|
||||
@@ -250,6 +250,19 @@ func TestCreateAcceptsAbsoluteResourceURIs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateTrimsResourceTrailingSlashes(t *testing.T) {
|
||||
db := testutils.NewDatabaseForTest(t)
|
||||
svc := New(Dependencies{DB: db}).service
|
||||
|
||||
created, err := svc.Create(t.Context(), apiCreateDto{Name: "Orders", Resource: "https://api.orders.example.com///"})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "https://api.orders.example.com", created.Audience)
|
||||
|
||||
// A trailing-slash variant must conflict with the canonical resource instead of creating a second audience
|
||||
_, err = svc.Create(t.Context(), apiCreateDto{Name: "Duplicate", Resource: "https://api.orders.example.com/"})
|
||||
require.True(t, apperror.IsCode(err, apperror.CodeAlreadyInUse))
|
||||
}
|
||||
|
||||
func TestDescribePermissions(t *testing.T) {
|
||||
db := testutils.NewDatabaseForTest(t)
|
||||
svc := New(Dependencies{DB: db}).service
|
||||
@@ -263,7 +276,7 @@ func TestDescribePermissions(t *testing.T) {
|
||||
}})
|
||||
require.NoError(t, err)
|
||||
|
||||
infos, err := svc.DescribePermissions(t.Context(), "https://api.orders.example.com", []string{"read:orders", "unknown"})
|
||||
infos, err := svc.DescribePermissions(t.Context(), "https://api.orders.example.com/", []string{"read:orders", "unknown"})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, infos, 1)
|
||||
assert.Equal(t, "read:orders", infos[0].Key)
|
||||
|
||||
Reference in New Issue
Block a user