From 9c590ee82aeb83b6a838700100aa07f889c964b3 Mon Sep 17 00:00:00 2001 From: Pascal Knoth Date: Thu, 19 Sep 2024 14:45:32 +0200 Subject: [PATCH] [ssi] presentation hybrid flow --- .github/workflows/deploy.yml | 1 + .../views/template_view.ex | 7 ++++ .../cross_device_presentation.mustache | 8 ++++ apps/boruta_web/lib/boruta_web/application.ex | 4 ++ .../controllers/oauth/authorize_controller.ex | 19 +++++++++- .../controllers/oauth/token_controller.ex | 5 ++- .../lib/boruta_web/presentation_server.ex | 38 +++++++++++++++++++ apps/boruta_web/lib/boruta_web/router.ex | 1 + 8 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 apps/boruta_web/lib/boruta_web/presentation_server.ex diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d5926d94..6e19031b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,6 +4,7 @@ on: push: branches: - ebsi-verify-conformance + - poc-hybrid-vp-token workflow_run: workflows: - Continuous Integration diff --git a/apps/boruta_identity/lib/boruta_identity_web/views/template_view.ex b/apps/boruta_identity/lib/boruta_identity_web/views/template_view.ex index 8c1e710b..fd4decd1 100644 --- a/apps/boruta_identity/lib/boruta_identity_web/views/template_view.ex +++ b/apps/boruta_identity/lib/boruta_identity_web/views/template_view.ex @@ -143,6 +143,13 @@ defmodule BorutaIdentityWeb.TemplateView do |> context(Map.delete(assigns, :scopes)) end + def context(context, %{code: code} = assigns) do + + %{code: code} + |> Map.merge(context) + |> context(Map.delete(assigns, :code)) + end + def context(context, %{}), do: context defp text_from_credential_offer(credential_offer) do diff --git a/apps/boruta_identity/priv/templates/settings/cross_device_presentation.mustache b/apps/boruta_identity/priv/templates/settings/cross_device_presentation.mustache index a10c00fc..699e5545 100644 --- a/apps/boruta_identity/priv/templates/settings/cross_device_presentation.mustache +++ b/apps/boruta_identity/priv/templates/settings/cross_device_presentation.mustache @@ -30,3 +30,11 @@ } } + + diff --git a/apps/boruta_web/lib/boruta_web/application.ex b/apps/boruta_web/lib/boruta_web/application.ex index 9d8723ce..d6415300 100644 --- a/apps/boruta_web/lib/boruta_web/application.ex +++ b/apps/boruta_web/lib/boruta_web/application.ex @@ -9,6 +9,10 @@ defmodule BorutaWeb.Application do children = [ BorutaWeb.Endpoint, BorutaWeb.Repo, + %{ + id: BorutaWeb.PresentationServer, + start: {BorutaWeb.PresentationServer, :start_link, []} + }, {Finch, name: FinchHttp}, {Cluster.Supervisor, [Application.get_env(:libcluster, :topologies), [name: BorutaWeb.ClusterSupervisor]]}, diff --git a/apps/boruta_web/lib/boruta_web/controllers/oauth/authorize_controller.ex b/apps/boruta_web/lib/boruta_web/controllers/oauth/authorize_controller.ex index b0339838..5df0938a 100644 --- a/apps/boruta_web/lib/boruta_web/controllers/oauth/authorize_controller.ex +++ b/apps/boruta_web/lib/boruta_web/controllers/oauth/authorize_controller.ex @@ -28,6 +28,7 @@ defmodule BorutaWeb.Oauth.AuthorizeController do alias BorutaIdentity.IdentityProviders.IdentityProvider alias BorutaIdentityWeb.Router.Helpers, as: IdentityRoutes alias BorutaIdentityWeb.TemplateView + alias BorutaWeb.PresentationServer def authorize(%Plug.Conn{} = conn, _params) do current_user = conn.assigns[:current_user] @@ -439,11 +440,27 @@ defmodule BorutaWeb.Oauth.AuthorizeController do %{uri | path: Routes.token_path(conn, :direct_post, code)} |> URI.to_string() - end) + end), + code: response.code } ) end + def authenticated?(conn, %{"code" => code}) do + spawn(fn -> + PresentationServer.start_presentation(code) + + receive do + {:authenticated, redirect_uri} -> + chunk(conn, redirect_uri) + end + end) + + conn + |> put_resp_header("content-type", "text/event-stream") + |> send_chunked(200) + end + def authorize_success( %Plug.Conn{} = conn, %SiopV2Response{response_mode: "direct_post"} = response diff --git a/apps/boruta_web/lib/boruta_web/controllers/oauth/token_controller.ex b/apps/boruta_web/lib/boruta_web/controllers/oauth/token_controller.ex index 5b78d2fc..6638427e 100644 --- a/apps/boruta_web/lib/boruta_web/controllers/oauth/token_controller.ex +++ b/apps/boruta_web/lib/boruta_web/controllers/oauth/token_controller.ex @@ -9,6 +9,7 @@ defmodule BorutaWeb.Oauth.TokenController do alias Boruta.Oauth.TokenResponse alias Boruta.Openid alias BorutaWeb.OauthView + alias BorutaWeb.PresentationServer def token(%Plug.Conn{} = conn, _params) do conn |> Oauth.token(__MODULE__) @@ -103,7 +104,9 @@ defmodule BorutaWeb.Oauth.TokenController do end @impl Boruta.Openid.DirectPostApplication - def direct_post_success(conn, callback_uri) do + def direct_post_success(conn, callback_uri, token) do + PresentationServer.authenticated(token.previous_code, token.redirect_uri) + redirect(conn, external: callback_uri) end end diff --git a/apps/boruta_web/lib/boruta_web/presentation_server.ex b/apps/boruta_web/lib/boruta_web/presentation_server.ex new file mode 100644 index 00000000..b42059e6 --- /dev/null +++ b/apps/boruta_web/lib/boruta_web/presentation_server.ex @@ -0,0 +1,38 @@ +defmodule BorutaWeb.PresentationServer do + use GenServer + + def start_link do + GenServer.start_link(__MODULE__, [], name: __MODULE__) + end + + def init(_args) do + {:ok, presentations: %{}} + end + + def start_presentation(code) do + GenServer.call({:start_presentation, code}, __MODULE__) + end + + def authenticated(code, redirect_uri) do + GenServer.cast({:authenticated, code, redirect_uri}, __MODULE__) + end + + def handle_call({:start_presentation, code}, pid, state) do + presentations = Map.put( + state.presentations, + code, + %{ + start: :os.system_time(:microseconds), + pid: pid + } + ) + {:reply, :ok, %{state| presentations: presentations}} + end + + def handle_cast({:authenticated, code, redirect_uri}, state) do + presentation = state.presentations[code] + send(presentation[:pid], {:authenticated, redirect_uri}) + + {:noreply, Map.delete(state, code)} + end +end diff --git a/apps/boruta_web/lib/boruta_web/router.ex b/apps/boruta_web/lib/boruta_web/router.ex index 00a671be..a675b4fc 100644 --- a/apps/boruta_web/lib/boruta_web/router.ex +++ b/apps/boruta_web/lib/boruta_web/router.ex @@ -83,6 +83,7 @@ defmodule BorutaWeb.Router do pipe_through([:api]) post("/direct_post/:code_id", TokenController, :direct_post) + get("/presentation_sse", AuthorizeController, :authenticated?) end @impl Plug.ErrorHandler