rancher/rancher · error

grant_type not supported

Error message

grant_type not supported

What it means

The embedded OIDC provider's token endpoint accepts exactly two grant types - authorization_code and refresh_token, matching its advertised grant_types_supported. Any other grant_type (password, client_credentials, device_code, or a typo) hits the default branch and gets a plain-text 500 'grant_type not supported'. RFC 6749 requires 400 with error=unsupported_grant_type, so standards-strict clients may mis-handle the 500 status.

Source

Thrown at pkg/oidc/provider/token.go:149

			return
		}
	case "refresh_token":
		tokenResponse, oidcErr := h.createRefreshToken(r)
		if oidcErr != nil {
			logrus.Debug("[OIDC provider] error creating refresh token response: " + oidcErr.ToString())
			oidcErr.Write(http.StatusBadRequest, w)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Cache-Control", "no-store")
		w.Header().Set("Pragma", "no-cache")
		err = json.NewEncoder(w).Encode(tokenResponse)
		if err != nil {
			oidcerror.WriteError(oidcerror.ServerError, "failed to encode refresh token response", http.StatusInternalServerError, w)
			return
		}
	default:
		http.Error(w, "grant_type not supported", http.StatusInternalServerError)
		return
	}
}

// createTokenFromCode creates a response with an id_token (if openid scope is
// provided), access_token and refresh_token
func (h *tokenHandler) createTokenFromCode(r *http.Request) (TokenResponse, *oidcerror.Error) {
	code := r.FormValue("code")
	session, err := h.sessionClient.GetAndRemove(code)
	if err != nil {
		if apierrors.IsNotFound(err) {
			return TokenResponse{}, oidcerror.New(oidcerror.InvalidRequest, "invalid code")
		}
		return TokenResponse{}, oidcerror.Newf(oidcerror.ServerError, "error retrieving session: %s", err)
	}

	// verify clientID and secret. They can be set in the Authorization header or as a form param as specified in the OIDC spec.
	clientID, clientSecret, ok := r.BasicAuth()

View on GitHub (pinned to 932558d4e6)

Solutions

  1. Switch the client to the authorization_code flow (or refresh_token when refreshing).
  2. For machine-to-machine access, use a Rancher API token (Bearer key) instead of the OIDC provider.
  3. Server-side hardening: return 400 with error=unsupported_grant_type per RFC 6749 instead of 500.

Example fix

# before
curl -s https://rancher/oidc/token -d grant_type=client_credentials
# 500 grant_type not supported

# after
curl -s https://rancher/oidc/token -d grant_type=authorization_code -d code=... -d redirect_uri=...
# or use a Rancher API token for machine access
Defensive patterns

Strategy: validation

Validate before calling

GRANT=authorization_code; [ "$GRANT" = authorization_code ] || [ "$GRANT" = refresh_token ] || { echo "unsupported grant_type: $GRANT"; exit 2; }; curl -s https://rancher/oidc/token -d grant_type=$GRANT ...

Type guard

func isSupportedGrantType(g string) bool {
	return g == "authorization_code" || g == "refresh_token"
}

Try / catch

if !isSupportedGrantType(r.Form.Get("grant_type")) { return 400 unsupported_grant_type before hitting the endpoint } - clients should fail fast on configuration, never retry a 500 for this cause.

Prevention

When it happens

Trigger: POST to the OIDC token endpoint with grant_type=password, client_credentials, urn:ietf:params:oauth:grant-type:device_code, or a misspelled value; an OIDC client library configured for a flow Rancher does not implement.

Common situations: Scripting authentication with password grant instead of the authorization-code flow; service-to-service consumers expecting client-credentials; SDK defaults selecting an unsupported flow.

Related errors


AI-assisted analysis of rancher/rancher@932558d4e6 (2026-08-16). Data as JSON: /api/errors/3acbc0264a54def1. Report an issue: GitHub.