Skip to content

Commit 0a49c2d

Browse files
committed
optimization of error handling
1 parent 51174a8 commit 0a49c2d

File tree

6 files changed

+97
-73
lines changed

6 files changed

+97
-73
lines changed

LICENSE

+17-19
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
1-
Copyright (c) 2016, OAuth 2.0
2-
All rights reserved.
1+
MIT License
32

4-
Redistribution and use in source and binary forms, with or without
5-
modification, are permitted provided that the following conditions are met:
3+
Copyright (c) 2016 Lyric
64

7-
* Redistributions of source code must retain the above copyright notice, this
8-
list of conditions and the following disclaimer.
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
911

10-
* Redistributions in binary form must reproduce the above copyright notice,
11-
this list of conditions and the following disclaimer in the documentation
12-
and/or other materials provided with the distribution.
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
1314

14-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+26-9
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
> An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.
44
5-
[![GoDoc](https://godoc.org/gopkg.in/oauth2.v3?status.svg)](https://godoc.org/gopkg.in/oauth2.v3)
6-
[![Go Report Card](https://goreportcard.com/badge/gopkg.in/oauth2.v3)](https://goreportcard.com/report/gopkg.in/oauth2.v3)
7-
[![Build Status](https://travis-ci.org/go-oauth2/oauth2.svg?branch=master)](https://travis-ci.org/go-oauth2/oauth2)
5+
[![License][License-Image]][License-Url]
6+
[![ReportCard][ReportCard-Image]][ReportCard-Url]
7+
[![Build][Build-Status-Image]][Build-Status-Url]
8+
[![GoDoc][GoDoc-Image]][GoDoc-Url]
9+
[![Release][Release-Image]][Release-Url]
810

911
## Protocol Flow
1012

@@ -42,6 +44,7 @@ $ go get -u gopkg.in/oauth2.v3/...
4244
package main
4345

4446
import (
47+
"fmt"
4548
"net/http"
4649

4750
"gopkg.in/oauth2.v3/manage"
@@ -59,6 +62,10 @@ func main() {
5962
srv := server.NewDefaultServer(manager)
6063
srv.SetAllowGetAccessRequest(true)
6164

65+
srv.SetInternalErrorHandler(func(err error) {
66+
fmt.Println("OAuth2 Error:",err.Error())
67+
})
68+
6269
http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) {
6370
err := srv.HandleAuthorizeRequest(w, r)
6471
if err != nil {
@@ -69,7 +76,7 @@ func main() {
6976
http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
7077
err := srv.HandleTokenRequest(w, r)
7178
if err != nil {
72-
http.Error(w, err.Error(), http.StatusBadRequest)
79+
http.Error(w, err.Error(), http.StatusInternalServerError)
7380
}
7481
})
7582

@@ -114,15 +121,25 @@ http://localhost:9096/token?grant_type=clientcredentials&client_id=1&client_secr
114121
115122
Simulation examples of authorization code model, please check [example](/example)
116123

117-
## Storage implements
124+
## Storage Implements
118125

119126
* [BuntDB](https://github.com/tidwall/buntdb)(The default storage)
120127
* [Redis](https://github.com/go-oauth2/redis)
121128
* [MongoDB](https://github.com/go-oauth2/mongo)
122129

123-
## License
130+
## MIT License
124131

125132
```
126-
Copyright (c) 2016, OAuth 2.0
127-
All rights reserved.
128-
```
133+
Copyright (c) 2016 Lyric
134+
```
135+
136+
[License-Url]: http://opensource.org/licenses/MIT
137+
[License-Image]: https://img.shields.io/npm/l/express.svg
138+
[Build-Status-Url]: https://travis-ci.org/go-oauth2/oauth2
139+
[Build-Status-Image]: https://travis-ci.org/go-oauth2/oauth2.svg?branch=master
140+
[Release-Url]: https://github.com/go-oauth2/oauth2/releases/tag/v3.4.8
141+
[Release-image]: http://img.shields.io/badge/release-v3.4.8-1eb0fc.svg
142+
[ReportCard-Url]: https://goreportcard.com/report/gopkg.in/oauth2.v3
143+
[ReportCard-Image]: https://goreportcard.com/badge/gopkg.in/oauth2.v3
144+
[GoDoc-Url]: https://godoc.org/gopkg.in/oauth2.v3
145+
[GoDoc-Image]: https://godoc.org/gopkg.in/oauth2.v3?status.svg

errors/response.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import "errors"
44

55
// Response error response
66
type Response struct {
7-
Error error `json:"error"`
8-
Description string `json:"error_description,omitempty"`
9-
URI string `json:"error_uri,omitempty"`
10-
StatusCode int `json:"-"`
7+
Error error
8+
ErrorCode int
9+
Description string
10+
URI string
11+
StatusCode int
1112
}
1213

1314
// https://tools.ietf.org/html/rfc6749#section-5.2
@@ -37,3 +38,10 @@ var Descriptions = map[error]string{
3738
ErrInvalidGrant: "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client",
3839
ErrUnsupportedGrantType: "The authorization grant type is not supported by the authorization server",
3940
}
41+
42+
// StatusCodes response error HTTP status code
43+
var StatusCodes = map[error]int{
44+
ErrInvalidClient: 401,
45+
ErrServerError: 500,
46+
ErrTemporarilyUnavailable: 503,
47+
}

example/server/server.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func main() {
5454
http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
5555
err := srv.HandleTokenRequest(w, r)
5656
if err != nil {
57-
http.Error(w, err.Error(), http.StatusBadRequest)
57+
http.Error(w, err.Error(), http.StatusInternalServerError)
5858
}
5959
})
6060

manage/manage_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ func testManager(manager oauth2.Manager) {
4242
}
4343
cti, err := manager.GenerateAuthToken(oauth2.Code, reqParams)
4444
So(err, ShouldBeNil)
45-
Println(cti.GetCode())
4645

4746
code := cti.GetCode()
4847
So(code, ShouldNotBeEmpty)

server/server.go

+41-39
Original file line numberDiff line numberDiff line change
@@ -55,37 +55,33 @@ type Server struct {
5555
AuthorizeScopeHandler AuthorizeScopeHandler
5656
}
5757

58-
// response redirect error
59-
func (s *Server) resRedirectError(w http.ResponseWriter, req *AuthorizeRequest, err error) (uerr error) {
58+
func (s *Server) redirectError(w http.ResponseWriter, req *AuthorizeRequest, err error) (uerr error) {
6059
if req == nil {
6160
uerr = err
6261
return
6362
}
6463
data, _ := s.GetErrorData(err)
65-
err = s.resRedirect(w, req, data)
64+
err = s.redirect(w, req, data)
6665
return
6766
}
6867

69-
func (s *Server) resRedirect(w http.ResponseWriter, req *AuthorizeRequest, data map[string]interface{}) (err error) {
70-
uri, verr := s.GetRedirectURI(req, data)
71-
if verr != nil {
72-
err = verr
68+
func (s *Server) redirect(w http.ResponseWriter, req *AuthorizeRequest, data map[string]interface{}) (err error) {
69+
uri, err := s.GetRedirectURI(req, data)
70+
if err != nil {
7371
return
7472
}
7573
w.Header().Set("Location", uri)
7674
w.WriteHeader(302)
7775
return
7876
}
7977

80-
// response token error
81-
func (s *Server) resTokenError(w http.ResponseWriter, err error) (uerr error) {
78+
func (s *Server) tokenError(w http.ResponseWriter, err error) (uerr error) {
8279
data, statusCode := s.GetErrorData(err)
83-
uerr = s.resToken(w, data, statusCode)
80+
uerr = s.token(w, data, statusCode)
8481
return
8582
}
8683

87-
// response token
88-
func (s *Server) resToken(w http.ResponseWriter, data map[string]interface{}, statusCode ...int) (err error) {
84+
func (s *Server) token(w http.ResponseWriter, data map[string]interface{}, statusCode ...int) (err error) {
8985
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
9086
w.Header().Set("Cache-Control", "no-store")
9187
w.Header().Set("Pragma", "no-cache")
@@ -157,18 +153,19 @@ func (s *Server) CheckResponseType(rt oauth2.ResponseType) bool {
157153

158154
// GetAuthorizeToken get authorization token(code)
159155
func (s *Server) GetAuthorizeToken(req *AuthorizeRequest) (ti oauth2.TokenInfo, err error) {
160-
if req.RedirectURI == "" ||
156+
if req.ResponseType == "" {
157+
err = errors.ErrUnsupportedResponseType
158+
return
159+
} else if req.RedirectURI == "" ||
161160
req.ClientID == "" {
162161
err = errors.ErrInvalidRequest
163162
return
164-
} else if req.ResponseType == "" {
165-
err = errors.ErrUnsupportedResponseType
166-
return
167163
}
168164
if allowed := s.CheckResponseType(req.ResponseType); !allowed {
169165
err = errors.ErrUnauthorizedClient
170166
return
171167
}
168+
// check the client allows the grant type
172169
if fn := s.ClientAuthorizedHandler; fn != nil {
173170
gt := oauth2.AuthorizationCode
174171
if req.ResponseType == oauth2.Token {
@@ -183,6 +180,7 @@ func (s *Server) GetAuthorizeToken(req *AuthorizeRequest) (ti oauth2.TokenInfo,
183180
return
184181
}
185182
}
183+
// check the client allows the authorized scope
186184
if fn := s.ClientScopeHandler; fn != nil {
187185
allowed, verr := fn(req.ClientID, req.Scope)
188186
if verr != nil {
@@ -194,13 +192,11 @@ func (s *Server) GetAuthorizeToken(req *AuthorizeRequest) (ti oauth2.TokenInfo,
194192
}
195193
}
196194
tgr := &oauth2.TokenGenerateRequest{
197-
ClientID: req.ClientID,
198-
UserID: req.UserID,
199-
RedirectURI: req.RedirectURI,
200-
Scope: req.Scope,
201-
}
202-
if exp := req.AccessTokenExp; exp > 0 {
203-
tgr.AccessTokenExp = exp
195+
ClientID: req.ClientID,
196+
UserID: req.UserID,
197+
RedirectURI: req.RedirectURI,
198+
Scope: req.Scope,
199+
AccessTokenExp: req.AccessTokenExp,
204200
}
205201
ti, err = s.Manager.GenerateAuthToken(req.ResponseType, tgr)
206202
return
@@ -222,13 +218,13 @@ func (s *Server) GetAuthorizeData(rt oauth2.ResponseType, ti oauth2.TokenInfo) (
222218
func (s *Server) HandleAuthorizeRequest(w http.ResponseWriter, r *http.Request) (err error) {
223219
req, verr := s.ValidationAuthorizeRequest(r)
224220
if verr != nil {
225-
err = s.resRedirectError(w, req, verr)
221+
err = s.redirectError(w, req, verr)
226222
return
227223
}
228224
// user authorization
229225
userID, verr := s.UserAuthorizationHandler(w, r)
230226
if verr != nil {
231-
err = s.resRedirectError(w, req, verr)
227+
err = s.redirectError(w, req, verr)
232228
return
233229
} else if userID == "" {
234230
return
@@ -250,16 +246,15 @@ func (s *Server) HandleAuthorizeRequest(w http.ResponseWriter, r *http.Request)
250246
if verr != nil {
251247
err = verr
252248
return
253-
} else if exp > 0 {
254-
req.AccessTokenExp = exp
255249
}
250+
req.AccessTokenExp = exp
256251
}
257252
ti, verr := s.GetAuthorizeToken(req)
258253
if verr != nil {
259-
err = s.resRedirectError(w, req, verr)
254+
err = s.redirectError(w, req, verr)
260255
return
261256
}
262-
err = s.resRedirect(w, req, s.GetAuthorizeData(req.ResponseType, ti))
257+
err = s.redirect(w, req, s.GetAuthorizeData(req.ResponseType, ti))
263258
return
264259
}
265260

@@ -433,15 +428,15 @@ func (s *Server) GetTokenData(ti oauth2.TokenInfo) (data map[string]interface{})
433428
func (s *Server) HandleTokenRequest(w http.ResponseWriter, r *http.Request) (err error) {
434429
gt, tgr, verr := s.ValidationTokenRequest(r)
435430
if verr != nil {
436-
err = s.resTokenError(w, verr)
431+
err = s.tokenError(w, verr)
437432
return
438433
}
439434
ti, verr := s.GetAccessToken(gt, tgr)
440435
if verr != nil {
441-
err = s.resTokenError(w, verr)
436+
err = s.tokenError(w, verr)
442437
return
443438
}
444-
err = s.resToken(w, s.GetTokenData(ti))
439+
err = s.token(w, s.GetTokenData(ti))
445440
return
446441
}
447442

@@ -453,24 +448,31 @@ func (s *Server) GetErrorData(err error) (data map[string]interface{}, statusCod
453448
}
454449
err = errors.ErrServerError
455450
}
456-
var re *errors.Response
451+
re := &errors.Response{
452+
Error: err,
453+
Description: errors.Descriptions[err],
454+
StatusCode: errors.StatusCodes[err],
455+
}
457456
if fn := s.ResponseErrorHandler; fn != nil {
458-
re = fn(err)
459-
} else {
460-
re = &errors.Response{
461-
Error: err,
462-
Description: errors.Descriptions[err],
457+
if vre := fn(err); vre != nil {
458+
re = vre
463459
}
464460
}
465461
data = map[string]interface{}{
466462
"error": re.Error.Error(),
467463
}
464+
if v := re.ErrorCode; v != 0 {
465+
data["error_code"] = v
466+
}
468467
if v := re.Description; v != "" {
469468
data["error_description"] = v
470469
}
471470
if v := re.URI; v != "" {
472471
data["error_uri"] = v
473472
}
474-
statusCode = re.StatusCode
473+
statusCode = 400
474+
if v := re.StatusCode; v > 0 {
475+
statusCode = v
476+
}
475477
return
476478
}

0 commit comments

Comments
 (0)