From 894dfab3a5651a6c1170617fe61446a0985179bc Mon Sep 17 00:00:00 2001 From: Judith Owens Date: Fri, 18 Apr 2025 10:28:42 +0000 Subject: [PATCH 1/2] feat: adds token expiry to session data --- config/runtime.exs | 5 +++++ lib/bathlarp_web/api_auth_plug.ex | 15 ++++++++++++--- .../controllers/v1/session_controller.ex | 3 ++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/config/runtime.exs b/config/runtime.exs index e730115..409e338 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -113,3 +113,8 @@ if config_env() == :prod do # # See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details. end + +# Set access token expiry in minutes and refresh token expiry in days +config :bathlarp, BathLARPWeb.APIAuthPlug, + access_expiry: System.get_env("BATHLARP_ACCESS_EXPIRY", "15"), + refresh_expiry: System.get_env("BATHLARP_REFRESH_EXPIRY", "30") diff --git a/lib/bathlarp_web/api_auth_plug.ex b/lib/bathlarp_web/api_auth_plug.ex index 2d217bc..8daf70e 100644 --- a/lib/bathlarp_web/api_auth_plug.ex +++ b/lib/bathlarp_web/api_auth_plug.ex @@ -28,7 +28,9 @@ defmodule BathLARPWeb.APIAuthPlug do The tokens are added to the `conn.private` as `:api_access_token` and `:api_renewal_token`. The renewal token is stored in the access token - metadata and vice versa. + metadata and vice versa. The expiry timestamp of the access token is + also stored as `:api_access_expiry` so it can be referenced by the + frontend later. """ @impl true @spec create(Conn.t(), map(), Config.t()) :: {Conn.t(), map()} @@ -36,23 +38,30 @@ defmodule BathLARPWeb.APIAuthPlug do store_config = store_config(config) access_token = Pow.UUID.generate() renewal_token = Pow.UUID.generate() + token_conf = Application.get_env(:bathlarp, BathLARPWeb.APIAuthPlug) + access_expiry = Keyword.get(token_conf, :access_expiry) |> String.to_integer() + refresh_expiry = Keyword.get(token_conf, :refresh_expiry) |> String.to_integer() conn = conn |> Conn.put_private(:api_access_token, sign_token(conn, access_token, config)) |> Conn.put_private(:api_renewal_token, sign_token(conn, renewal_token, config)) + |> Conn.put_private( + :api_access_expiry, + DateTime.utc_now() |> DateTime.add(access_expiry, :minute) + ) |> Conn.register_before_send(fn conn -> # The store caches will use their default `:ttl` setting. To change the # `:ttl`, `Keyword.put(store_config, :ttl, :timer.minutes(10))` can be # passed in as the first argument instead of `store_config`. CredentialsCache.put( - store_config, + Keyword.put(store_config, :ttl, :timer.minutes(access_expiry)), access_token, {account, [renewal_token: renewal_token]} ) PersistentSessionCache.put( - store_config, + Keyword.put(store_config, :ttl, :timer.minutes(refresh_expiry * 60 * 24)), renewal_token, {account, [access_token: access_token]} ) diff --git a/lib/bathlarp_web/controllers/v1/session_controller.ex b/lib/bathlarp_web/controllers/v1/session_controller.ex index 6caca31..5ce1475 100644 --- a/lib/bathlarp_web/controllers/v1/session_controller.ex +++ b/lib/bathlarp_web/controllers/v1/session_controller.ex @@ -108,7 +108,8 @@ defmodule BathLARPWeb.V1.SessionController do id: UUID.uuid4(), attributes: %{ access_token: conn.private.api_access_token, - renewal_token: conn.private.api_renewal_token + renewal_token: conn.private.api_renewal_token, + access_expiry: conn.private.api_access_expiry } } }) From b99bb4ce565ecd375de353af73a9f7cf37d849bf Mon Sep 17 00:00:00 2001 From: Judith Owens Date: Fri, 18 Apr 2025 11:07:04 +0000 Subject: [PATCH 2/2] feat: updates session schema --- lib/bathlarp_web/api_auth_plug.ex | 2 +- lib/bathlarp_web/controllers/v1/schemas/session.ex | 5 +++++ openapi.yaml | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/bathlarp_web/api_auth_plug.ex b/lib/bathlarp_web/api_auth_plug.ex index 8daf70e..fb1ef7e 100644 --- a/lib/bathlarp_web/api_auth_plug.ex +++ b/lib/bathlarp_web/api_auth_plug.ex @@ -61,7 +61,7 @@ defmodule BathLARPWeb.APIAuthPlug do ) PersistentSessionCache.put( - Keyword.put(store_config, :ttl, :timer.minutes(refresh_expiry * 60 * 24)), + Keyword.put(store_config, :ttl, :timer.hours(refresh_expiry * 24)), renewal_token, {account, [access_token: access_token]} ) diff --git a/lib/bathlarp_web/controllers/v1/schemas/session.ex b/lib/bathlarp_web/controllers/v1/schemas/session.ex index 4a251be..ba49b00 100644 --- a/lib/bathlarp_web/controllers/v1/schemas/session.ex +++ b/lib/bathlarp_web/controllers/v1/schemas/session.ex @@ -109,6 +109,11 @@ defmodule BathLARPWeb.V1.Schemas.Session do renewal_token: %Schema{ type: :string, description: "Long-lived token for refreshing the access token" + }, + access_expiry: %Schema{ + type: :string, + description: "Expiry timestamp for the access token to trigger refreshes", + format: :"date-time" } }, required: [:access_token, :renewal_token] diff --git a/openapi.yaml b/openapi.yaml index 7123d2a..addaf4a 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -299,6 +299,10 @@ components: SessionAttributes: description: Session tokens properties: + access_expiry: + description: Expiry timestamp for the access token to trigger refreshes + format: date-time + type: string access_token: description: Short-lived token for regular API access type: string