Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor code #2727

Merged
merged 1 commit into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions gateway/enforcer/internal/authorization/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,14 @@ import (

// Validate performs the authorization.
func Validate(rch *requestconfig.Holder, subAppDataStore *datastore.SubscriptionApplicationDataStore, cfg *config.Server) *dto.ImmediateResponse {
if immediateResponse := ValidateScopes(*rch.JWTValidationInfo.Scopes, rch.MatchedResource.Scopes, rch.MatchedResource.Path); immediateResponse != nil {
if immediateResponse := ValidateScopes(rch, subAppDataStore, cfg); immediateResponse != nil {
return immediateResponse
}
cfg.Logger.Info(fmt.Sprintf("Scope validation successful for the request: %s", rch.MatchedResource.Path))
if rch.MatchedAPI.SubscriptionValidation {
appID := rch.ExternalProcessingEnvoyAttributes.ApplicationID
if appID == "" && rch.JWTValidationInfo.ClientID != "" {
appID = getAppIDUsingConsumerKey(rch.JWTValidationInfo.ClientID, subAppDataStore, rch.MatchedAPI, "")
} else {
return &dto.ImmediateResponse{
StatusCode: 403,
Message: "Application ID not found",
}
}
return validateSubscription(appID, subAppDataStore, rch)
if immediateResponse := ValidateSubscription(rch, subAppDataStore, cfg); immediateResponse != nil {
return immediateResponse
}
cfg.Logger.Info(fmt.Sprintf("Subscription validation successful for the request: %s", rch.MatchedResource.Path))

return nil
}
34 changes: 24 additions & 10 deletions gateway/enforcer/internal/authorization/scope_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,40 @@ package authorization

import (
"fmt"

"github.com/wso2/apk/gateway/enforcer/internal/config"
"github.com/wso2/apk/gateway/enforcer/internal/datastore"
"github.com/wso2/apk/gateway/enforcer/internal/dto"
"github.com/wso2/apk/gateway/enforcer/internal/requestconfig"
)

// ValidateScopes validates the scopes of the user against the required scopes.
func ValidateScopes(scopes []string, requiredScopes []string, path string) *dto.ImmediateResponse {
for _, requiredScope := range requiredScopes {
found := false
for _, scope := range scopes {
func ValidateScopes(rch *requestconfig.Holder, subAppDataStore *datastore.SubscriptionApplicationDataStore, cfg *config.Server) *dto.ImmediateResponse {
requiredScopes := rch.MatchedResource.Scopes
scopes := rch.JWTValidationInfo.Scopes
if len(requiredScopes) == 0 {
return nil
}
if len(scopes) == 0 {
return &dto.ImmediateResponse{
StatusCode: 403,
Message: fmt.Sprintf("User is NOT authorized to access the Resource: %s. Scope validation failed.", rch.MatchedResource.Path),
}
}
found := false
for requiredScope := range requiredScopes {
for scope := range scopes {
if requiredScope == scope {
found = true
break
}
}
if !found {
return &dto.ImmediateResponse{
StatusCode: 403,
Message: fmt.Sprintf("User is NOT authorized to access the Resource: %s. Scope validation failed.", path),
}
}
if !found {
return &dto.ImmediateResponse{
StatusCode: 403,
Message: fmt.Sprintf("User is NOT authorized to access the Resource: %s. Scope validation failed.", rch.MatchedResource.Path),
}
}
return nil
}

47 changes: 28 additions & 19 deletions gateway/enforcer/internal/authorization/subscription.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package authorization

import (
"github.com/wso2/apk/gateway/enforcer/internal/config"
"github.com/wso2/apk/gateway/enforcer/internal/datastore"
"github.com/wso2/apk/gateway/enforcer/internal/dto"
"github.com/wso2/apk/gateway/enforcer/internal/requestconfig"
Expand All @@ -11,33 +12,41 @@ const (
forbiddenMessage = "Resource forbidden"
)

// validateSubscription validates the subscription.
func validateSubscription(appID string, subAppDatastore *datastore.SubscriptionApplicationDataStore, rch *requestconfig.Holder) *dto.ImmediateResponse{
// ValidateSubscription validates the subscription.
func ValidateSubscription(rch *requestconfig.Holder, subAppDataStore *datastore.SubscriptionApplicationDataStore, cfg *config.Server) *dto.ImmediateResponse {
api := rch.MatchedAPI
appMaps := subAppDatastore.GetApplicationMappings(api.OrganizationID, appID)
for _, appMap := range appMaps {
subscriptions := subAppDatastore.GetSubscriptions(api.OrganizationID, appMap.SubscriptionRef)
for _, subscription := range subscriptions {
subscribedAPI := subscription.SubscribedAPI
if subscribedAPI.Name == api.Name && subscribedAPI.Version == api.Version {
rch.MatchedSubscription = subscription
rch.MatchedApplication = subAppDatastore.GetApplication(api.OrganizationID, appID)
return nil
clientID := rch.JWTValidationInfo.ClientID
if rch.MatchedAPI.SubscriptionValidation {
if rch.JWTValidationInfo.ClientID != "" {
appID := getAppIDUsingConsumerKey(clientID, subAppDataStore, api, "oauth2")
if appID != "" {
appMaps := subAppDataStore.GetApplicationMappings(api.OrganizationID, appID)
for _, appMap := range appMaps {
subscriptions := subAppDataStore.GetSubscriptions(api.OrganizationID, appMap.SubscriptionRef)
for _, subscription := range subscriptions {
subscribedAPI := subscription.SubscribedAPI
if subscribedAPI.Name == api.Name && subscribedAPI.Version == api.Version {
rch.MatchedSubscription = subscription
rch.MatchedApplication = subAppDataStore.GetApplication(api.OrganizationID, appID)
return nil
}
}
}
}
}

}
return &dto.ImmediateResponse{
StatusCode: 403,
Message: forbiddenMessage,
return &dto.ImmediateResponse{
StatusCode: 403,
Message: forbiddenMessage,
}
}
return nil
}

func getAppIDUsingConsumerKey(consumerKey string, subAppDatastore *datastore.SubscriptionApplicationDataStore, api *requestconfig.API, securityScheme string) string {
appKeyMapKey := util.PrepareApplicationKeyMappingCacheKey(consumerKey, api.EnvType, securityScheme, api.Environment)
appKeyMap := subAppDatastore.GetApplicationKeyMapping(api.OrganizationID,appKeyMapKey)
appKeyMapKey := util.PrepareApplicationKeyMappingCacheKey(consumerKey, api.EnvType, securityScheme, api.Environment)
appKeyMap := subAppDatastore.GetApplicationKeyMapping(api.OrganizationID, appKeyMapKey)
if appKeyMap != nil {
return appKeyMap.ApplicationIdentifier
}
return ""
}
}
4 changes: 2 additions & 2 deletions gateway/enforcer/internal/dto/jwt_validation_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type JWTValidationInfo struct {
Issuer string `json:"issuer"` // Issuer
ClientID string `json:"clientId"` // Client ID
Subject string `json:"subject"` // Subject
Audiences *[]string `json:"audiences"` // Audiences
Scopes *[]string `json:"scopes"` // Scopes
Audiences []string `json:"audiences"` // Audiences
Scopes []string `json:"scopes"` // Scopes
Claims map[string]interface{} `json:"claims"` // Claims
}
8 changes: 4 additions & 4 deletions gateway/enforcer/internal/transformer/jwtTransformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ func (transformer *JWTTransformer) TransformJWTClaims(organization string, exter
switch audienceClaim.(type) {
case string:
audiences := []string{remoteClaims["aud"].(string)}
jwtValidationInfo.Audiences = &audiences
jwtValidationInfo.Audiences = audiences
case []string:
audiences := remoteClaims["aud"].([]string)
jwtValidationInfo.Audiences = &audiences
jwtValidationInfo.Audiences = audiences
}
}
remoteScopes := remoteClaims[tokenIssuer.ScopesClaim]
Expand All @@ -59,10 +59,10 @@ func (transformer *JWTTransformer) TransformJWTClaims(organization string, exter
switch remoteScopes := remoteScopes.(type) {
case string:
scopes := []string{remoteScopes}
jwtValidationInfo.Scopes = &scopes
jwtValidationInfo.Scopes = scopes
case []string:
scopes := remoteScopes
jwtValidationInfo.Scopes = &scopes
jwtValidationInfo.Scopes = scopes
}
}
remoteClientID := remoteClaims[tokenIssuer.ConsumerKeyClaim]
Expand Down