go-chi / jwtauth

JWT authentication middleware for Go HTTP services
MIT License
541 stars 91 forks source link

Having a hard time setting up a custom authenticator function #49

Closed adrianocr closed 3 years ago

adrianocr commented 3 years ago

I'm doing the oauth dance with an API (Shopify) that is making it difficult on me to write an authenticator function. Currently it looks like this:

func Authenticator(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token, _, err := jwtauth.FromContext(r.Context())

        if err != nil {
            ctx := context.WithValue(r.Context(), "shop", r.URL.Query().Get("shop"))
            fmt.Println(r.URL.Query().Get("shop"), "Debug: 1")
            http.Redirect(w, r.WithContext(ctx), "http://localhost:2020/login", 301)
        }

        if token == nil || !token.Valid {
            ctx := context.WithValue(r.Context(), "shop", r.URL.Query().Get("shop"))
            fmt.Println(r.URL.Query().Get("shop"), "Debug: 2")
            http.Redirect(w, r.WithContext(ctx), "http://localhost:2020/login", 301)
        }

        // Token is authenticated, pass it through
        next.ServeHTTP(w, r)
    })
}

If I'm not mistaken, the middleware runs before the actual request right? Which means that my r.URL.Query().Get("shop") will never be available to the middleware before redirecting to http://localhost:2020/login.

But it's necessary because shopify doesn't auth with a generic https://shopify.com/oauth/authorize style endpoint, but rather with a account specific endpoint that looks like this: https://{shop}.myshopify.com/admin/oauth/authorize. The shop query param I'm trying to pass in would replace that {shop} in the URL and is provided to the code when you go to http://localhost:2020/?shop=shopNameHere.myshopify.com. The authenticator function should redirect to /login and pass the 'shop' param through but it doesn't.

So what can I do here?