Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content-Type application/json error: "failed to redirect user during authboss.Middleware redirect: template for page redirect not found" #29

Closed
frederikhors opened this issue Jan 5, 2019 · 7 comments

Comments

@frederikhors
Copy link
Contributor

frederikhors commented Jan 5, 2019

Issue opened for the creation of a wiki page that summarizes the doubts and problems for newbies (volatiletech/authboss#210).

Let's take authboss-sample (https://github.com/volatiletech/authboss-sample).

If I use it via browser it works. If I visit localhost:3000/blogs/new it redirects on /login page which is what I want.

But if I use Postman (or a javascript client) and - example - call the POST localhost:3000/blogs/new or maybe the GET localhost:3000/blogs/new it panics:

GET /blogs/new HTTP/1.1
2019-01-05T17:22:17Z [INFO]: redirecting unauthorized user to login from: /blogs/new
2019-01-05T17:22:17Z [EROR]: failed to redirect user during authboss.Middleware redirect: template for page redirect not found
github.com/volatiletech/authboss-renderer.(*HTML).Render
        C:/Users/Fred/go/pkg/mod/github.com/volatiletech/[email protected]/html.go:95
github.com/volatiletech/authboss/defaults.Redirector.redirectAPI
        C:/Users/Fred/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/defaults/responder.go:103
github.com/volatiletech/authboss/defaults.Redirector.redirectAPI-fm
        C:/Users/Fred/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/defaults/responder.go:71
github.com/volatiletech/authboss/defaults.(*Redirector).Redirect
        C:/Users/Fred/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/defaults/responder.go:74
github.com/volatiletech/authboss.MountedMiddleware2.func1.1.1
        C:/Users/Fred/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/authboss.go:190
github.com/volatiletech/authboss.MountedMiddleware2.func1.1
        C:/Users/Fred/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/authboss.go:203
net/http.HandlerFunc.ServeHTTP
        C:/Go/src/net/http/server.go:1964
github.com/go-chi/chi.(*ChainHandler).ServeHTTP
        C:/Users/Fred/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/chain.go:31
github.com/go-chi/chi.(*Mux).routeHTTP
        C:/Users/Fred/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:424
github.com/go-chi/chi.(*Mux).routeHTTP-fm
        C:/Users/Fred/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:368
net/http.HandlerFunc.ServeHTTP
        C:/Go/src/net/http/server.go:1964
main.dataInjector.func1
        D:/go/authboss-sample/blog.go:309
net/http.HandlerFunc.ServeHTTP
        C:/Go/src/net/http/server.go:1964
github.com/volatiletech/authboss/remember.Middleware.func1.1
        C:/Users/Fred/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/remember/remember.go:80
net/http.HandlerFunc.ServeHTTP
        C:/Go/src/net/http/server.go:1964
github.com/volatiletech/authboss.(*Authboss).LoadClientStateMiddleware.func1
        C:/Users/Fred/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/client_state.go:132
net/http.HandlerFunc.ServeHTTP
        C:/Go/src/net/http/server.go:1964
main.logger.func1
        D:/go/authboss-sample/middleware.go:59
net/http.HandlerFunc.ServeHTTP
        C:/Go/src/net/http/server.go:1964
github.com/go-chi/chi.(*Mux).ServeHTTP
        C:/Users/Fred/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:81
net/http.serverHandler.ServeHTTP
        C:/Go/src/net/http/server.go:2741
net/http.(*conn).serve
        C:/Go/src/net/http/server.go:1847
runtime.goexit
        C:/Go/src/runtime/asm_amd64.s:1333

Why this behaviour?

If I remove the Content-Type: application/json from the request it redirects again but is not what I need.
I need a 401 http status code so I can handle the error in my javascript client.

I don't need the API mode. Just need to use authboss in browser with templates and all, which is amazing (thanks again!).

Same problem using Middleware2.

Is it wrong what I need?


Same on authboss: volatiletech/authboss#208

@aarondl
Copy link
Member

aarondl commented Jan 12, 2019

Changing the sample like so:

diff --git a/blog.go b/blog.go
index bae3bda..b125d93 100644
--- a/blog.go
+++ b/blog.go
@@ -256,7 +256,7 @@ func main() {
 
 	// Authed routes
 	mux.Group(func(mux chi.Router) {
-		mux.Use(authboss.Middleware(ab, true, false, false), lock.Middleware(ab), confirm.Middleware(ab))
+		mux.Use(authboss.Middleware2(ab, authboss.RequireNone, authboss.RespondUnauthorized), lock.Middleware(ab), confirm.Middleware(ab))
 		mux.MethodFunc("GET", "/blogs/new", newblog)
 		mux.MethodFunc("GET", "/blogs/{id}/edit", edit)
 		mux.MethodFunc("POST", "/blogs/{id}/edit", update)

With the following request:

$ curl -v -X GET -d '{}' http://localhost:3000/blogs/new

Gives the following response (and no error):

> GET /blogs/new HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 2 out of 2 bytes
< HTTP/1.1 401 Unauthorized
< Set-Cookie: csrf_token=1XbLOaxfhYgVWJC/V3NWXCMWMBK9xhksaCD7qsYcxCs=; Max-Age=31536000
< Vary: Cookie
< Date: Sat, 12 Jan 2019 19:08:02 GMT
< Content-Length: 0
< 
* Connection #0 to host localhost left intact

Do not use Content-Type: application/json outside of API mode. Please only open a single issue per problem on the most appropriate repo please :) Cuts down on noise.

@aarondl aarondl closed this as completed Jan 12, 2019
@frederikhors
Copy link
Contributor Author

Now I think I understand.

But a question: API endpoints (with Content-Type: application / json) can never give a redirect as a response?

  • What if someone calls them from browser? Why panic my go server?

Can the following code be fine, in your opinion?

r.Group(func(r chi.Router) {
  r.Use(authboss.Middleware2(config.Ab, authboss.RequireNone, authboss.RespondRedirect))
  r.Get("/routeRenderedByServerNotAPI", myServerRouteHandler)
})

r.Group(func(r chi.Router) {
  r.Use(authboss.Middleware2(config.Ab, authboss.RequireNone, authboss.RespondUnauthorized))
  r.Get("/routeForAPIContentTypeJSON", myAPIRouteHandler)
})

What if someone calls /routeForAPIContentTypeJSON from browser?

@aarondl
Copy link
Member

aarondl commented Jan 15, 2019

For Authboss to have API endpoints it needs to be in API mode. They can do redirects, but they do them differently. But when it's in API mode it doesn't look for a template, therefore doesn't error when templates are missing.

@frederikhors
Copy link
Contributor Author

Ok, @aarondl, I understand.

What I do not understand now is if authboss can be used in two different ways on the same server or not.

As you can see from the previous examples, I have both html endpoints (authboss pages also) (ex: /auth/login or /faq) and other JSON API endpoints (ex: /api/v1).

I need authboss to protect both and I need different "respond" operations if the json endpoint or html page is called.

How do you solve it?

Should I have two different authboss.Middleware2(authboss.RespondRedirect) and authboss.Middleware2(authboss.RespondUnauthorized) as in the previous example or am I totally wrong?

In blog.go of authboss-sample there is this code:

func redirect(w http.ResponseWriter, r *http.Request, path string) {
	if *flagAPI {
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Location", path)
		w.WriteHeader(http.StatusFound)
		fmt.Fprintf(w, `{"path": %q}`, path)
		return
	}

	http.Redirect(w, r, path, http.StatusFound)
}

Why does authboss not detect automatically if the call has Content-Type: application/json and responds appropriately with the redirect as above?

Can we introduce this behavior?

@aarondl
Copy link
Member

aarondl commented Jan 20, 2019

It cannot be used in two different ways on the same server. It was meant to be one or the other.

It's a significant amount of work to change everything to accept both types of requests since there's so much abstraction going on in Authboss. When you first set Authboss up you do a lot of configuration and instantiating types that will fulfill it's interfaces and quite a bit of that is binary - either API or Form based. It'd be a challenge. It's not something I want to do because it doesn't help my use cases and I don't really see it as an important thing, but I wouldn't stop someone from contributing that.

@frederikhors
Copy link
Contributor Author

Ok I understand.

Just a final little question:

If I use the below code am I totally wrong?

...
r.Use(Ab.LoadClientStateMiddleware, remember.Middleware(Ab))

// HTML endpoints with **authboss.RespondRedirect**?
r.Group(func(r chi.Router) {
	r.Use(authboss.Middleware2(Ab, authboss.RequireNone, authboss.RespondRedirect))
        ....
}

// JSON API endpoints with **authboss.RespondUnauthorized**?
r.Group(func(r chi.Router) {
	r.Use(authboss.Middleware2(Ab, authboss.RequireNone, authboss.RespondUnauthorized))
        ....
}

// authboss endpoints
r.Group(func(r chi.Router) {
	r.Use(auth.DataInjector, authboss.ModuleListMiddleware(Ab))
	r.Mount(AUTH_URL, http.StripPrefix(AUTH_URL, Ab.Config.Core.Router))
})

@aarondl
Copy link
Member

aarondl commented Jan 25, 2019

That could work sure, so long as you're not mixing API and non-API anywhere. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants