~bigbes/core-go

d3f7b91ae41a41d56a78de7eb065f15b1a155851 — Drew DeVault 1 year, 6 months ago 465a6f7
webhooks: implement internal webhook users

AUTH_INTERNAL requests previously could not register webhooks. This
commit adds the necessary changes to allow for this.
3 files changed, 43 insertions(+), 20 deletions(-)

M auth/middleware.go
M webhooks/config.go
M webhooks/context.go
M auth/middleware.go => auth/middleware.go +6 -3
@@ 77,8 77,10 @@ type AuthContext struct {

	// Only filled out if AuthMethod == AUTH_OAUTH2 or AUTH_WEBHOOK
	BearerToken *BearerToken
	Grants      Grants
	TokenHash   [64]byte

	// AUTH_OAUTH2, AUTH_WEBHOOK, AUTH_INTERNAL
	Grants Grants
}

func (authctx *AuthContext) Access(scope, kind string) error {


@@ 295,6 297,7 @@ func internalAuth(payload []byte, w http.ResponseWriter, r *http.Request, next h
	}

	auth.InternalAuth = internalAuth
	auth.Grants, _ = DecodeGrants(r.Context(), "")

	auth.IPAddress = r.RemoteAddr
	var route []string


@@ 660,8 663,8 @@ func LegacyOAuth(bearer string, hash [64]byte, w http.ResponseWriter,
// webhook to be fired.
func WebhookAuth(ctx context.Context, auth *AuthContext,
	tokenHash [64]byte, rawGrants string, clientID *string,
	expires time.Time) (context.Context, error) {
	if time.Now().UTC().After(expires) {
	expires *time.Time) (context.Context, error) {
	if expires != nil && time.Now().UTC().After(*expires) {
		return nil, fmt.Errorf("The authentication token used to create this webhook has expired")
	}


M webhooks/config.go => webhooks/config.go +6 -2
@@ 7,6 7,7 @@ import (
	"time"

	"git.sr.ht/~sircmpwn/core-go/auth"
	"git.sr.ht/~sircmpwn/core-go/config"
	sq "github.com/Masterminds/squirrel"
)



@@ 53,8 54,11 @@ func NewAuthConfig(ctx context.Context) (AuthConfig, error) {
		// TODO: Should this work?
		return AuthConfig{}, fmt.Errorf("Native webhooks are not supported with web authentication")
	case auth.AUTH_INTERNAL:
		// TODO: Should this work?
		panic(fmt.Errorf("Internal webtoken auth is not supported"))
		nodeID := config.ServiceName(ctx)
		return AuthConfig{
			AuthMethod: user.AuthMethod,
			NodeID:     &nodeID,
		}, nil
	case auth.AUTH_WEBHOOK:
		panic(fmt.Errorf("Recursive webhook auth is not supported"))
	}

M webhooks/context.go => webhooks/context.go +31 -15
@@ 49,23 49,39 @@ func Payload(ctx context.Context) (interface{}, error) {
// the configuration of a secondary authentication and GraphQL context.
func (webhook *WebhookContext) Exec(ctx context.Context,
	schema graphql.ExecutableSchema) ([]byte, error) {
	var (
		err       error
		tokenHash [64]byte
	)
	sub := webhook.Subscription
	if sub.AuthMethod != auth.AUTH_OAUTH2 {
		panic(fmt.Errorf("TODO"))
	}
	tslice, err := hex.DecodeString(*sub.TokenHash)
	if err != nil {
		panic(err)
	}

	var tokenHash [64]byte
	copy(tokenHash[:], tslice)
	ctx, err = auth.WebhookAuth(ctx, webhook.User,
		tokenHash, *sub.Grants, sub.ClientID, *sub.Expires)
	if err != nil {
		// TODO: This codepath can occur when the token has expired, and we may
		// want to communicate this to the user.
		return nil, err
	switch sub.AuthMethod {
	case auth.AUTH_OAUTH2:
		tslice, err := hex.DecodeString(*sub.TokenHash)
		if err != nil {
			panic(err)
		}
		if sub.Expires == nil {
			panic(fmt.Errorf("OAuth 2 token has no expiry?"))
		}

		copy(tokenHash[:], tslice)
		ctx, err = auth.WebhookAuth(ctx, webhook.User,
			tokenHash, *sub.Grants, sub.ClientID, sub.Expires)
		if err != nil {
			// TODO: This codepath can occur when the token has
			// expired, and we may want to communicate this to the
			// user.
			return nil, err
		}
	case auth.AUTH_INTERNAL:
		ctx, err = auth.WebhookAuth(ctx, webhook.User,
			tokenHash, "", nil, nil)
		if err != nil {
			panic(err)
		}
	default:
		panic(fmt.Errorf("Unsupported authentication context for webhook"))
	}

	exec := executor.New(schema)