The idea of this pattern is that the algorithm behind verfiy returns a Dict of parameters -- which can be anything. Here I am imagining that this includes a unique hash representing the result of token verification (e.g. a key to a lookup table). This can then be used by the page located at config.success_redirect to look up any data stored by verify. Note thatparams is allowed to be nothing (e.g. if token validation failed, or if this pattern is unused). If params is nothing then no parameters are included by redirect_handler.
A simple use case for this is if verify stores the logged in user's name using a global dict. The value in params can then be used to look up the user's name. Eg:
struct Users
tokens::Dict{String, Tuple{String, String, String}}
Users() = new(Dict{String, Tuple{String, String, String}}())
end
function add(
users::Users,
email::String, access_token::String, refresh_token::String;
length=16
)
while true
new_key = randstring(['0':'9'; 'a':'f'], length)
if ! (new_key in keys(users.tokens))
users.tokens[new_key] = (email, access_token, refresh_token)
return new_key
end
end
end
import Base.keys
keys(u::Users) = Base.keys(u.tokens)
email(u::Users, k::String) = u.tokens[k][1]
access_token(u::Users, k::String) = u.tokens[k][2]
refresh_token(u::Users, k::String) = u.tokens[k][3]
authenticated_users = Users()
@get oauth_callback function(req)
query_params = queryparams(req)
code = query_params["code"]
# handle tokens and user details
google_oauth2.token_exchange(code,
function (tokens::Google.Tokens, user::Google.User)
user_key = add(
authenticated_users,
user.email, tokens.access_token, tokens.refresh_token
)
return Dict("user_key" => user_key)
end
)
end
function is_authenticated(req)
query_params = queryparams(req)
if !("user_key" in keys(query_params)) return false end
return query_params["user_key"] in keys(authenticated_users)
end
@get "/protected" function(req)
if is_authenticated(req)
user_key = queryparams(req)["user_key"]
"""
<html>
<body>
You are successfully signed in as: $(email(authenticated_users, user_key))
<p>
Please go to: <a href='$(oauth_path)'>Authenticate with Google</a> to log in as a different user
</body>
</html>
"""
else
"""
<html>
<body>
You are not logged in, please log in by going to:
<a href='$(oauth_path)'>Authenticate with Google</a>
</body>
</html>
"""
end
end
In this case params contains only the user UUID -- but it can be whatever your application needs.
I'm thinking of how to generalize this to include a session cookie in the redirect_handler.
This PR introduces the following pattern for verifying tokens and redirecting on success:
The idea of this pattern is that the algorithm behind
verfiy
returns aDict
of parameters -- which can be anything. Here I am imagining that this includes a unique hash representing the result of token verification (e.g. a key to a lookup table). This can then be used by the page located atconfig.success_redirect
to look up any data stored byverify
. Note thatparams
is allowed to benothing
(e.g. if token validation failed, or if this pattern is unused). Ifparams
isnothing
then no parameters are included byredirect_handler
.A simple use case for this is if
verify
stores the logged in user's name using a global dict. The value inparams
can then be used to look up the user's name. Eg:In this case
params
contains only the user UUID -- but it can be whatever your application needs.I'm thinking of how to generalize this to include a session cookie in the
redirect_handler
.