{"record":{"id":"2768f9967ac20411","repo":"argoproj/argo-workflows","slug":"oidc-end-session-endpoint-must-be-an-absolute-http","errorCode":null,"errorMessage":"oidc end-session endpoint must be an absolute HTTP(S) URL without user info or a fragment: %q","messagePattern":"oidc end-session endpoint must be an absolute HTTP\\(S\\) URL without user info or a fragment: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/logout/logout.go","lineNumber":66,"sourceCode":"}\n\nfunc parseAbsoluteHTTPURL(rawURL string) (*url.URL, bool) {\n\tparsedURL, err := url.Parse(rawURL)\n\tif err != nil || parsedURL.Hostname() == \"\" || parsedURL.User != nil || parsedURL.Fragment != \"\" ||\n\t\t(!strings.EqualFold(parsedURL.Scheme, \"http\") && !strings.EqualFold(parsedURL.Scheme, \"https\")) {\n\t\treturn nil, false\n\t}\n\treturn parsedURL, true\n}\n\nfunc constructLogoutURL(logoutURL, clientID, redirectURL string) (string, error) {\n\tif logoutURL == \"\" {\n\t\treturn redirectURL, nil\n\t}\n\n\tparsedURL, ok := parseAbsoluteHTTPURL(logoutURL)\n\tif !ok {\n\t\treturn redirectURL, fmt.Errorf(\"oidc end-session endpoint must be an absolute HTTP(S) URL without user info or a fragment: %q\", logoutURL)\n\t}\n\n\tquery := parsedURL.Query()\n\tif clientID != \"\" {\n\t\tquery.Set(\"client_id\", clientID)\n\t}\n\tif redirectURL != \"\" {\n\t\tquery.Set(\"post_logout_redirect_uri\", redirectURL)\n\t}\n\tparsedURL.RawQuery = query.Encode()\n\treturn parsedURL.String(), nil\n}\n\nfunc (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tif r.Method != http.MethodGet && r.Method != http.MethodHead {\n\t\tw.Header().Set(\"Allow\", http.MethodGet+\", \"+http.MethodHead)\n\t\tw.WriteHeader(http.StatusMethodNotAllowed)\n\t\treturn","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/logout/logout.go#L48-L84","documentation":"constructLogoutURL builds the OIDC provider end-session URL used during logout. If the configured end-session endpoint is non-empty but not an absolute HTTP(S) URL without userinfo/fragment, logout falls back to the plain redirect URL and returns this error. It ensures the server only redirects to well-formed provider endpoints.","triggerScenarios":"OIDC issuer discovery or explicit configuration yields an end_session_endpoint value that is empty-schemed, relative, contains userinfo, or has a fragment, and a user performs logout on the Argo UI.","commonSituations":"Misconfigured OIDC provider metadata, hand-written endSessionEndpoint in the SSO configmap with a typo, or an issuer URL missing its scheme.","solutions":["Fix the OIDC end-session endpoint in the argo SSO configmap to a full https:// URL","Verify the issuer metadata (.well-known/openid-configuration) publishes a valid absolute end_session_endpoint","Remove any fragment or userinfo from the endpoint"],"exampleFix":"// before (argo-cm sso config)\nendSessionEndpoint: /oidc/logout\n// after\nendSessionEndpoint: https://sso.example.com/oidc/logout","handlingStrategy":"validation","validationCode":"u, err := url.Parse(ssoCfg.EndSessionEndpoint)\nif ssoCfg.EndSessionEndpoint != \"\" && (err != nil || (u.Scheme != \"http\" && u.Scheme != \"https\") || u.Host == \"\" || u.Fragment != \"\") {\n    return fmt.Errorf(\"invalid end-session endpoint: %q\", ssoCfg.EndSessionEndpoint)\n}","typeGuard":"func isAbsoluteHTTPEndpoint(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\" && u.Fragment == \"\"\n}","tryCatchPattern":"redirect, err := logout.ConstructLogoutURL(...)\nif err != nil {\n    log.Printf(\"falling back to plain redirect: %v\", err)\n    // redirect already contains the safe fallback URL\n}","preventionTips":["Fetch end_session_endpoint from the issuer's discovery document rather than hardcoding","Ping the provider's .well-known/openid-configuration after SSO config changes","Avoid copying URLs with fragments from browser address bars"],"tags":["oidc","logout","url-validation","sso"],"backgroundTag":"invalid-url","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}