@@ -3,6 +3,7 @@ package main
33import (
44 "context"
55 "embed"
6+ "encoding/base64"
67 "encoding/json"
78 "errors"
89 "fmt"
@@ -110,6 +111,8 @@ type OAuthProxy struct {
110111 serveMux *mux.Router
111112 redirectValidator redirect.Validator
112113 appDirector redirect.AppDirector
114+
115+ encodeState bool
113116}
114117
115118// NewOAuthProxy creates a new instance of OAuthProxy from the options provided
@@ -239,6 +242,7 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
239242 upstreamProxy: upstreamProxy,
240243 redirectValidator: redirectValidator,
241244 appDirector: appDirector,
245+ encodeState: opts.EncodeState,
242246 }
243247 p.buildServeMux(opts.ProxyPrefix)
244248
@@ -796,7 +800,7 @@ func (p *OAuthProxy) doOAuthStart(rw http.ResponseWriter, req *http.Request, ove
796800 callbackRedirect := p.getOAuthRedirectURI(req)
797801 loginURL := p.provider.GetLoginURL(
798802 callbackRedirect,
799− encodeState(csrf.HashOAuthState(), appRedirect),
803+ encodeState(csrf.HashOAuthState(), appRedirect, p.encodeState),
800804 csrf.HashOIDCNonce(),
801805 extraParams,
802806 )
@@ -854,7 +858,7 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) {
854858
855859 csrf.ClearCookie(rw, req)
856860
857− nonce, appRedirect, err := decodeState(req)
861+ nonce, appRedirect, err := decodeState(req.Form.Get("state"), p.encodeState)
858862 if err != nil {
859863 logger.Errorf("Error while parsing OAuth2 state: %v", err)
860864 p.ErrorPage(rw, req, http.StatusInternalServerError, err.Error())
@@ -1194,18 +1198,28 @@ func checkAllowedEmails(req *http.Request, s *sessionsapi.SessionState) bool {
11941198
11951199// encodedState builds the OAuth state param out of our nonce and
11961200// original application redirect
1197−func encodeState(nonce string, redirect string) string {
1198− return fmt.Sprintf("%v:%v", nonce, redirect)
1201+func encodeState(nonce string, redirect string, encode bool) string {
1202+ rawString := fmt.Sprintf("%v:%v", nonce, redirect)
1203+ if encode {
1204+ return base64.RawURLEncoding.EncodeToString([]byte(rawString))
1205+ }
1206+ return rawString
11991207}
12001208
12011209// decodeState splits the reflected OAuth state response back into
12021210// the nonce and original application redirect
1203−func decodeState(req *http.Request) (string, string, error) {
1204− state := strings.SplitN(req.Form.Get("state"), ":", 2)
1205− if len(state) != 2 {
1211+func decodeState(state string, encode bool) (string, string, error) {
1212+ toParse := state
1213+ if encode {
1214+ decoded, _ := base64.RawURLEncoding.DecodeString(state)
1215+ toParse = string(decoded)
1216+ }
1217+
1218+ parsedState := strings.SplitN(toParse, ":", 2)
1219+ if len(parsedState) != 2 {
12061220 return "", "", errors.New("invalid length")
12071221 }
1208− return state[0], state[1], nil
1222+ return parsedState[0], parsedState[1], nil
12091223}
12101224
12111225// addHeadersForProxying adds the appropriate headers the request / response for proxying