mirror of
https://github.com/wso2/open-mcp-auth-proxy.git
synced 2025-06-29 01:44:19 +00:00
Update scope validation implementation
This commit is contained in:
parent
5c22f36ddc
commit
64caaa0f7c
7 changed files with 202 additions and 138 deletions
|
@ -4,54 +4,68 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type TokenClaims struct {
|
||||
Scopes []string
|
||||
}
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/wso2/open-mcp-auth-proxy/internal/config"
|
||||
"github.com/wso2/open-mcp-auth-proxy/internal/util"
|
||||
)
|
||||
|
||||
type ScopeValidator struct{}
|
||||
|
||||
// Evaluate and checks the token claims against one or more required scopes.
|
||||
func (d *ScopeValidator) ValidateAccess(
|
||||
_ *http.Request,
|
||||
claims *TokenClaims,
|
||||
requiredScopes any,
|
||||
r *http.Request,
|
||||
claims *jwt.MapClaims,
|
||||
config *config.Config,
|
||||
) AccessControlResult {
|
||||
var scopeStr string
|
||||
switch v := requiredScopes.(type) {
|
||||
case string:
|
||||
scopeStr = v
|
||||
case []string:
|
||||
scopeStr = strings.Join(v, " ")
|
||||
env, err := util.ParseRPCRequest(r)
|
||||
if err != nil {
|
||||
return AccessControlResult{DecisionDeny, "bad JSON-RPC request"}
|
||||
}
|
||||
requiredScopes := util.GetRequiredScopes(config, env.Method)
|
||||
if len(requiredScopes) == 0 {
|
||||
return AccessControlResult{DecisionAllow, ""}
|
||||
}
|
||||
|
||||
required := make(map[string]struct{}, len(requiredScopes))
|
||||
for _, s := range requiredScopes {
|
||||
s = strings.TrimSpace(s)
|
||||
if s != "" {
|
||||
required[s] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
var tokenScopes []string
|
||||
if claims, ok := (*claims)["scope"]; ok {
|
||||
switch v := claims.(type) {
|
||||
case string:
|
||||
tokenScopes = strings.Fields(v)
|
||||
case []interface{}:
|
||||
for _, x := range v {
|
||||
if s, ok := x.(string); ok && s != "" {
|
||||
tokenScopes = append(tokenScopes, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokenScopeSet := make(map[string]struct{}, len(tokenScopes))
|
||||
for _, s := range tokenScopes {
|
||||
tokenScopeSet[s] = struct{}{}
|
||||
}
|
||||
|
||||
if strings.TrimSpace(scopeStr) == "" {
|
||||
return AccessControlResult{DecisionAllow, ""}
|
||||
}
|
||||
|
||||
scopes := strings.FieldsFunc(scopeStr, func(r rune) bool {
|
||||
return r == ' ' || r == ','
|
||||
})
|
||||
required := make(map[string]struct{}, len(scopes))
|
||||
for _, s := range scopes {
|
||||
if s = strings.TrimSpace(s); s != "" {
|
||||
required[s] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for _, tokenScope := range claims.Scopes {
|
||||
if _, ok := required[tokenScope]; ok {
|
||||
return AccessControlResult{DecisionAllow, ""}
|
||||
}
|
||||
}
|
||||
|
||||
var list []string
|
||||
var missing []string
|
||||
for s := range required {
|
||||
list = append(list, s)
|
||||
if _, ok := tokenScopeSet[s]; !ok {
|
||||
missing = append(missing, s)
|
||||
}
|
||||
}
|
||||
|
||||
if len(missing) == 0 {
|
||||
return AccessControlResult{DecisionAllow, ""}
|
||||
}
|
||||
return AccessControlResult{
|
||||
DecisionDeny,
|
||||
fmt.Sprintf("missing required scope(s): %s", strings.Join(list, ", ")),
|
||||
fmt.Sprintf("missing required scope(s): %s", strings.Join(missing, ", ")),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue