rogerweb

rogerweb

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!

Showing Posts 1 to 6

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().

hauleth

hauleth

Or just application configuration :wink:

kokolegorille

kokolegorille

But it needs to be dynamic, at least when app starts :slight_smile:

hauleth

hauleth

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

kokolegorille

kokolegorille

Ok, it’s simpler :slight_smile:

rogerweb

rogerweb OP

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?

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews