git.iko.soy/typeable/oauth2-proxy
on master help sign in
After authentication, redirect to original URI.
commitd2b1815d4337a43ee89aee18bdac64f88d1bb66b authorSean O'Connor <sean@bit.ly> dateTue 22 Oct 2013, 19:56 (13 years ago) parent7dc5b69
2 files changed+36−15
oauthproxy.go+34−15 templates.go+2
oauthproxy.go+34−15
@@ -67,13 +67,16 @@ func (p *OauthProxy) SetRedirectUrl(redirectUrl *url.URL) {
6767 p.redirectUrl = redirectUrl
6868}
6969
70−func (p *OauthProxy) GetLoginURL() string {
70+func (p *OauthProxy) GetLoginURL(redirectUrl string) string {
7171 params := url.Values{}
7272 params.Add("redirect_uri", p.redirectUrl.String())
7373 params.Add("approval_prompt", "force")
7474 params.Add("scope", p.oauthScope)
7575 params.Add("client_id", p.clientID)
7676 params.Add("response_type", "code")
77+ if strings.HasPrefix(redirectUrl, "/") {
78+ params.Add("state", redirectUrl)
79+ }
7780 return fmt.Sprintf("%s?%s", p.oauthLoginUrl, params.Encode())
7881}
7982
@@ -100,6 +103,9 @@ func apiRequest(req *http.Request) (*simplejson.Json, error) {
100103}
101104
102105func (p *OauthProxy) redeemCode(code string) (string, error) {
106+ if code == "" {
107+ return "", errors.New("missing code")
108+ }
103109 params := url.Values{}
104110 params.Add("redirect_uri", p.redirectUrl.String())
105111 params.Add("client_id", p.clientID)
@@ -197,7 +203,6 @@ func (p *OauthProxy) ErrorPage(rw http.ResponseWriter, code int, title string, m
197203}
198204
199205func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code int) {
200− // TODO: capture state for which url to redirect to at the end
201206 p.ClearCookie(rw, req)
202207 rw.WriteHeader(code)
203208 templates := getTemplates()
@@ -205,9 +210,11 @@ func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code
205210 t := struct {
206211 SignInMessage string
207212 Htpasswd bool
213+ Redirect string
208214 }{
209215 SignInMessage: p.SignInMessage,
210216 Htpasswd: p.HtpasswdFile != nil,
217+ Redirect: req.URL.RequestURI(),
211218 }
212219 templates.ExecuteTemplate(rw, "sign_in.html", t)
213220}
@@ -239,39 +246,46 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
239246
240247 var ok bool
241248 var user string
249+ redirect := req.FormValue("rd")
250+
251+ if redirect == "" {
252+ redirect = "/"
253+ }
254+
242255 if req.URL.Path == signInPath {
243256 user, ok = p.ManualSignIn(rw, req)
244257 if ok {
245258 p.SetCookie(rw, req, user)
246− http.Redirect(rw, req, "/", 302)
259+ http.Redirect(rw, req, redirect, 302)
247260 } else {
248261 p.SignInPage(rw, req, 200)
249262 }
250263 return
251264 }
252265 if req.URL.Path == oauthStartPath {
253− http.Redirect(rw, req, p.GetLoginURL(), 302)
266+ // get the ?rd= value
267+ err := req.ParseForm()
268+ if err != nil {
269+ p.ErrorPage(rw, 500, "Internal Error", err.Error())
270+ return
271+ }
272+ http.Redirect(rw, req, p.GetLoginURL(redirect), 302)
254273 return
255274 }
256275 if req.URL.Path == oauthCallbackPath {
257276 // finish the oauth cycle
258− reqParams, err := url.ParseQuery(req.URL.RawQuery)
277+ err := req.ParseForm()
259278 if err != nil {
260279 p.ErrorPage(rw, 500, "Internal Error", err.Error())
261280 return
262281 }
263− errorString, ok := reqParams["error"]
264− if ok && len(errorString) == 1 {
265− p.ErrorPage(rw, 403, "Permission Denied", errorString[0])
266− return
267− }
268− code, ok := reqParams["code"]
269− if !ok || len(code) != 1 {
270− p.ErrorPage(rw, 500, "Internal Error", "Invalid API response")
282+ errorString := req.Form.Get("error")
283+ if errorString != "" {
284+ p.ErrorPage(rw, 403, "Permission Denied", errorString)
271285 return
272286 }
273287
274− token, err := p.redeemCode(code[0])
288+ token, err := p.redeemCode(req.Form.Get("code"))
275289 if err != nil {
276290 log.Printf("error redeeming code %s", err.Error())
277291 p.ErrorPage(rw, 500, "Internal Error", err.Error())
@@ -285,11 +299,16 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
285299 return
286300 }
287301
302+ redirect := req.Form.Get("state")
303+ if redirect == "" {
304+ redirect = "/"
305+ }
306+
288307 // set cookie, or deny
289308 if p.Validator(email) {
290309 log.Printf("authenticating %s completed", email)
291310 p.SetCookie(rw, req, email)
292− http.Redirect(rw, req, "/", 302)
311+ http.Redirect(rw, req, redirect, 302)
293312 return
294313 } else {
295314 p.ErrorPage(rw, 403, "Permission Denied", "Invalid Account")
templates.go+2
@@ -12,12 +12,14 @@ func getTemplates() *template.Template {
1212<head><title>Sign In</title></head>
1313<body>
1414 <form method="GET" action="/oauth2/start">
15+ <input type="hidden" name="rd" value="{{.Redirect}}">
1516 <button type="submit">Sign In w/ Google</button>
1617 {{.SignInMessage}}
1718 </form>
1819 {{ if .Htpasswd }}
1920 <fieldset>
2021 <form method="POST" action="/oauth2/sign_in">
22+ <input type="hidden" name="rd" value="{{.Redirect}}">
2123 <label>Username: <input type="text" name="username" size="10"></label><br/>
2224 <label>Password: <input type="password" name="password" size="10"></label><br/>
2325 <button type="submit">Sign In</button>