@@ -3,6 +3,7 @@ package main
6 "encoding/json"
7 "encoding/json"
@@ -110,6 +111,8 @@ type OAuthProxy struct {
110 serveMux *mux.Router
111 serveMux *mux.Router
111 redirectValidator redirect.Validator
112 redirectValidator redirect.Validator
112 appDirector redirect.AppDirector
113 appDirector redirect.AppDirector
115// NewOAuthProxy creates a new instance of OAuthProxy from the options provided
118// 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
239 upstreamProxy: upstreamProxy,
242 upstreamProxy: upstreamProxy,
240 redirectValidator: redirectValidator,
243 redirectValidator: redirectValidator,
241 appDirector: appDirector,
244 appDirector: appDirector,
245+ encodeState: opts.EncodeState,
243 p.buildServeMux(opts.ProxyPrefix)
247 p.buildServeMux(opts.ProxyPrefix)
@@ -796,7 +800,7 @@ func (p *OAuthProxy) doOAuthStart(rw http.ResponseWriter, req *http.Request, ove
796 callbackRedirect := p.getOAuthRedirectURI(req)
800 callbackRedirect := p.getOAuthRedirectURI(req)
797 loginURL := p.provider.GetLoginURL(
801 loginURL := p.provider.GetLoginURL(
798 callbackRedirect,
802 callbackRedirect,
799− encodeState(csrf.HashOAuthState(), appRedirect),
803+ encodeState(csrf.HashOAuthState(), appRedirect, p.encodeState),
800 csrf.HashOIDCNonce(),
804 csrf.HashOIDCNonce(),
801 extraParams,
805 extraParams,
@@ -854,7 +858,7 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) {
855 csrf.ClearCookie(rw, req)
859 csrf.ClearCookie(rw, req)
857− nonce, appRedirect, err := decodeState(req)
861+ nonce, appRedirect, err := decodeState(req.Form.Get("state"), p.encodeState)
858 if err != nil {
862 if err != nil {
859 logger.Errorf("Error while parsing OAuth2 state: %v", err)
863 logger.Errorf("Error while parsing OAuth2 state: %v", err)
860 p.ErrorPage(rw, req, http.StatusInternalServerError, err.Error())
864 p.ErrorPage(rw, req, http.StatusInternalServerError, err.Error())
@@ -1194,18 +1198,28 @@ func checkAllowedEmails(req *http.Request, s *sessionsapi.SessionState) bool {
1195// encodedState builds the OAuth state param out of our nonce and
1199// encodedState builds the OAuth state param out of our nonce and
1196// original application redirect
1200// original application redirect
1197−func encodeState(nonce string, redirect string) string {
1201+func encodeState(nonce string, redirect string, encode bool) string {
1198− return fmt.Sprintf("%v:%v", nonce, redirect)
1202+ rawString := fmt.Sprintf("%v:%v", nonce, redirect)
1204+ return base64.RawURLEncoding.EncodeToString([]byte(rawString))
1201// decodeState splits the reflected OAuth state response back into
1209// decodeState splits the reflected OAuth state response back into
1202// the nonce and original application redirect
1210// the nonce and original application redirect
1203−func decodeState(req *http.Request) (string, string, error) {
1211+func decodeState(state string, encode bool) (string, string, error) {
1214+ decoded, _ := base64.RawURLEncoding.DecodeString(state)
1215+ toParse = string(decoded)
1204− state := strings.SplitN(req.Form.Get("state"), ":", 2)
1218+ parsedState := strings.SplitN(toParse, ":", 2)
1205− if len(state) != 2 {
1219+ if len(parsedState) != 2 {
1206 return "", "", errors.New("invalid length")
1220 return "", "", errors.New("invalid length")
1208− return state[0], state[1], nil
1222+ return parsedState[0], parsedState[1], nil
1211// addHeadersForProxying adds the appropriate headers the request / response for proxying
1225// addHeadersForProxying adds the appropriate headers the request / response for proxying