After authentication, redirect to original URI.
This commit is contained in:
		
							parent
							
								
									7dc5b691e7
								
							
						
					
					
						commit
						d2b1815d43
					
				|  | @ -67,13 +67,16 @@ func (p *OauthProxy) SetRedirectUrl(redirectUrl *url.URL) { | ||||||
| 	p.redirectUrl = redirectUrl | 	p.redirectUrl = redirectUrl | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) GetLoginURL() string { | func (p *OauthProxy) GetLoginURL(redirectUrl string) string { | ||||||
| 	params := url.Values{} | 	params := url.Values{} | ||||||
| 	params.Add("redirect_uri", p.redirectUrl.String()) | 	params.Add("redirect_uri", p.redirectUrl.String()) | ||||||
| 	params.Add("approval_prompt", "force") | 	params.Add("approval_prompt", "force") | ||||||
| 	params.Add("scope", p.oauthScope) | 	params.Add("scope", p.oauthScope) | ||||||
| 	params.Add("client_id", p.clientID) | 	params.Add("client_id", p.clientID) | ||||||
| 	params.Add("response_type", "code") | 	params.Add("response_type", "code") | ||||||
|  | 	if strings.HasPrefix(redirectUrl, "/") { | ||||||
|  | 		params.Add("state", redirectUrl) | ||||||
|  | 	} | ||||||
| 	return fmt.Sprintf("%s?%s", p.oauthLoginUrl, params.Encode()) | 	return fmt.Sprintf("%s?%s", p.oauthLoginUrl, params.Encode()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -100,6 +103,9 @@ func apiRequest(req *http.Request) (*simplejson.Json, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) redeemCode(code string) (string, error) { | func (p *OauthProxy) redeemCode(code string) (string, error) { | ||||||
|  | 	if code == "" { | ||||||
|  | 		return "", errors.New("missing code") | ||||||
|  | 	} | ||||||
| 	params := url.Values{} | 	params := url.Values{} | ||||||
| 	params.Add("redirect_uri", p.redirectUrl.String()) | 	params.Add("redirect_uri", p.redirectUrl.String()) | ||||||
| 	params.Add("client_id", p.clientID) | 	params.Add("client_id", p.clientID) | ||||||
|  | @ -197,7 +203,6 @@ func (p *OauthProxy) ErrorPage(rw http.ResponseWriter, code int, title string, m | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code int) { | func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code int) { | ||||||
| 	// TODO: capture state for which url to redirect to at the end
 |  | ||||||
| 	p.ClearCookie(rw, req) | 	p.ClearCookie(rw, req) | ||||||
| 	rw.WriteHeader(code) | 	rw.WriteHeader(code) | ||||||
| 	templates := getTemplates() | 	templates := getTemplates() | ||||||
|  | @ -205,9 +210,11 @@ func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code | ||||||
| 	t := struct { | 	t := struct { | ||||||
| 		SignInMessage string | 		SignInMessage string | ||||||
| 		Htpasswd      bool | 		Htpasswd      bool | ||||||
|  | 		Redirect      string | ||||||
| 	}{ | 	}{ | ||||||
| 		SignInMessage: p.SignInMessage, | 		SignInMessage: p.SignInMessage, | ||||||
| 		Htpasswd:      p.HtpasswdFile != nil, | 		Htpasswd:      p.HtpasswdFile != nil, | ||||||
|  | 		Redirect:      req.URL.RequestURI(), | ||||||
| 	} | 	} | ||||||
| 	templates.ExecuteTemplate(rw, "sign_in.html", t) | 	templates.ExecuteTemplate(rw, "sign_in.html", t) | ||||||
| } | } | ||||||
|  | @ -239,39 +246,46 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||||||
| 
 | 
 | ||||||
| 	var ok bool | 	var ok bool | ||||||
| 	var user string | 	var user string | ||||||
|  | 	redirect := req.FormValue("rd") | ||||||
|  | 
 | ||||||
|  | 	if redirect == "" { | ||||||
|  | 		redirect = "/" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if req.URL.Path == signInPath { | 	if req.URL.Path == signInPath { | ||||||
| 		user, ok = p.ManualSignIn(rw, req) | 		user, ok = p.ManualSignIn(rw, req) | ||||||
| 		if ok { | 		if ok { | ||||||
| 			p.SetCookie(rw, req, user) | 			p.SetCookie(rw, req, user) | ||||||
| 			http.Redirect(rw, req, "/", 302) | 			http.Redirect(rw, req, redirect, 302) | ||||||
| 		} else { | 		} else { | ||||||
| 			p.SignInPage(rw, req, 200) | 			p.SignInPage(rw, req, 200) | ||||||
| 		} | 		} | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	if req.URL.Path == oauthStartPath { | 	if req.URL.Path == oauthStartPath { | ||||||
| 		http.Redirect(rw, req, p.GetLoginURL(), 302) | 		// get the ?rd= value
 | ||||||
| 		return | 		err := req.ParseForm() | ||||||
| 	} |  | ||||||
| 	if req.URL.Path == oauthCallbackPath { |  | ||||||
| 		// finish the oauth cycle
 |  | ||||||
| 		reqParams, err := url.ParseQuery(req.URL.RawQuery) |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			p.ErrorPage(rw, 500, "Internal Error", err.Error()) | 			p.ErrorPage(rw, 500, "Internal Error", err.Error()) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		errorString, ok := reqParams["error"] | 		http.Redirect(rw, req, p.GetLoginURL(redirect), 302) | ||||||
| 		if ok && len(errorString) == 1 { | 		return | ||||||
| 			p.ErrorPage(rw, 403, "Permission Denied", errorString[0]) | 	} | ||||||
|  | 	if req.URL.Path == oauthCallbackPath { | ||||||
|  | 		// finish the oauth cycle
 | ||||||
|  | 		err := req.ParseForm() | ||||||
|  | 		if err != nil { | ||||||
|  | 			p.ErrorPage(rw, 500, "Internal Error", err.Error()) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		code, ok := reqParams["code"] | 		errorString := req.Form.Get("error") | ||||||
| 		if !ok || len(code) != 1 { | 		if errorString != "" { | ||||||
| 			p.ErrorPage(rw, 500, "Internal Error", "Invalid API response") | 			p.ErrorPage(rw, 403, "Permission Denied", errorString) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		token, err := p.redeemCode(code[0]) | 		token, err := p.redeemCode(req.Form.Get("code")) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Printf("error redeeming code %s", err.Error()) | 			log.Printf("error redeeming code %s", err.Error()) | ||||||
| 			p.ErrorPage(rw, 500, "Internal Error", err.Error()) | 			p.ErrorPage(rw, 500, "Internal Error", err.Error()) | ||||||
|  | @ -285,11 +299,16 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		redirect := req.Form.Get("state") | ||||||
|  | 		if redirect == "" { | ||||||
|  | 			redirect = "/" | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		// set cookie, or deny
 | 		// set cookie, or deny
 | ||||||
| 		if p.Validator(email) { | 		if p.Validator(email) { | ||||||
| 			log.Printf("authenticating %s completed", email) | 			log.Printf("authenticating %s completed", email) | ||||||
| 			p.SetCookie(rw, req, email) | 			p.SetCookie(rw, req, email) | ||||||
| 			http.Redirect(rw, req, "/", 302) | 			http.Redirect(rw, req, redirect, 302) | ||||||
| 			return | 			return | ||||||
| 		} else { | 		} else { | ||||||
| 			p.ErrorPage(rw, 403, "Permission Denied", "Invalid Account") | 			p.ErrorPage(rw, 403, "Permission Denied", "Invalid Account") | ||||||
|  |  | ||||||
|  | @ -12,12 +12,14 @@ func getTemplates() *template.Template { | ||||||
| <head><title>Sign In</title></head> | <head><title>Sign In</title></head> | ||||||
| <body> | <body> | ||||||
| 	<form method="GET" action="/oauth2/start"> | 	<form method="GET" action="/oauth2/start"> | ||||||
|  | 	<input type="hidden" name="rd" value="{{.Redirect}}"> | ||||||
| 	<button type="submit">Sign In w/ Google</button> | 	<button type="submit">Sign In w/ Google</button> | ||||||
| 	{{.SignInMessage}} | 	{{.SignInMessage}} | ||||||
| 	</form> | 	</form> | ||||||
| 	{{ if .Htpasswd }} | 	{{ if .Htpasswd }} | ||||||
| 	<fieldset> | 	<fieldset> | ||||||
| 		<form method="POST" action="/oauth2/sign_in"> | 		<form method="POST" action="/oauth2/sign_in"> | ||||||
|  | 		<input type="hidden" name="rd" value="{{.Redirect}}"> | ||||||
| 		<label>Username: <input type="text" name="username" size="10"></label><br/> | 		<label>Username: <input type="text" name="username" size="10"></label><br/> | ||||||
| 		<label>Password: <input type="password" name="password" size="10"></label><br/> | 		<label>Password: <input type="password" name="password" size="10"></label><br/> | ||||||
| 		<button type="submit">Sign In</button> | 		<button type="submit">Sign In</button> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue