gin
gin copied to clipboard
BasicAuth() asking for authorization on every route starting from subroute
I have the following code:
authorized.GET("/api", func(ctx *gin.Context) {
ctx.JSON(200, gin.H{"message": "this is the root!", "status": 200})
})
authorized.GET("/api/:first", func(ctx *gin.Context) {
ctx.JSON(200, gin.H{"message": "this is a subroute!", "status": 200})
})
authorized.GET("/api/:first/:second", func(ctx *gin.Context) {
ctx.JSON(200, gin.H{"message": "this is a deeper subroute!", "status": 200})
})
If I login to localhost:8080/api
is asks for username and password as expected. Now I can go to localhost:8080/api/deep
and localhost:8080/api/deep/deeper
without issue.
[GIN] 2022/10/30 - 23:32:45 | 401 | 0s | 127.0.0.1 | GET "/api" AUTHORIZATION
[GIN] 2022/10/30 - 23:32:47 | 200 | 0s | 127.0.0.1 | GET "/api"
[GIN] 2022/10/30 - 23:32:49 | 200 | 998.8µs | 127.0.0.1 | GET "/api/deep"
[GIN] 2022/10/30 - 23:32:53 | 200 | 1.0186ms | 127.0.0.1 | GET "/api/deep/deeper"
If however I start by logging in to to localhost:8080/api/deep/deeper
, then it asks for username and password as expected. But if I now go to localhost:8080/api/deep/
it asks for login again. And then also at localhost:8080/api
.
[GIN] 2022/10/30 - 23:32:27 | 401 | 0s | 127.0.0.1 | GET "/api/deep/deeper" AUTHORIZATION
[GIN] 2022/10/30 - 23:32:30 | 200 | 991µs | 127.0.0.1 | GET "/api/deep/deeper"
[GIN] 2022/10/30 - 23:32:33 | 401 | 0s | 127.0.0.1 | GET "/api/deep" AUTHORIZATION
[GIN] 2022/10/30 - 23:32:33 | 200 | 193.3µs | 127.0.0.1 | GET "/api/deep"
[GIN] 2022/10/30 - 23:32:35 | 401 | 0s | 127.0.0.1 | GET "/api" AUTHORIZATION
[GIN] 2022/10/30 - 23:32:35 | 200 | 0s | 127.0.0.1 | GET "/api"
How to reproduce
Try logging into /api
, then go to the subroutes. This should work as expected.
Now try logging in from /api/first/second
, then go to /api/first
, then to /api
, it should now show 401 in console.
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
authorized := router.Group("/", gin.BasicAuth(gin.Accounts{
"foo": "bar",
}))
authorized.GET("/api", func(ctx *gin.Context) {
ctx.JSON(200, gin.H{"message": "this is the root!", "status": 200})
})
authorized.GET("/api/:first", func(ctx *gin.Context) {
ctx.JSON(200, gin.H{"message": "this is a subroute!", "status": 200})
})
authorized.GET("/api/:first/:second", func(ctx *gin.Context) {
ctx.JSON(200, gin.H{"message": "this is a deeper subroute!", "status": 200})
})
router.Run("localhost:8080")
}
Other
While this does work in the browser for me (Firefox), this does not work for something like VLC Media Player or applications like that. They constantly have to authorize, which is very inconvenient if one is creating a file server with Gin, as this subroute permission mess can require one to log in every time a file is fetched.
Environment
- go version: 1.19
- gin version: v1.8.1
- operating system: Windows 10
Hey @BenStigsen, That is the regular behaviour. Maybe you can take a look this question: https://stackoverflow.com/questions/27818587/httpget-401-status-code-followed-by-200-status-code
If you don't want a redundant 401 response, maybe you can use other auth mode. I recommend you use JWT and token.