diff --git a/auth/auth.go b/auth/auth.go index c9c77a1c6..8775ad6e9 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -81,13 +81,12 @@ func New(ctx context.Context, log *zap.Logger, s store.Storer, opt options.AuthO handlers.GetLinks().OAuth2AuthorizeClient, )) - oauth2Server.SetClientAuthorizedHandler(func(id string, grant oauth2def.GrantType) (bool, error) { + oauth2Server.SetClientAuthorizedHandler(func(id string, grant oauth2def.GrantType) (allowed bool, err error) { // this is a bit silly and a bad design of the oauth2 server lib // why do we need to keep on load the client?? var ( clientID uint64 client *types.AuthClient - err error ) clientID, err = strconv.ParseUint(id, 10, 64) @@ -108,7 +107,7 @@ func New(ctx context.Context, log *zap.Logger, s store.Storer, opt options.AuthO return true, nil }) - oauth2Server.SetClientScopeHandler(func(id, ss string) (allowed bool, err error) { + oauth2Server.SetClientScopeHandler(func(tgr *oauth2def.TokenGenerateRequest) (allowed bool, err error) { // this is a bit silly and a bad design of the oauth2 server lib // why do we need to keep on load the client?? var ( @@ -116,7 +115,7 @@ func New(ctx context.Context, log *zap.Logger, s store.Storer, opt options.AuthO client *types.AuthClient ) - clientID, err = strconv.ParseUint(id, 10, 64) + clientID, err = strconv.ParseUint(tgr.ClientID, 10, 64) if err != nil { return false, fmt.Errorf("could not authorize client: %w", err) } @@ -127,7 +126,7 @@ func New(ctx context.Context, log *zap.Logger, s store.Storer, opt options.AuthO } // ensure all requested scopes are allowed on a client - for _, scope := range strings.Split(ss, " ") { + for _, scope := range strings.Split(tgr.Scope, " ") { if !auth.CheckScope(client.Scope, scope) { return false, fmt.Errorf("client does not allow use of '%s' scope", scope) } diff --git a/auth/handlers/handle_oauth2.go b/auth/handlers/handle_oauth2.go index d005dcb63..292970149 100644 --- a/auth/handlers/handle_oauth2.go +++ b/auth/handlers/handle_oauth2.go @@ -160,22 +160,10 @@ func (h AuthHandlers) oauth2Token(req *request.AuthReq) (err error) { client, err := h.loadRequestedClient(req) if err != nil { - return + return h.tokenError(req.Response, err) } - if err = client.Verify(); err != nil { - return fmt.Errorf("invalid client: %w", err) - } else { - // add client to context so we can reach it from client store via context.Value() fn - // - // this way we work around the limitations we have with the oauth2 lib. - r := req.Request.Clone(context.WithValue(req.Context(), &oauth2.ContextClientStore{}, client)) - - // handle token request with extended context that now holds client! - err = h.OAuth2.HandleTokenRequest(req.Response, r) - } - - return + return h.handleTokenRequest(req, client) } func (h AuthHandlers) oauth2Info(w http.ResponseWriter, r *http.Request) { @@ -289,8 +277,9 @@ func (h AuthHandlers) oauth2authorizeDefaultClientProc(req *request.AuthReq) (er h.DefaultClient.Secret, ) - req.Status = -1 - return h.OAuth2.HandleTokenRequest(req.Response, r) + req.Request = r + + return h.handleTokenRequest(req, h.DefaultClient) } func (h AuthHandlers) verifyDefaultClient() error { @@ -356,6 +345,58 @@ func (h AuthHandlers) loadRequestedClient(req *request.AuthReq) (client *types.A }() } +func (h AuthHandlers) handleTokenRequest(req *request.AuthReq, client *types.AuthClient) error { + req.Status = -1 + + var ( + r = req.Request + w = req.Response + ctx = req.Context() + ) + + req.Status = -1 + + if err := client.Verify(); err != nil { + return h.tokenError(w, fmt.Errorf("invalid client: %w", err)) + } + + // add client to context so we can reach it from client store via context.Value() fn + // this way we work around the limitations we have with the oauth2 lib. + ctx = context.WithValue(ctx, &oauth2.ContextClientStore{}, client) + r = req.Request.Clone(ctx) + + gt, tgr, err := h.OAuth2.ValidationTokenRequest(r) + if err != nil { + return h.tokenError(w, err) + } + + if gt == oauth2def.ClientCredentials { + // Authenticated with client credentials! + // + // We'll use info from client security + if client.Security == nil || client.Security.ImpersonateUser == 0 { + return h.tokenError(w, errors.Internal("auth client security configuration invalid")) + } + + tgr.UserID = strings.Join(append( + []string{fmt.Sprintf("%d", client.Security.ImpersonateUser)}, + client.Security.ForcedRoles..., + ), " ") + } + + ti, err := h.OAuth2.GetAccessToken(ctx, gt, tgr) + if err != nil { + return h.tokenError(w, err) + } + + return token(w, h.OAuth2.GetTokenData(ti), nil) +} + +func (h AuthHandlers) tokenError(w http.ResponseWriter, err error) error { + data, statusCode, header := h.OAuth2.GetErrorData(err) + return token(w, data, header, statusCode) +} + func SubSplit(ti oauth2def.TokenInfo, data map[string]interface{}) { userIdWithRoles := strings.SplitN(ti.GetUserID(), " ", 2) data["sub"] = userIdWithRoles[0] @@ -395,3 +436,21 @@ func Profile(ctx context.Context, ti oauth2def.TokenInfo, data map[string]interf return nil } + +func token(w http.ResponseWriter, data map[string]interface{}, header http.Header, statusCode ...int) error { + w.Header().Set("Content-Type", "application/json;charset=UTF-8") + w.Header().Set("Cache-Control", "no-store") + w.Header().Set("Pragma", "no-cache") + + for key := range header { + w.Header().Set(key, header.Get(key)) + } + + status := http.StatusOK + if len(statusCode) > 0 && statusCode[0] > 0 { + status = statusCode[0] + } + + w.WriteHeader(status) + return json.NewEncoder(w).Encode(data) +} diff --git a/auth/oauth2/corteza_token_store.go b/auth/oauth2/corteza_token_store.go index 3e09df262..13065e2aa 100644 --- a/auth/oauth2/corteza_token_store.go +++ b/auth/oauth2/corteza_token_store.go @@ -83,7 +83,7 @@ func (c CortezaTokenStore) Create(ctx context.Context, info oauth2.TokenInfo) (e if info.GetUserID() != "" { if oa2t.UserID = auth.ExtractUserIDFromSubClaim(info.GetUserID()); oa2t.UserID == 0 { // UserID stores collection of IDs: user's ID and set of all roles user is member of - return fmt.Errorf("could not parse user ID from token info: %w", err) + return fmt.Errorf("could not parse user ID from token info") } } diff --git a/auth/oauth2/oauth2.go b/auth/oauth2/oauth2.go index 8b9ce0f2e..8f1c478b1 100644 --- a/auth/oauth2/oauth2.go +++ b/auth/oauth2/oauth2.go @@ -71,8 +71,7 @@ func NewServer(manager *manage.Manager) *server.Server { oauth2.Refreshing, // before enabling ClientCredentials grant type, we need to know how to modify released token // using client's security info; how to enforce impersonated user and his roles. - // - // oauth2.ClientCredentials, + oauth2.ClientCredentials, }, AllowedCodeChallengeMethods: []oauth2.CodeChallengeMethod{ oauth2.CodeChallengePlain, diff --git a/auth/oauth2/user_authorizer.go b/auth/oauth2/user_authorizer.go index 4d4331f6b..3cf5ba6be 100644 --- a/auth/oauth2/user_authorizer.go +++ b/auth/oauth2/user_authorizer.go @@ -9,6 +9,7 @@ import ( func NewUserAuthorizer(sm *request.SessionManager, loginURL, clientAuthURL string) server.UserAuthorizationHandler { return func(w http.ResponseWriter, r *http.Request) (identity string, err error) { + var ( ses = sm.Get(r) au = request.GetAuthUser(ses) diff --git a/go.mod b/go.mod index 4433ab157..768f089c7 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/go-chi/cors v1.0.0 github.com/go-chi/httprate v0.4.0 github.com/go-chi/jwtauth v0.0.0-20190109153619-47840abb19b3 - github.com/go-oauth2/oauth2/v4 v4.2.0 + github.com/go-oauth2/oauth2/v4 v4.3.0 github.com/go-sql-driver/mysql v1.5.0 github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.4.2 @@ -55,7 +55,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect github.com/prometheus/client_golang v0.9.3 - github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b // indirect github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect github.com/sony/sonyflake v0.0.0-20181109022403-6d5bd6181009 github.com/spf13/afero v1.2.2 diff --git a/go.sum b/go.sum index 5e05f5152..c2cfc566b 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,6 @@ github.com/Masterminds/squirrel v1.1.1-0.20191017225151-12f2162c8d8d/go.mod h1:y github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PaesslerAG/gval v0.1.1/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= -github.com/PaesslerAG/gval v1.1.0 h1:k3RuxeZDO3eejD4cMPSt+74tUSvTnbGvLx0df4mdwFc= -github.com/PaesslerAG/gval v1.1.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= github.com/PaesslerAG/gval v1.1.1-0.20201104175134-7847ed0c7671 h1:mXmNWMJr5OPcaA00ryiN+FZphVa1EtUYiVNH8nfWALY= github.com/PaesslerAG/gval v1.1.1-0.20201104175134-7847ed0c7671/go.mod h1:Fa8gfkCmUsELXgayr8sfL/sw+VzCVoa03dcOcR/if2w= github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= @@ -136,6 +134,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-oauth2/oauth2/v4 v4.2.0 h1:wz9w9SwHrzC58XniFSGXIfl2R5Q6x1aecVuL/QBupl8= github.com/go-oauth2/oauth2/v4 v4.2.0/go.mod h1:+rsyi0o/ZbSfhL/3Xr/sAtL4brS+IdGj86PHVlPjE+4= +github.com/go-oauth2/oauth2/v4 v4.3.0 h1:vp4goUmrq1YaPzpm34FDLlZiAkIqK3LsuNTTRyTnPbo= +github.com/go-oauth2/oauth2/v4 v4.3.0/go.mod h1:+rsyi0o/ZbSfhL/3Xr/sAtL4brS+IdGj86PHVlPjE+4= github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= @@ -320,8 +320,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b h1:aUNXCGgukb4gtY99imuIeoh8Vr0GSwAlYxPAhqZrpFc= -github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= @@ -411,8 +409,6 @@ go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/pkg/auth/middleware.go b/pkg/auth/middleware.go index 1ecf8e589..5a025f1e3 100644 --- a/pkg/auth/middleware.go +++ b/pkg/auth/middleware.go @@ -7,19 +7,29 @@ import ( ) func MiddlewareValidOnly(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var ctx = r.Context() + return AccessTokenCheck("api")(next) +} - if !CheckScope(ctx.Value(scopeCtxKey{}), "api") { - api.Send(w, r, errors.New("Unauthorized scope")) - return - } +func AccessTokenCheck(scope ...string) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var ctx = r.Context() - if !GetIdentityFromContext(ctx).Valid() { - api.Send(w, r, errors.New("Unauthorized")) - return - } + for _, s := range scope { + if !CheckScope(ctx.Value(scopeCtxKey{}), s) { + w.WriteHeader(http.StatusUnauthorized) + api.Send(w, r, errors.New("unauthorized scope")) + return + } + } - next.ServeHTTP(w, r) - }) + if !GetIdentityFromContext(ctx).Valid() { + w.WriteHeader(http.StatusUnauthorized) + api.Send(w, r, errors.New("unauthorized")) + return + } + + next.ServeHTTP(w, r) + }) + } } diff --git a/system/types/auth_client.go b/system/types/auth_client.go index 5179a4085..d058bb2ec 100644 --- a/system/types/auth_client.go +++ b/system/types/auth_client.go @@ -12,7 +12,6 @@ import ( ) type ( - // AuthClient - An organisation may have many authClients. AuthClients may have many channels available. Access to channels may be shared between authClients. AuthClient struct { ID uint64 `json:"authClientID,string"` @@ -70,7 +69,7 @@ type ( AuthClientSecurity struct { // Impersonates a specific user; // ignored when non client-credentials grant is used - //ImpersonateUser uint64 `json:"impersonateUser,string,omitempty"` + ImpersonateUser uint64 `json:"impersonateUser,string,omitempty"` // Subset of roles, permitted to be used with this client // IDs are intentionally stored as strings to support JS (int64 only) @@ -146,7 +145,7 @@ func (set AuthClientSet) FindByHandle(handle string) *AuthClient { func (r *AuthClient) Verify() error { switch { - case !r.Enabled: + case r == nil || !r.Enabled: return fmt.Errorf("disabled") case r.ExpiresAt != nil && r.ExpiresAt.After(time.Now()): return fmt.Errorf("expired") diff --git a/system/types/role.go b/system/types/role.go index 09d3a6a0e..46d6088b2 100644 --- a/system/types/role.go +++ b/system/types/role.go @@ -8,7 +8,6 @@ import ( ) type ( - // Role - An organisation may have many roles. Roles may have many channels available. Access to channels may be shared between roles. Role struct { ID uint64 `json:"roleID,string"` Name string `json:"name"` diff --git a/vendor/github.com/go-oauth2/oauth2/v4/README.md b/vendor/github.com/go-oauth2/oauth2/v4/README.md index cb05e2834..d55587550 100644 --- a/vendor/github.com/go-oauth2/oauth2/v4/README.md +++ b/vendor/github.com/go-oauth2/oauth2/v4/README.md @@ -2,11 +2,11 @@ > An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications. -[![Build][Build-Status-Image]][Build-Status-Url] [![Codecov][codecov-image]][codecov-url] [![ReportCard][reportcard-image]][reportcard-url] [![GoDoc][godoc-image]][godoc-url] [![License][license-image]][license-url] +[![Build][build-status-image]][build-status-url] [![Codecov][codecov-image]][codecov-url] [![ReportCard][reportcard-image]][reportcard-url] [![GoDoc][godoc-image]][godoc-url] [![License][license-image]][license-url] ## Protocol Flow -``` text +```text +--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | @@ -30,13 +30,13 @@ ### Download and install -``` bash +```bash go get -u -v github.com/go-oauth2/oauth2/v4/... ``` ### Create file `server.go` -``` go +```go package main import ( @@ -95,7 +95,7 @@ func main() { ### Build and run -``` bash +```bash go build server.go ./server @@ -105,24 +105,24 @@ go build server.go [http://localhost:9096/token?grant_type=client_credentials&client_id=000000&client_secret=999999&scope=read](http://localhost:9096/token?grant_type=client_credentials&client_id=000000&client_secret=999999&scope=read) -``` json +```json { - "access_token": "J86XVRYSNFCFI233KXDL0Q", - "expires_in": 7200, - "scope": "read", - "token_type": "Bearer" + "access_token": "J86XVRYSNFCFI233KXDL0Q", + "expires_in": 7200, + "scope": "read", + "token_type": "Bearer" } ``` ## Features -* Easy to use -* Based on the [RFC 6749](https://tools.ietf.org/html/rfc6749) implementation -* Token storage support TTL -* Support custom expiration time of the access token -* Support custom extension field -* Support custom scope -* Support jwt to generate access tokens +- Easy to use +- Based on the [RFC 6749](https://tools.ietf.org/html/rfc6749) implementation +- Token storage support TTL +- Support custom expiration time of the access token +- Support custom extension field +- Support custom scope +- Support jwt to generate access tokens ## Example @@ -161,27 +161,28 @@ if !ok || !token.Valid { ## Store Implements -* [BuntDB](https://github.com/tidwall/buntdb)(default store) -* [Redis](https://github.com/go-oauth2/redis) -* [MongoDB](https://github.com/go-oauth2/mongo) -* [MySQL](https://github.com/go-oauth2/mysql) -* [MySQL (Provides both client and token store)](https://github.com/imrenagi/go-oauth2-mysql) -* [PostgreSQL](https://github.com/vgarvardt/go-oauth2-pg) -* [DynamoDB](https://github.com/contamobi/go-oauth2-dynamodb) -* [XORM](https://github.com/techknowlogick/go-oauth2-xorm) -* [GORM](https://github.com/techknowlogick/go-oauth2-gorm) -* [Firestore](https://github.com/tslamic/go-oauth2-firestore) +- [BuntDB](https://github.com/tidwall/buntdb)(default store) +- [Redis](https://github.com/go-oauth2/redis) +- [MongoDB](https://github.com/go-oauth2/mongo) +- [MySQL](https://github.com/go-oauth2/mysql) +- [MySQL (Provides both client and token store)](https://github.com/imrenagi/go-oauth2-mysql) +- [PostgreSQL](https://github.com/vgarvardt/go-oauth2-pg) +- [DynamoDB](https://github.com/contamobi/go-oauth2-dynamodb) +- [XORM](https://github.com/techknowlogick/go-oauth2-xorm) +- [XORM (MySQL, client and token store)](https://github.com/rainlay/go-oauth2-xorm) +- [GORM](https://github.com/techknowlogick/go-oauth2-gorm) +- [Firestore](https://github.com/tslamic/go-oauth2-firestore) ## Handy Utilities -* [OAuth2 Proxy Logger (Debug utility that proxies interfaces and logs)](https://github.com/aubelsb2/oauth2-logger-proxy) +- [OAuth2 Proxy Logger (Debug utility that proxies interfaces and logs)](https://github.com/aubelsb2/oauth2-logger-proxy) ## MIT License - Copyright (c) 2016 Lyric +Copyright (c) 2016 Lyric -[Build-Status-Url]: https://travis-ci.org/go-oauth2/oauth2 -[Build-Status-Image]: https://travis-ci.org/go-oauth2/oauth2.svg?branch=master +[build-status-url]: https://travis-ci.org/go-oauth2/oauth2 +[build-status-image]: https://travis-ci.org/go-oauth2/oauth2.svg?branch=master [codecov-url]: https://codecov.io/gh/go-oauth2/oauth2 [codecov-image]: https://codecov.io/gh/go-oauth2/oauth2/branch/master/graph/badge.svg [reportcard-url]: https://goreportcard.com/report/github.com/go-oauth2/oauth2/v4 diff --git a/vendor/github.com/go-oauth2/oauth2/v4/server/handler.go b/vendor/github.com/go-oauth2/oauth2/v4/server/handler.go index a5fd13904..bb2c6d811 100644 --- a/vendor/github.com/go-oauth2/oauth2/v4/server/handler.go +++ b/vendor/github.com/go-oauth2/oauth2/v4/server/handler.go @@ -16,7 +16,7 @@ type ( ClientAuthorizedHandler func(clientID string, grant oauth2.GrantType) (allowed bool, err error) // ClientScopeHandler check the client allows to use scope - ClientScopeHandler func(clientID, scope string) (allowed bool, err error) + ClientScopeHandler func(tgr *oauth2.TokenGenerateRequest) (allowed bool, err error) // UserAuthorizationHandler get user id from request authorization UserAuthorizationHandler func(w http.ResponseWriter, r *http.Request) (userID string, err error) @@ -25,9 +25,9 @@ type ( PasswordAuthorizationHandler func(username, password string) (userID string, err error) // RefreshingScopeHandler check the scope of the refreshing token - RefreshingScopeHandler func(newScope, oldScope string) (allowed bool, err error) + RefreshingScopeHandler func(tgr *oauth2.TokenGenerateRequest, oldScope string) (allowed bool, err error) - //RefreshingValidationHandler check if refresh_token is still valid. eg no revocation or other + // RefreshingValidationHandler check if refresh_token is still valid. eg no revocation or other RefreshingValidationHandler func(ti oauth2.TokenInfo) (allowed bool, err error) // ResponseErrorHandler response error handing diff --git a/vendor/github.com/go-oauth2/oauth2/v4/server/server.go b/vendor/github.com/go-oauth2/oauth2/v4/server/server.go index 4e1215fc7..af911f429 100644 --- a/vendor/github.com/go-oauth2/oauth2/v4/server/server.go +++ b/vendor/github.com/go-oauth2/oauth2/v4/server/server.go @@ -214,7 +214,15 @@ func (s *Server) GetAuthorizeToken(ctx context.Context, req *AuthorizeRequest) ( // check the client allows the authorized scope if fn := s.ClientScopeHandler; fn != nil { - allowed, err := fn(req.ClientID, req.Scope) + tgr := &oauth2.TokenGenerateRequest{ + ClientID: req.ClientID, + UserID: req.UserID, + RedirectURI: req.RedirectURI, + Scope: req.Scope, + AccessTokenExp: req.AccessTokenExp, + Request: req.Request, + } + allowed, err := fn(tgr) if err != nil { return nil, err } else if !allowed { @@ -311,11 +319,6 @@ func (s *Server) ValidationTokenRequest(r *http.Request) (oauth2.GrantType, *oau return "", nil, errors.ErrUnsupportedGrantType } - codeVer := r.FormValue("code_verifier") - if s.Config.ForcePKCE && codeVer == "" { - return "", nil, errors.ErrInvalidRequest - } - clientID, clientSecret, err := s.ClientInfoHandler(r) if err != nil { return "", nil, err @@ -335,7 +338,10 @@ func (s *Server) ValidationTokenRequest(r *http.Request) (oauth2.GrantType, *oau tgr.Code == "" { return "", nil, errors.ErrInvalidRequest } - tgr.CodeVerifier = codeVer + tgr.CodeVerifier = r.FormValue("code_verifier") + if s.Config.ForcePKCE && tgr.CodeVerifier == "" { + return "", nil, errors.ErrInvalidRequest + } case oauth2.PasswordCredentials: tgr.Scope = r.FormValue("scope") username, password := r.FormValue("username"), r.FormValue("password") @@ -404,7 +410,7 @@ func (s *Server) GetAccessToken(ctx context.Context, gt oauth2.GrantType, tgr *o return ti, nil case oauth2.PasswordCredentials, oauth2.ClientCredentials: if fn := s.ClientScopeHandler; fn != nil { - allowed, err := fn(tgr.ClientID, tgr.Scope) + allowed, err := fn(tgr) if err != nil { return nil, err } else if !allowed { @@ -423,7 +429,7 @@ func (s *Server) GetAccessToken(ctx context.Context, gt oauth2.GrantType, tgr *o return nil, err } - allowed, err := scopeFn(scope, rti.GetScope()) + allowed, err := scopeFn(tgr, rti.GetScope()) if err != nil { return nil, err } else if !allowed { diff --git a/vendor/modules.txt b/vendor/modules.txt index 9ca31ff24..ea21c488e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -82,7 +82,7 @@ github.com/go-chi/httprate # github.com/go-chi/jwtauth v0.0.0-20190109153619-47840abb19b3 ## explicit github.com/go-chi/jwtauth -# github.com/go-oauth2/oauth2/v4 v4.2.0 +# github.com/go-oauth2/oauth2/v4 v4.3.0 ## explicit github.com/go-oauth2/oauth2/v4 github.com/go-oauth2/oauth2/v4/errors @@ -212,8 +212,6 @@ github.com/prometheus/common/model # github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs -# github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b -## explicit # github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd ## explicit github.com/rwcarlsen/goexif/exif