Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
15 changes: 12 additions & 3 deletions lib/bathlarp_web/api_auth_plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,40 @@ 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()}
def create(conn, account, config) 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.hours(refresh_expiry * 24)),
renewal_token,
{account, [access_token: access_token]}
)
Expand Down
5 changes: 5 additions & 0 deletions lib/bathlarp_web/controllers/v1/schemas/session.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
3 changes: 2 additions & 1 deletion lib/bathlarp_web/controllers/v1/session_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
})
Expand Down
4 changes: 4 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading