plugins/wasm-go/extensions/oidc/main.go (100 lines of code) (raw):

package main import ( "fmt" "net/http" "net/url" "strings" oidc "github.com/higress-group/oauth2-proxy" "github.com/higress-group/oauth2-proxy/pkg/apis/options" "github.com/higress-group/oauth2-proxy/pkg/util" "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper" "github.com/higress-group/proxy-wasm-go-sdk/proxywasm" "github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types" "github.com/tidwall/gjson" ) func main() { wrapper.SetCtx( // 插件名称 "oidc", // 为解析插件配置,设置自定义函数 wrapper.ParseConfigBy(parseConfig), // 为处理请求头,设置自定义函数 wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders), // 为处理响应头,设置自定义函数 wrapper.ProcessResponseHeadersBy(onHttpResponseHeaders), ) } type PluginConfig struct { oidcHandler *oidc.OAuthProxy options *options.Options } // 在控制台插件配置中填写的yaml配置会自动转换为json,此处直接从json这个参数里解析配置即可 func parseConfig(json gjson.Result, config *PluginConfig, log wrapper.Log) error { oidc.SetLogger(log) opts, err := oidc.LoadOptions(json) if err != nil { return err } opts.Providers[0].Scope = strings.Replace(opts.Providers[0].Scope, ";", " ", -1) config.options = opts config.oidcHandler, err = oidc.NewOAuthProxy(opts) if err != nil { return err } wrapper.RegisteTickFunc(opts.VerifierInterval.Milliseconds(), func() { config.oidcHandler.SetVerifier(opts) }) return nil } func onHttpRequestHeaders(ctx wrapper.HttpContext, config PluginConfig, log wrapper.Log) types.Action { config.oidcHandler.SetContext(ctx) req := getHttpRequest() rw := util.NewRecorder() if options.IsAllowedByMode(req.URL.Host, req.URL.Path, config.options.MatchRules, config.options.ProxyPrefix) { log.Infof("request is allowed by mode %s", config.options.MatchRules.Mode) return types.ActionContinue } // TODO: remove this verifier after envoy support send request during parseConfig if err := config.oidcHandler.ValidateVerifier(); err != nil { log.Critical(err.Error()) return types.ActionContinue } config.oidcHandler.ServeHTTP(rw, req) if code := rw.GetStatus(); code != 0 { return types.ActionContinue } return types.ActionPause } func onHttpResponseHeaders(ctx wrapper.HttpContext, config PluginConfig, log wrapper.Log) types.Action { value := ctx.GetContext(oidc.SetCookieHeader) if value != nil { proxywasm.AddHttpResponseHeader(oidc.SetCookieHeader, value.(string)) } config.oidcHandler.SetContext(nil) return types.ActionContinue } func getHttpRequest() *http.Request { headers, _ := proxywasm.GetHttpRequestHeaders() var method, path, authority, scheme string for _, header := range headers { switch header[0] { case ":method": method = header[1] case ":path": path = header[1] case ":authority": authority = header[1] case ":scheme": scheme = header[1] } } rawURL := fmt.Sprintf("%s://%s%s", scheme, authority, path) parsedURL, _ := url.Parse(rawURL) req := &http.Request{ Method: method, URL: parsedURL, Header: make(http.Header), Body: nil, } req.Form, _ = url.ParseQuery(parsedURL.RawQuery) for _, header := range headers { if !strings.HasPrefix(header[0], ":") { req.Header.Add(header[0], header[1]) } } return req }