GenieFramework / GenieAuthentication.jl

Authentication plugin for Genie framework
MIT License
20 stars 11 forks source link

Can't use `@authenticated!` and `current_user()` from within `MyModelController.jl`. #11

Closed mcvmcv closed 1 year ago

mcvmcv commented 2 years ago

According to the documentation in the readme at https://github.com/GenieFramework/GenieAuthentication.jl, there are two main ways to use the GenieAuthentication @authenticated! macro: 1/ In routes.jl:

# routes.jl
using GenieAuthentication

route("/protected") do; @authenticated!
  # this code is only accessible for authenticated users
end

2/ In a controller file:

# routes.jl
route("/protected", ProtectedController.secret)
# ProtectedController.jl
using GenieAuthentication

function secret()
  @authenticated!

  # this code is only accessible for authenticated users
end

I am finding that only the first works correctly.

To reproduce: Construct a minimal WatchTonight style app with GenieAuthentication.

Genie.newapp_mvc("WatchTonight")
Genie.add_resource("Movie")

In routes.jl

using Genie.Router
using GenieAuthentication
using MoviesController

function test2function()
    @authenticated!
    @show current_user()
    "Test 2: logged in."
end

route("/") do
  serve_static_file("welcome.html")
end

route("/test") do
    @show current_user()
    @authenticated!
    "Test: logged in."
end

route("/test2", test2function; method = GET, named = :test2)

route("/test_movies", MoviesController.test_movies; method = GET, named = :test_movies)

and in MoviesController.jl:

module MoviesController

using GenieAuthentication

function test_movies()
    @authenticated!
    @show current_user()
    "MoviesController: logged in."
end

# Build something great
end

Then /test and /test2 show the current user (here, nothing) in the repl and redirect to login as expected, while /test_movies continually redirects to itself before giving up.

Additional information: The first time loading this project I got:

me@pc:~/projects/Watchtonight$ bin/server

 _____         _
|   __|___ ___|_|___
|  |  | -_|   | | -_|
|_____|___|_|_|_|___|

| Web: https://genieframework.com
| GitHub: https://github.com/genieframework/Genie.jl
| Docs: https://www.genieframework.com/docs/tutorials/Overview.html
| Discord: https://discord.com/invite/9zyZbD6J7H
| Twitter: https://twitter.com/GenieMVC

Active env: DEV

Loading routes[ Info: 2022-02-14 09:47:43 Precompiling MoviesController [top-level]
┌ Warning: Route named `show_login` is not defined
└ @ Genie.Router ~/.julia/packages/Genie/JHrq4/src/Router.jl:294

This line about show_login not being defined didn't appear on subsequent bin/server commands.

While running the server, editing the MoviesController.test_movies function (causing recompilation?) means that /test_movies redirects to /login correctly.

Routes like /test and /test2 above can use the current_user() function defined in /plugins/genie_authentication.jl, while /test_movies cannot find it.

[ Info: 2022-02-14 10:03:41 GET /test_movies 200
┌ Error: 2022-02-14 10:03:42 UndefVarError: current_user not defined

Versions, packages, etc:

(Watchtonight) pkg> st
     Project Watchtonight v0.1.0
      Status `~/projects/Watchtonight/Project.toml`
  [c43c736e] Genie v4.10.1
  [e115e502] GenieAuthentication v1.1.0
  [6d011eab] Inflector v1.0.1
  [e6f89c97] LoggingExtras v0.4.7
  [739be429] MbedTLS v1.0.3
  [340e8cb6] SearchLight v2.1.1
  [21a827c4] SearchLightSQLite v2.1.0
  [ade2ca70] Dates
  [56ddb016] Logging
essenciary commented 2 years ago

@mcvmcv thanks for flagging this - can you share the app as a zip file to make it easier to debug?

essenciary commented 2 years ago

@mcvmcv Judging by the warning it looks like there is no show_login route - which is supposed to display the login form.

mcvmcv commented 2 years ago

WatchTonight.zip App should be attached. I have made no migrations, so logging in is not possible.

The :show_login route definitely exists: you can access it by visiting /test or /test2; or /test_movies after editing the controller function while the server is running. Here is a shell session I just ran:

me@pc:~/projects/Watchtonight$ bin/server

 _____         _
|   __|___ ___|_|___
|  |  | -_|   | | -_|
|_____|___|_|_|_|___|

| Web: https://genieframework.com
| GitHub: https://github.com/genieframework/Genie.jl
| Docs: https://www.genieframework.com/docs/tutorials/Overview.html
| Discord: https://discord.com/invite/9zyZbD6J7H
| Twitter: https://twitter.com/GenieMVC

Active env: DEV

Loading plugins[ Info: 2022-02-15 07:43:37 Precompiling AuthenticationController [top-level]

Ready! 

┌ Info: 2022-02-15 07:44:03 
└ Web Server starting at http://127.0.0.1:8000 - press Ctrl/Cmd+C to stop the server. 
[ Info: 2022-02-15 07:44:25 GET /login 200
[ Info: 2022-02-15 07:44:37 SELECT "users"."id" AS "users_id", "users"."username" AS "users_username", "users"."password" AS "users_password", "users"."name" AS "users_name", "users"."email" AS "users_email" FROM "users" WHERE "id" = NULL ORDER BY users.id ASC
current_user() = nothing
[ Info: 2022-02-15 07:44:38 GET /test 302 # This route calls `@authenticated!` from `routes.jl`
[ Info: 2022-02-15 07:44:38 GET /login 200
[ Info: 2022-02-15 07:44:53 GET /test2 302 # This route calls `@authenticated!` from `routes.jl`
[ Info: 2022-02-15 07:44:53 GET /login 200
[ Info: 2022-02-15 07:45:03 GET /test_movies 302  # This route calls `@authenticated!` from MoviesController.jl
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302
[ Info: 2022-02-15 07:45:03 GET /test_movies 302 #The browser gave up here and displayed a warning here.
[ Info: 2022-02-15 07:45:44 GET /test_movies 302 #Here I have edited the controller function, and refreshing redirects correctly to the login page.
[ Info: 2022-02-15 07:45:44 GET /test_movies 302
[ Info: 2022-02-15 07:45:44 GET /login 200
essenciary commented 2 years ago

@mcvmcv thank you! I'll try to debug it today and follow up.

MRoqueta commented 2 years ago

I'm having the same issue as @mcvmcv I'm getting a 302 error from trying to access a route that calls the @authenticated! macro, it only happens if I'm not logged in. If I navigate to the :show_login route manually and log in, then navigate to the authentication restricted route everything seems to work properly.

essenciary commented 2 years ago

@MRoqueta - thanks, I haven't had the chance to look into it but I'll try to soon, we'll need a fresh release and some refactoring of the package, so it would be a good opportunity.

essenciary commented 1 year ago

Confirmed issue with the @authenticated! macro and the not found route. The macro was evaluated before the route was loaded so it didn't know where to correctly redirect.

This has been addressed in v2.1 -- the @authenticated! macro should be replaced with the authenticated!() function.