func (a *Authenticator) Authorizer(scope string, force, loadClient, loadResourceOwner bool) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// create tracer
			tracer := fire.NewTracerFromRequest(r, "flame/Authenticator.Authorizer")
			tracer.Tag("scope", scope)
			tracer.Tag("force", force)
			tracer.Tag("loadClient", loadClient)
			tracer.Tag("loadResourceOwner", loadResourceOwner)
			defer tracer.Finish(true)

			// add span to context
			r = r.WithContext(tracer.Context(r.Context()))

			// immediately pass on request if force is not set and there is
			// no authentication information provided
			if !force && r.Header.Get("Authorization") == "" {
				// call next handler
				next.ServeHTTP(w, r)

				return
			}

			// continue any previous aborts
			defer stack.Resume(func(err error) {
				// directly write bearer errors
				if bearerError, ok := err.(*bearer.Error); ok {
					_ = bearer.WriteError(w, bearerError)
					return
				}

				// set critical error on last span
				tracer.Tag("error", true)
				tracer.Log("error", err.Error())
				tracer.Log("stack", stack.Trace())

				// otherwise report critical errors
				if a.Reporter != nil {
					a.Reporter(err)
				}

				// ignore errors caused by writing critical errors
				_ = bearer.WriteError(w, bearer.ServerError())
			})

			// parse scope
			s := oauth2.ParseScope(scope)

			// parse bearer token
			tk, err := bearer.ParseToken(r)
			stack.AbortIf(err)

			// parse token
			claims, expired, err := a.policy.ParseToken(tk)
			if expired {
				stack.Abort(bearer.InvalidToken("expired token"))
			} else if err != nil {
				stack.Abort(bearer.InvalidToken("malformed token"))
			}

			// copy store
			store := a.store.Copy()
			defer store.Close()

			// create state
			state := &state{
				request: r,
				writer:  w,
				store:   store,
				tracer:  tracer,
			}

			// get token
			accessToken := a.getToken(state, a.policy.Token, bson.ObjectIdHex(claims.Id))
			if accessToken == nil {
				stack.Abort(bearer.InvalidToken("unknown token"))
			}

			// get additional data
			typ, scope, expiresAt, clientID, resourceOwnerID := accessToken.GetTokenData()

			// validate token type
			if typ != AccessToken {
				stack.Abort(bearer.InvalidToken("invalid type"))
			}

			// validate expiration
			if expiresAt.Before(time.Now()) {
				stack.Abort(bearer.InvalidToken("expired token"))
			}

			// validate scope
			if !oauth2.Scope(scope).Includes(s) {
				stack.Abort(bearer.InsufficientScope(s.String()))
			}

			// create new context with access token
			ctx := context.WithValue(r.Context(), AccessTokenContextKey, accessToken)

			// call next handler if client should not be loaded
			if !loadClient {
				// call next handler
				next.ServeHTTP(w, r.WithContext(ctx))

				return
			}

			// get client
			client := a.getFirstClient(state, clientID)
			if client == nil {
				stack.Abort(errors.New("missing client"))
			}

			// create new context with client
			ctx = context.WithValue(ctx, ClientContextKey, client)

			// call next handler if resource owner does not exist or should not
			// be loaded
			if resourceOwnerID == nil || !loadResourceOwner {
				// call next handler
				next.ServeHTTP(w, r.WithContext(ctx))

				return
			}

			// get resource owner
			resourceOwner := a.getFirstResourceOwner(state, client, *resourceOwnerID)
			if resourceOwner == nil {
				stack.Abort(errors.New("missing resource owner"))
			}

			// create new context with resource owner
			ctx = context.WithValue(ctx, ResourceOwnerContextKey, resourceOwner)

			// call next handler
			next.ServeHTTP(w, r.WithContext(ctx))
		})
	}
}
func (a *Authenticator) Authorizer(scope string, force, loadClient, loadResourceOwner bool) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			
			tracer := fire.NewTracerFromRequest(r, "flame/Authenticator.Authorizer")
			tracer.Tag("scope", scope)
			tracer.Tag("force", force)
			tracer.Tag("loadClient", loadClient)
			tracer.Tag("loadResourceOwner", loadResourceOwner)
			defer tracer.Finish(true)

			
			r = r.WithContext(tracer.Context(r.Context()))

			
			
			if !force && r.Header.Get("Authorization") == "" {
				
				next.ServeHTTP(w, r)

				return
			}

			
			defer stack.Resume(func(err error) {
				
				if bearerError, ok := err.(*bearer.Error); ok {
					_ = bearer.WriteError(w, bearerError)
					return
				}

				
				tracer.Tag("error", true)
				tracer.Log("error", err.Error())
				tracer.Log("stack", stack.Trace())

				
				if a.Reporter != nil {
					a.Reporter(err)
				}

				
				_ = bearer.WriteError(w, bearer.ServerError())
			})

			
			s := oauth2.ParseScope(scope)

			
			tk, err := bearer.ParseToken(r)
			stack.AbortIf(err)

			
			claims, expired, err := a.policy.ParseToken(tk)
			if expired {
				stack.Abort(bearer.InvalidToken("expired token"))
			} else if err != nil {
				stack.Abort(bearer.InvalidToken("malformed token"))
			}

			
			store := a.store.Copy()
			defer store.Close()

			
			state := &state{
				request: r,
				writer:  w,
				store:   store,
				tracer:  tracer,
			}

			
			accessToken := a.getToken(state, a.policy.Token, bson.ObjectIdHex(claims.Id))
			if accessToken == nil {
				stack.Abort(bearer.InvalidToken("unknown token"))
			}

			
			typ, scope, expiresAt, clientID, resourceOwnerID := accessToken.GetTokenData()

			
			if typ != AccessToken {
				stack.Abort(bearer.InvalidToken("invalid type"))
			}

			
			if expiresAt.Before(time.Now()) {
				stack.Abort(bearer.InvalidToken("expired token"))
			}

			
			if !oauth2.Scope(scope).Includes(s) {
				stack.Abort(bearer.InsufficientScope(s.String()))
			}

			
			ctx := context.WithValue(r.Context(), AccessTokenContextKey, accessToken)

			
			if !loadClient {
				
				next.ServeHTTP(w, r.WithContext(ctx))

				return
			}

			
			client := a.getFirstClient(state, clientID)
			if client == nil {
				stack.Abort(errors.New("missing client"))
			}

			
			ctx = context.WithValue(ctx, ClientContextKey, client)

			
			
			if resourceOwnerID == nil || !loadResourceOwner {
				
				next.ServeHTTP(w, r.WithContext(ctx))

				return
			}

			
			resourceOwner := a.getFirstResourceOwner(state, client, *resourceOwnerID)
			if resourceOwner == nil {
				stack.Abort(errors.New("missing resource owner"))
			}

			
			ctx = context.WithValue(ctx, ResourceOwnerContextKey, resourceOwner)

			
			next.ServeHTTP(w, r.WithContext(ctx))
		})
	}
}
func ( a * Authenticator ) Authorizer ( scope string , force , loadClient , loadResourceOwner bool ) func ( http . Handler ) http . Handler { return func ( next http . Handler ) http . Handler { return http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) { // create tracer tracer := fire . NewTracerFromRequest ( r , " " ) tracer . Tag ( " " , scope ) tracer . Tag ( " " , force ) tracer . Tag ( " " , loadClient ) tracer . Tag ( " " , loadResourceOwner ) defer tracer . Finish ( true ) // add span to context r = r . WithContext ( tracer . Context ( r . Context ( ) ) ) // immediately pass on request if force is not set and there is // no authentication information provided if ! force && r . Header . Get ( " " ) == " " { // call next handler next . ServeHTTP ( w , r ) return } // continue any previous aborts defer stack . Resume ( func ( err error ) { // directly write bearer errors if bearerError , ok := err . ( * bearer . Error ) ; ok { _ = bearer . WriteError ( w , bearerError ) return } // set critical error on last span tracer . Tag ( " " , true ) tracer . Log ( " " , err . Error ( ) ) tracer . Log ( " " , stack . Trace ( ) ) // otherwise report critical errors if a . Reporter != nil { a . Reporter ( err ) } // ignore errors caused by writing critical errors _ = bearer . WriteError ( w , bearer . ServerError ( ) ) } ) // parse scope s := oauth2 . ParseScope ( scope ) // parse bearer token tk , err := bearer . ParseToken ( r ) stack . AbortIf ( err ) // parse token claims , expired , err := a . policy . ParseToken ( tk ) if expired { stack . Abort ( bearer . InvalidToken ( " " ) ) } else if err != nil { stack . Abort ( bearer . InvalidToken ( " " ) ) } // copy store store := a . store . Copy ( ) defer store . Close ( ) // create state state := & state { request : r , writer : w , store : store , tracer : tracer , } // get token accessToken := a . getToken ( state , a . policy . Token , bson . ObjectIdHex ( claims . Id ) ) if accessToken == nil { stack . Abort ( bearer . InvalidToken ( " " ) ) } // get additional data typ , scope , expiresAt , clientID , resourceOwnerID := accessToken . GetTokenData ( ) // validate token type if typ != AccessToken { stack . Abort ( bearer . InvalidToken ( " " ) ) } // validate expiration if expiresAt . Before ( time . Now ( ) ) { stack . Abort ( bearer . InvalidToken ( " " ) ) } // validate scope if ! oauth2 . Scope ( scope ) . Includes ( s ) { stack . Abort ( bearer . InsufficientScope ( s . String ( ) ) ) } // create new context with access token ctx := context . WithValue ( r . Context ( ) , AccessTokenContextKey , accessToken ) // call next handler if client should not be loaded if ! loadClient { // call next handler next . ServeHTTP ( w , r . WithContext ( ctx ) ) return } // get client client := a . getFirstClient ( state , clientID ) if client == nil { stack . Abort ( errors . New ( " " ) ) } // create new context with client ctx = context . WithValue ( ctx , ClientContextKey , client ) // call next handler if resource owner does not exist or should not // be loaded if resourceOwnerID == nil || ! loadResourceOwner { // call next handler next . ServeHTTP ( w , r . WithContext ( ctx ) ) return } // get resource owner resourceOwner := a . getFirstResourceOwner ( state , client , * resourceOwnerID ) if resourceOwner == nil { stack . Abort ( errors . New ( " " ) ) } // create new context with resource owner ctx = context . WithValue ( ctx , ResourceOwnerContextKey , resourceOwner ) // call next handler next . ServeHTTP ( w , r . WithContext ( ctx ) ) } ) } }
// Authorizer returns a middleware that can be used to authorize a request by
// requiring an access token with the provided scope to be granted.
Authorizer returns a middleware that can be used to authorize a request by requiring an access token with the provided scope to be granted .