auth
122:eb9842ae3ff1 Browse Files
Enable the implict grant flow. Add the implicit grant flow. This can't be done in a grant type, because it's not specified through the grant_type parameter, for some absurd reason. Whatever. We basically achieved this by refactoring how we respond to the authorization endpoint, keying off the "response_type" parameter.
1.1 --- a/oauth2.go Sun Jan 18 02:14:41 2015 -0500 1.2 +++ b/oauth2.go Sun Jan 18 03:23:20 2015 -0500 1.3 @@ -7,6 +7,7 @@ 1.4 "log" 1.5 "net/http" 1.6 "net/url" 1.7 + "strconv" 1.8 "sync" 1.9 "time" 1.10 1.11 @@ -257,10 +258,11 @@ 1.12 } 1.13 scope := r.URL.Query().Get("scope") 1.14 state := r.URL.Query().Get("state") 1.15 - if r.URL.Query().Get("response_type") != "code" { 1.16 - q := redirectURL.Query() 1.17 + responseType := r.URL.Query().Get("response_type") 1.18 + q := redirectURL.Query() 1.19 + q.Add("state", state) 1.20 + if responseType != "code" && responseType != "token" { 1.21 q.Add("error", "invalid_request") 1.22 - q.Add("state", state) 1.23 redirectURL.RawQuery = q.Encode() 1.24 http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.25 return 1.26 @@ -268,45 +270,68 @@ 1.27 if r.Method == "POST" { 1.28 // BUG(paddy): We need to implement CSRF protection when obtaining a grant code. 1.29 if r.PostFormValue("grant") == "approved" { 1.30 - code := uuid.NewID().String() 1.31 - authCode := AuthorizationCode{ 1.32 - Code: code, 1.33 - Created: time.Now(), 1.34 - ExpiresIn: defaultAuthorizationCodeExpiration, 1.35 - ClientID: clientID, 1.36 - Scope: scope, 1.37 - RedirectURI: r.URL.Query().Get("redirect_uri"), 1.38 - State: state, 1.39 - ProfileID: session.ProfileID, 1.40 + var fragment bool 1.41 + switch responseType { 1.42 + case "code": 1.43 + code := uuid.NewID().String() 1.44 + authCode := AuthorizationCode{ 1.45 + Code: code, 1.46 + Created: time.Now(), 1.47 + ExpiresIn: defaultAuthorizationCodeExpiration, 1.48 + ClientID: clientID, 1.49 + Scope: scope, 1.50 + RedirectURI: r.URL.Query().Get("redirect_uri"), 1.51 + State: state, 1.52 + ProfileID: session.ProfileID, 1.53 + } 1.54 + err := context.SaveAuthorizationCode(authCode) 1.55 + if err != nil { 1.56 + log.Println("Error saving authorization code:", err) 1.57 + q.Add("error", "server_error") 1.58 + break 1.59 + } 1.60 + q.Add("code", code) 1.61 + case "token": 1.62 + token := Token{ 1.63 + AccessToken: uuid.NewID().String(), 1.64 + Created: time.Now(), 1.65 + CreatedFrom: "", 1.66 + ExpiresIn: defaultTokenExpiration, 1.67 + TokenType: "bearer", 1.68 + Scope: scope, 1.69 + ProfileID: session.ProfileID, 1.70 + } 1.71 + err := context.SaveToken(token) 1.72 + if err != nil { 1.73 + log.Println("Error saving token:", err) 1.74 + q.Add("error", "server_error") 1.75 + break 1.76 + } 1.77 + q = url.Values{} // we're not altering the querystring, so don't clone it 1.78 + q.Add("access_token", token.AccessToken) 1.79 + q.Add("token_type", token.TokenType) 1.80 + q.Add("expires_in", strconv.FormatInt(int64(token.ExpiresIn), 10)) 1.81 + q.Add("scope", token.Scope) 1.82 + q.Add("state", state) // we wiped out the old values, so we need to set the state again 1.83 + fragment = true 1.84 } 1.85 - err := context.SaveAuthorizationCode(authCode) 1.86 - if err != nil { 1.87 - q := redirectURL.Query() 1.88 - q.Add("error", "server_error") 1.89 - q.Add("state", state) 1.90 + if fragment { 1.91 + redirectURL.Fragment = q.Encode() 1.92 + } else { 1.93 redirectURL.RawQuery = q.Encode() 1.94 - http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.95 - return 1.96 } 1.97 - q := redirectURL.Query() 1.98 - q.Add("code", code) 1.99 - q.Add("state", state) 1.100 - redirectURL.RawQuery = q.Encode() 1.101 http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.102 return 1.103 } 1.104 - q := redirectURL.Query() 1.105 q.Add("error", "access_denied") 1.106 - q.Add("state", state) 1.107 redirectURL.RawQuery = q.Encode() 1.108 http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.109 return 1.110 } 1.111 profile, err := context.GetProfileByID(session.ProfileID) 1.112 if err != nil { 1.113 - q := redirectURL.Query() 1.114 + log.Println("Error getting profile from session:", err) 1.115 q.Add("error", "server_error") 1.116 - q.Add("state", state) 1.117 redirectURL.RawQuery = q.Encode() 1.118 http.Redirect(w, r, redirectURL.String(), http.StatusFound) 1.119 return