Skip to content

Commit

Permalink
fix get teannts with descope tenants claim (#439)
Browse files Browse the repository at this point in the history
  • Loading branch information
asafshen authored Jul 3, 2024
1 parent aaec8ed commit 51e8227
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 23 deletions.
10 changes: 6 additions & 4 deletions descope/internal/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -827,13 +827,15 @@ func getAuthorizationClaimItems(token *descope.Token, tenant string, claim strin
}
} else {
var claimValue []interface{}
if token.Claims[claimDescopeCurrentTenant] == tenant && len(token.GetTenants()) == 0 {
if v, ok := token.GetTenantValue(tenant, claim).([]interface{}); ok {
claimValue = v
} else if token.Claims[descope.ClaimDescopeCurrentTenant] == tenant && token.Claims[descope.ClaimAuthorizedTenants] == nil {
// The token may have the current tenant in the "dct" claim and without the "tenants" claim
// Note: We also must ensure that the tenants claim is not present because in the if "tenants" claim exists,
// the top level claim represents for the project level roles/permissions
if v, ok := token.Claims[claim].([]interface{}); ok {
claimValue = v
}
} else if v, ok := token.GetTenantValue(tenant, claim).([]interface{}); ok {
claimValue = v
}

for i := range claimValue {
Expand All @@ -852,7 +854,7 @@ func getAuthorizationClaimItems(token *descope.Token, tenant string, claim strin
}

func isAssociatedWithTenant(token *descope.Token, tenant string) bool {
return slices.Contains(token.GetTenants(), tenant) || (token.Claims != nil && token.Claims[claimDescopeCurrentTenant] == tenant)
return slices.Contains(token.GetTenants(), tenant) || (token.Claims != nil && token.Claims[descope.ClaimDescopeCurrentTenant] == tenant)
}

func getPendingRefFromResponse(httpResponse *api.HTTPResponse) (*descope.EnchantedLinkResponse, error) {
Expand Down
60 changes: 46 additions & 14 deletions descope/internal/auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,24 @@ var (
},
},
}
mockAuthorizationCurrentTenantToken = &descope.Token{
mockAuthorizationCurrentTenantTokenNoTenants = &descope.Token{
Claims: map[string]any{
claimPermissions: permissions,
claimRoles: roles,
claimDescopeCurrentTenant: "t1",
claimPermissions: permissions,
claimRoles: roles,
descope.ClaimDescopeCurrentTenant: "t1",
},
}
mockAuthorizationCurrentTenantTokenWithTenants = &descope.Token{
Claims: map[string]any{
claimPermissions: permissions,
claimRoles: roles,
descope.ClaimAuthorizedTenants: map[string]any{
"t1": map[string]any{
claimPermissions: []interface{}{"t1-perm1", "t1-perm2"},
claimRoles: []interface{}{"t1-role1", "t1-role2"},
},
"t2": map[string]any{},
},
},
}
)
Expand Down Expand Up @@ -1030,9 +1043,12 @@ func TestValidatePermissions(t *testing.T) {
require.True(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationTenantToken, "t1", []string{}))
require.False(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationTenantToken, "t2", []string{}))

require.True(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationCurrentTenantToken, "t1", []string{"foo"}))
require.False(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationCurrentTenantToken, "t1", []string{"qux"}))
require.False(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationCurrentTenantToken, "t2", []string{"foo"}))
require.True(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t1", []string{"foo"}))
require.False(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t1", []string{"qux"}))
require.False(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t2", []string{"foo"}))

require.True(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenWithTenants, "t1", []string{"t1-perm1"}))
require.False(t, a.ValidateTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenWithTenants, "t1", []string{"foo"}))

// check when the value of the claim is not a map
require.False(t, a.ValidateTenantPermissions(
Expand Down Expand Up @@ -1062,8 +1078,11 @@ func TestGetMatchedPermissions(t *testing.T) {
require.Equal(t, []string{"foo", "bar"}, a.GetMatchedTenantPermissions(context.Background(), mockAuthorizationTenantToken, "kuku", []string{"foo", "bar"}))
require.Equal(t, []string{"foo", "bar"}, a.GetMatchedTenantPermissions(context.Background(), mockAuthorizationTenantToken, "kuku", []string{"foo", "bar", "qux"}))

require.Equal(t, []string{"foo", "bar"}, a.GetMatchedTenantPermissions(context.Background(), mockAuthorizationCurrentTenantToken, "t1", []string{"foo", "bar", "qux"}))
require.Equal(t, []string{}, a.GetMatchedTenantPermissions(context.Background(), mockAuthorizationCurrentTenantToken, "t2", []string{"foo", "bar", "qux"}))
require.Equal(t, []string{"foo", "bar"}, a.GetMatchedTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t1", []string{"foo", "bar", "qux"}))
require.Equal(t, []string{}, a.GetMatchedTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t2", []string{"foo", "bar", "qux"}))

require.Equal(t, []string{"t1-perm1"}, a.GetMatchedTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenWithTenants, "t1", []string{"t1-perm1"}))
require.Equal(t, []string{}, a.GetMatchedTenantPermissions(context.Background(), mockAuthorizationCurrentTenantTokenWithTenants, "t1", []string{"foo"}))
}

func TestValidateRoles(t *testing.T) {
Expand Down Expand Up @@ -1096,9 +1115,12 @@ func TestValidateRoles(t *testing.T) {
require.True(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationTenantToken, "t1", []string{}))
require.False(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationTenantToken, "t2", []string{}))

require.True(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationCurrentTenantToken, "t1", []string{"abc"}))
require.False(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationCurrentTenantToken, "t1", []string{"tuv"}))
require.False(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationCurrentTenantToken, "t2", []string{"abc"}))
require.True(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t1", []string{"abc"}))
require.False(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t1", []string{"tuv"}))
require.False(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t2", []string{"abc"}))

require.True(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenWithTenants, "t1", []string{"t1-role1"}))
require.False(t, a.ValidateTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenWithTenants, "t1", []string{"abc"}))
}

func TestGetMatchedRoles(t *testing.T) {
Expand All @@ -1118,8 +1140,18 @@ func TestGetMatchedRoles(t *testing.T) {
require.Equal(t, []string{"abc", "xyz"}, a.GetMatchedTenantRoles(context.Background(), mockAuthorizationTenantToken, "kuku", []string{"abc", "xyz"}))
require.Equal(t, []string{"abc", "xyz"}, a.GetMatchedTenantRoles(context.Background(), mockAuthorizationTenantToken, "kuku", []string{"abc", "xyz", "tuv"}))

require.Equal(t, []string{"abc", "xyz"}, a.GetMatchedTenantRoles(context.Background(), mockAuthorizationCurrentTenantToken, "t1", []string{"abc", "xyz", "tuv"}))
require.Equal(t, []string{}, a.GetMatchedTenantRoles(context.Background(), mockAuthorizationCurrentTenantToken, "t2", []string{"abc", "xyz", "tuv"}))
require.Equal(t, []string{"abc", "xyz"}, a.GetMatchedTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t1", []string{"abc", "xyz", "tuv"}))
require.Equal(t, []string{}, a.GetMatchedTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenNoTenants, "t2", []string{"abc", "xyz", "tuv"}))

require.Equal(t, []string{"t1-role1"}, a.GetMatchedTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenWithTenants, "t1", []string{"t1-role1"}))
require.Equal(t, []string{}, a.GetMatchedTenantRoles(context.Background(), mockAuthorizationCurrentTenantTokenWithTenants, "t1", []string{"abc"}))
}

func TestGetTenants(t *testing.T) {
require.Equal(t, []string{}, mockAuthorizationToken.GetTenants())
require.Equal(t, []string{"t1"}, mockAuthorizationCurrentTenantTokenNoTenants.GetTenants())
require.ElementsMatch(t, []string{"kuku", "t1"}, mockAuthorizationTenantToken.GetTenants())
require.ElementsMatch(t, []string{"t1", "t2"}, mockAuthorizationCurrentTenantTokenWithTenants.GetTenants())
}

func TestMe(t *testing.T) {
Expand Down
7 changes: 3 additions & 4 deletions descope/internal/auth/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,9 @@ func newExchangeAccessKeyBody(loginOptions *descope.AccessKeyLoginOptions) *exch
}

const (
claimAttributeName = "drn"
claimPermissions = "permissions"
claimRoles = "roles"
claimDescopeCurrentTenant = "dct"
claimAttributeName = "drn"
claimPermissions = "permissions"
claimRoles = "roles"
)

var (
Expand Down
7 changes: 7 additions & 0 deletions descope/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ type Token struct {

func (to *Token) GetTenants() []string {
tenants := to.getTenants()
if len(tenants) == 0 && to.Claims != nil && to.Claims[ClaimDescopeCurrentTenant] != nil {
return []string{to.Claims[ClaimDescopeCurrentTenant].(string)}
}
return maps.Keys(tenants)
}

Expand Down Expand Up @@ -224,6 +227,9 @@ func (to *Token) IsPermitted(permission string) bool {
func (to *Token) IsPermittedPerTenant(tenant string, permission string) bool {
permitted := false
tenants := to.getTenants()
if to.Claims[ClaimDescopeCurrentTenant] == tenant && len(tenants) == 0 {
return to.IsPermitted(permission)
}
tPermissions, ok := tenants[tenant]
if ok {
if tPermissionsMap, ok := tPermissions.(map[string]any); ok {
Expand Down Expand Up @@ -930,6 +936,7 @@ const (
ContextUserIDPropertyKey ContextKey = ContextUserIDProperty
ClaimAuthorizedTenants = "tenants"
ClaimAuthorizedGlobalPermissions = "permissions"
ClaimDescopeCurrentTenant = "dct"

EnvironmentVariableProjectID = "DESCOPE_PROJECT_ID"
EnvironmentVariablePublicKey = "DESCOPE_PUBLIC_KEY"
Expand Down
16 changes: 15 additions & 1 deletion descope/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestGetCreatedTime(t *testing.T) {
assert.True(t, r.GetCreatedTime().Equal(now))
}

func TestIsPermittedPerTenant(t *testing.T) {
func TestIsPermittedPerTenantFromTenantsClaim(t *testing.T) {
tenantID := "somestring"
dt := &Token{
Claims: map[string]any{
Expand All @@ -111,6 +111,20 @@ func TestIsPermittedPerTenant(t *testing.T) {
assert.False(t, p)
}

func TestIsPermittedPerTenantWithCurrentTenant(t *testing.T) {
tenantID := "t1"
dt := &Token{
Claims: map[string]any{
ClaimDescopeCurrentTenant: tenantID,
ClaimAuthorizedGlobalPermissions: []any{"a", "b", "c"},
},
}
p := dt.IsPermittedPerTenant(tenantID, "a")
assert.True(t, p)
p = dt.IsPermittedPerTenant(tenantID, "d")
assert.False(t, p)
}

func TestIsPermitted(t *testing.T) {
dt := &Token{
Claims: map[string]any{
Expand Down

0 comments on commit 51e8227

Please sign in to comment.