package identityprovider import ( "errors" "net/url" "strings" "vpn-platform/backend/internal/model" "vpn-platform/backend/internal/service" "vpn-platform/backend/internal/store" ) // builtinTunnel finds the one tunnel whose OAuth callback owns this redirect. // Ambiguous or missing routes fail closed; a browser redirect alone grants nothing. func builtinTunnel(redirect, base string, cfg model.IdentityProvider) (model.Tunnel, map[string]interface{}, error) { u, err := url.Parse(redirect) if err != nil || u.RawQuery != "" || u.Fragment != "" || u.Path != "/oauth2/callback" { return model.Tunnel{}, nil, errors.New("unknown callback") } var tunnels []model.Tunnel if err := store.DB.Where("protocol = ?", "openvpn").Find(&tunnels).Error; err != nil { return model.Tunnel{}, nil, err } var match model.Tunnel var config map[string]interface{} for _, tunnel := range tunnels { data, err := store.TunnelConfig(&tunnel) if err != nil { return model.Tunnel{}, nil, err } if service.Str(data, "auth_mode") != "oidc" || service.Str(data, "oidc_provider") != "builtin" || service.Str(data, "oidc_issuer") != base || service.Str(data, "oidc_client_id") != cfg.ClientID || strings.TrimRight(service.Str(data, "oidc_base_url"), "/")+"/oauth2/callback" != redirect { continue } if match.ID != 0 { return model.Tunnel{}, nil, errors.New("ambiguous callback") } match, config = tunnel, data } if match.ID == 0 { return model.Tunnel{}, nil, errors.New("unknown callback") } return match, config, nil } func admitted(redirect, base string, cfg model.IdentityProvider, subject string) (bool, error) { tunnel, config, err := builtinTunnel(redirect, base, cfg) if err != nil { return false, err } if raw, present := config["feishu_access_mode"]; present { if _, ok := raw.(string); !ok { return false, errors.New("invalid admission mode") } } switch service.Str(config, "feishu_access_mode") { case "", "all": return true, nil case "allowlist": var count int64 err := store.DB.Model(&model.FeishuTunnelGrant{}).Where("tunnel_id = ? AND issuer = ? AND app_id = ? AND subject = ?", tunnel.ID, base, cfg.AppID, subject).Count(&count).Error return err == nil && count == 1, err default: return false, errors.New("invalid admission mode") } }