auth
60:0cc717e02c9b Browse Files
Fill out redirects. Actually redirect the user when obtaining a grant. Check if the redirect_uri being passed when obtaining a grant is _actually a URL_. If it's not, return the right error. Add a test for a redirect_uri that isn't a valid URL.
1.1 --- a/http.go Sun Oct 26 03:31:24 2014 -0400 1.2 +++ b/http.go Sun Nov 02 20:45:51 2014 -0500 1.3 @@ -2,11 +2,16 @@ 1.4 1.5 import ( 1.6 "net/http" 1.7 + "net/url" 1.8 + "time" 1.9 1.10 "code.secondbit.org/uuid" 1.11 ) 1.12 1.13 -const getGrantTemplateName = "get_grant" 1.14 +const ( 1.15 + getGrantTemplateName = "get_grant" 1.16 + defaultGrantExpiration = 600 // default to ten minute grant expirations 1.17 +) 1.18 1.19 // GetGrantHandler presents and processes the page for asking a user to grant access 1.20 // to their data. See RFC 6749, Section 4.1. 1.21 @@ -90,18 +95,51 @@ 1.22 }) 1.23 return 1.24 } 1.25 + scope := r.URL.Query().Get("scope") 1.26 + state := r.URL.Query().Get("state") 1.27 + redirectURL, err := url.Parse(redirectURI) 1.28 + if err != nil { 1.29 + w.WriteHeader(http.StatusBadRequest) 1.30 + context.Render(w, getGrantTemplateName, map[string]interface{}{ 1.31 + "error": "The redirect_uri specified is not valid.", 1.32 + }) 1.33 + return 1.34 + } 1.35 if r.URL.Query().Get("response_type") != "code" { 1.36 - // TODO: redirect error 1.37 + redirectURL.Query().Add("error", "invalid_request") 1.38 + redirectURL.Query().Add("state", state) 1.39 + http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.40 + return 1.41 } 1.42 - //scope := r.URL.Query().Get("scope") 1.43 - //state := r.URL.Query().Get("state") 1.44 if r.Method == "POST" { 1.45 // TODO: CSRF protection 1.46 if r.PostFormValue("grant") == "approved" { 1.47 - // TODO: redirect 1.48 - } else { 1.49 - // TODO: redirect error 1.50 + code := uuid.NewID().String() 1.51 + grant := Grant{ 1.52 + Code: code, 1.53 + Created: time.Now(), 1.54 + ExpiresIn: defaultGrantExpiration, 1.55 + ClientID: clientID, 1.56 + Scope: scope, 1.57 + RedirectURI: redirectURI, 1.58 + State: state, 1.59 + } 1.60 + err := context.SaveGrant(grant) 1.61 + if err != nil { 1.62 + redirectURL.Query().Add("error", "server_error") 1.63 + redirectURL.Query().Add("state", state) 1.64 + http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.65 + return 1.66 + } 1.67 + redirectURL.Query().Add("code", code) 1.68 + redirectURL.Query().Add("state", state) 1.69 + http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.70 + return 1.71 } 1.72 + redirectURL.Query().Add("error", "access_denied") 1.73 + redirectURL.Query().Add("state", state) 1.74 + http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.75 + return 1.76 } 1.77 w.WriteHeader(http.StatusOK) 1.78 context.Render(w, getGrantTemplateName, map[string]interface{}{
2.1 --- a/http_test.go Sun Oct 26 03:31:24 2014 -0400 2.2 +++ b/http_test.go Sun Nov 02 20:45:51 2014 -0500 2.3 @@ -136,4 +136,18 @@ 2.4 if w.Body.String() != "The redirect_uri specified is not valid." { 2.5 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The redirect_uri specified is not valid.", w.Body.String()) 2.6 } 2.7 + req, err = http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil) 2.8 + if err != nil { 2.9 + t.Fatal("Can't build request:", err) 2.10 + } 2.11 + w = httptest.NewRecorder() 2.12 + params.Set("redirect_uri", "not a URL") 2.13 + req.URL.RawQuery = params.Encode() 2.14 + GetGrantHandler(w, req, testContext) 2.15 + if w.Code != http.StatusBadRequest { 2.16 + t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) 2.17 + } 2.18 + if w.Body.String() != "The redirect_uri specified is not valid." { 2.19 + t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The redirect_uri specified is not valid.", w.Body.String()) 2.20 + } 2.21 }