rogerweb

rogerweb

Closure for module configuration?

Hi,

When a user connects to my application via a Phoenix.Socket he/she provides a token (generated by another system) that I would like to verify and validate. I created a Token module to encapsulate all the verification and validation code. It uses Joken to actually do the job and it requires some configuration like creating a signer using a public_key and defining some validation functions for checking the claims (the iss for instance).

These two strings (public key and the expected issuer) are considered configuration and must be provided to the solution via environment variables.

Considering that this configuration part of the flow needs to be executed only once (when the application starts, for instance) and not every time a token is verified, I started wondering what would be the best design, i.e., how to perform the configuration only once and provide a simple verify_and_validate/1 function that takes only the token.

A closure seems to be an option. Example:

  def get_verify_fun(public_key, issuer) do
    config = token_config(issuer)
    signer = Joken.Signer.create("RS256", %{"pem" => public_key})
    fn token -> verify(config, token, signer) end
  end

  defp verify(config, token, signer) do
    with {:ok, claims} <- Joken.verify_and_validate(config, token, signer) do
      check_for_missing_claims(claims, @required_claims)
    end
  end

Now the question is: where to call the get_verify_fun/2 and/or how to make the returned function available to my code in the connect function in the Phoenix.Socket module?

An option is to call the get_verify_fun/2 in my runtime.exs, store the returned function in the application scope using config and use Application.fetch_env! in the socket connect:

Example (runtime.exs):

public_key = get_env("TOKEN_PUBLIC_KEY") |> String.replace("\\n", "\n")
issuer = get_env("TOKEN_ISSUER")
verify = MyApp.Token.get_verify_fun(public_key, issuer)
config :myapp, verify_token: verify

It works but it doesn’t feel right. What do you think?

I know I can fall back to passing the config along with the token on every call to verify but then we would be executing the configuration part over and over. It might be not a big deal in this case if Joken is not doing much, but what if this “configuration” ou “preparation” part of the flow is expensive?

Sorry for the long and not so direct to the point question and let me know if I can clarify anything.

Cheers!

First Post!

kokolegorille

kokolegorille

It looks like You want to cache your function when application start.

Probably using an Agent would be ok.
Or an Ets table (and a GenServer), to speed up think…
Or cachex.
Or a simple file, with :erlang.term_to_binary() and binary_to_term().

Most Liked

hauleth

hauleth

Application.put_env/3 call in Application.start/2 should do.

hauleth

hauleth

Or just application configuration :wink:

Last Post!

rogerweb

rogerweb

Thanks @kokolegorille, @hauleth, @dimitarvp and @gregvaughn for taking the time to read it and contribute.

Application.put_env/3 call in Application.start/2 should do.

Your suggestion is to store the resulting function in the application environment when it starts, right?

Isn’t it what I’m already doing, except that I’m using config in the runtime.exs?

Where Next?

Popular in Questions Top

joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42716 114
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement