From cd6a6cb77c896b350f93563c36c85a3140f4a722 Mon Sep 17 00:00:00 2001 From: Ivan Reshetnikov Date: Sun, 20 Oct 2024 23:03:39 +0500 Subject: [PATCH] Remove openid support I switched to an external solution that supports more protocols. --- config/runtime.exs | 2 +- lib/comfycamp/sso.ex | 171 ------------------ lib/comfycamp/sso/id_token.ex | 25 --- lib/comfycamp/sso/oidc_app.ex | 36 ---- lib/comfycamp/sso/oidc_code.ex | 35 ---- lib/comfycamp/sso/oidc_redirect_uri.ex | 22 --- .../components/layouts/admin.html.heex | 5 - .../controllers/oauth_controller.ex | 165 ----------------- lib/comfycamp_web/controllers/oauth_html.ex | 23 --- lib/comfycamp_web/controllers/oauth_json.ex | 39 ---- .../controllers/oidc_app_controller.ex | 76 -------- .../controllers/oidc_app_html.ex | 13 -- .../controllers/oidc_app_html/edit.html.heex | 10 - .../controllers/oidc_app_html/index.html.heex | 28 --- .../controllers/oidc_app_html/new.html.heex | 10 - .../oidc_app_html/oidc_app_form.html.heex | 12 -- .../controllers/oidc_app_html/show.html.heex | 41 ----- .../controllers/oidc_uri_controller.ex | 39 ---- .../controllers/oidc_uri_html.ex | 26 --- lib/comfycamp_web/router.ex | 26 --- lib/comfycamp_web/user_auth.ex | 31 ---- .../20241020180106_delete_openid.exs | 9 + test/comfycamp/sso_test.exs | 72 -------- .../controllers/oidc_app_controller_test.exs | 100 ---------- test/support/fixtures/sso_fixtures.ex | 23 --- 25 files changed, 10 insertions(+), 1029 deletions(-) delete mode 100644 lib/comfycamp/sso.ex delete mode 100644 lib/comfycamp/sso/id_token.ex delete mode 100644 lib/comfycamp/sso/oidc_app.ex delete mode 100644 lib/comfycamp/sso/oidc_code.ex delete mode 100644 lib/comfycamp/sso/oidc_redirect_uri.ex delete mode 100644 lib/comfycamp_web/controllers/oauth_controller.ex delete mode 100644 lib/comfycamp_web/controllers/oauth_html.ex delete mode 100644 lib/comfycamp_web/controllers/oauth_json.ex delete mode 100644 lib/comfycamp_web/controllers/oidc_app_controller.ex delete mode 100644 lib/comfycamp_web/controllers/oidc_app_html.ex delete mode 100644 lib/comfycamp_web/controllers/oidc_app_html/edit.html.heex delete mode 100644 lib/comfycamp_web/controllers/oidc_app_html/index.html.heex delete mode 100644 lib/comfycamp_web/controllers/oidc_app_html/new.html.heex delete mode 100644 lib/comfycamp_web/controllers/oidc_app_html/oidc_app_form.html.heex delete mode 100644 lib/comfycamp_web/controllers/oidc_app_html/show.html.heex delete mode 100644 lib/comfycamp_web/controllers/oidc_uri_controller.ex delete mode 100644 lib/comfycamp_web/controllers/oidc_uri_html.ex create mode 100644 priv/repo/migrations/20241020180106_delete_openid.exs delete mode 100644 test/comfycamp/sso_test.exs delete mode 100644 test/comfycamp_web/controllers/oidc_app_controller_test.exs delete mode 100644 test/support/fixtures/sso_fixtures.ex diff --git a/config/runtime.exs b/config/runtime.exs index 8ec2e01..ad4fb6f 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -109,7 +109,7 @@ if config_env() == :prod do relay: System.get_env("SMTP_RELAY"), username: System.get_env("SMTP_USERNAME"), password: System.get_env("SMTP_PASSWORD"), - ssl: true, + ssl: System.get_env("SMTP_SSL") == "true", tls: :always, auth: :always, port: Integer.parse(System.get_env("SMTP_PORT") || "465") diff --git a/lib/comfycamp/sso.ex b/lib/comfycamp/sso.ex deleted file mode 100644 index 442ed86..0000000 --- a/lib/comfycamp/sso.ex +++ /dev/null @@ -1,171 +0,0 @@ -defmodule Comfycamp.SSO do - @moduledoc """ - The SSO context. - """ - - import Ecto.Query, warn: false - alias Comfycamp.Repo - - alias Comfycamp.SSO.OIDCApp - alias Comfycamp.SSO.OIDCCode - alias Comfycamp.SSO.OIDCRedirectURI - - @doc """ - Returns the list of oidc_apps. - - ## Examples - - iex> list_oidc_apps() - [%OIDCApp{}, ...] - - """ - def list_oidc_apps do - Repo.all(OIDCApp) - end - - @doc """ - Gets a single oidc_app. - - Raises `Ecto.NoResultsError` if the Oidc app does not exist. - - ## Examples - - iex> get_oidc_app!(123) - %OIDCApp{} - - iex> get_oidc_app!(456) - ** (Ecto.NoResultsError) - - """ - def get_oidc_app!(id) do - query = - from a in OIDCApp, - preload: [:redirect_uris], - where: a.client_id == ^id - - Repo.one!(query) - end - - def get_oidc_app_by_secret!(client_secret) do - query = - from a in OIDCApp, - where: a.client_secret == ^client_secret - - Repo.one!(query) - end - - def has_redirect_uri?(client_id, redirect_uri) do - query = - from a in OIDCApp, - join: u in assoc(a, :redirect_uris), - where: u.uri == ^redirect_uri and a.client_id == ^client_id - - Repo.aggregate(query, :count) >= 1 - end - - def get_oidc_redirect_uri!(id), do: Repo.get(OIDCRedirectURI, id) - - def get_oidc_code!(value) do - ten_minutes_ago = DateTime.utc_now() |> DateTime.add(-600, :second) - - query = - from c in OIDCCode, - preload: [:oidc_app, :user], - where: c.value == ^value and c.inserted_at >= ^ten_minutes_ago - - Repo.one!(query) - end - - @doc """ - Creates a oidc_app. - - ## Examples - - iex> create_oidc_app(%{field: value}) - {:ok, %OIDCApp{}} - - iex> create_oidc_app(%{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def create_oidc_app(attrs \\ %{}) do - %OIDCApp{} - |> OIDCApp.creation_changeset(attrs) - |> Repo.insert() - end - - @doc """ - Create a temporary code for OIDC app - that may be exchanged for an access token. - """ - def create_oidc_code(attrs \\ %{}) do - %OIDCCode{} - |> OIDCCode.changeset(attrs) - |> Repo.insert() - end - - def create_oidc_redirect_uri(attrs \\ %{}) do - %OIDCRedirectURI{} - |> OIDCRedirectURI.changeset(attrs) - |> Repo.insert() - end - - @doc """ - Updates a oidc_app. - - ## Examples - - iex> update_oidc_app(oidc_app, %{field: new_value}) - {:ok, %OIDCApp{}} - - iex> update_oidc_app(oidc_app, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def update_oidc_app(%OIDCApp{} = oidc_app, attrs) do - oidc_app - |> OIDCApp.update_changeset(attrs) - |> Repo.update() - end - - @doc """ - Deletes a oidc_app. - - ## Examples - - iex> delete_oidc_app(oidc_app) - {:ok, %OIDCApp{}} - - iex> delete_oidc_app(oidc_app) - {:error, %Ecto.Changeset{}} - - """ - def delete_oidc_app(%OIDCApp{} = oidc_app) do - Repo.delete(oidc_app) - end - - def delete_oidc_code(%OIDCCode{} = code) do - Repo.delete(code) - end - - def delete_oidc_redirect_uri(%OIDCRedirectURI{} = uri) do - Repo.delete(uri) - end - - @doc """ - Returns an `%Ecto.Changeset{}` for tracking oidc_app changes. - - ## Examples - - iex> change_oidc_app(oidc_app) - %Ecto.Changeset{data: %OIDCApp{}} - - """ - def change_oidc_app(%OIDCApp{} = oidc_app, attrs \\ %{}) do - OIDCApp.update_changeset(oidc_app, attrs) - end - - def change_oidc_redirect_uri(%OIDCRedirectURI{} = oidc_redirect_uri, attrs \\ %{}) do - OIDCRedirectURI.changeset(oidc_redirect_uri, attrs) - end -end diff --git a/lib/comfycamp/sso/id_token.ex b/lib/comfycamp/sso/id_token.ex deleted file mode 100644 index 582c18a..0000000 --- a/lib/comfycamp/sso/id_token.ex +++ /dev/null @@ -1,25 +0,0 @@ -defmodule Comfycamp.SSO.IDToken do - @derive Jason.Encoder - defstruct [:iss, :sub, :aud, :exp, :iat, :email, :preferred_username, :nonce] - - def build_id_token(user, client_id, nonce) do - {_, now} = DateTime.now("Etc/UTC") - issued_at = DateTime.to_unix(now) - - expires_at = - now - |> DateTime.add(1, :day) - |> DateTime.to_unix() - - %Comfycamp.SSO.IDToken{ - iss: "https://" <> System.get_env("PHX_HOST"), - sub: Integer.to_string(user.id), - aud: client_id, - exp: expires_at, - iat: issued_at, - email: user.email, - preferred_username: user.username, - nonce: nonce - } - end -end diff --git a/lib/comfycamp/sso/oidc_app.ex b/lib/comfycamp/sso/oidc_app.ex deleted file mode 100644 index 53bbfa4..0000000 --- a/lib/comfycamp/sso/oidc_app.ex +++ /dev/null @@ -1,36 +0,0 @@ -defmodule Comfycamp.SSO.OIDCApp do - use Ecto.Schema - import Ecto.Changeset - - alias Comfycamp.SSO.OIDCCode - alias Comfycamp.SSO.OIDCRedirectURI - alias Comfycamp.Rand - - @derive {Phoenix.Param, key: :client_id} - @primary_key {:client_id, :string, autogenerate: false} - schema "oidc_apps" do - field :client_secret, :string - field :name, :string - field :enabled, :boolean, default: false - - has_many :codes, OIDCCode, foreign_key: :oidc_app_id - has_many :redirect_uris, OIDCRedirectURI, foreign_key: :oidc_app_id - - timestamps(type: :utc_datetime) - end - - @doc false - def update_changeset(oidc_app, attrs) do - oidc_app - |> cast(attrs, [:name, :enabled]) - |> validate_required([:name, :enabled]) - |> validate_length(:name, min: 2, max: 48) - end - - def creation_changeset(oidc_app, attrs) do - oidc_app - |> update_changeset(attrs) - |> change(client_id: Rand.get_random_string(20)) - |> change(client_secret: Rand.get_random_string(32)) - end -end diff --git a/lib/comfycamp/sso/oidc_code.ex b/lib/comfycamp/sso/oidc_code.ex deleted file mode 100644 index 2e287a8..0000000 --- a/lib/comfycamp/sso/oidc_code.ex +++ /dev/null @@ -1,35 +0,0 @@ -defmodule Comfycamp.SSO.OIDCCode do - @moduledoc """ - Temporary code that may be exchanged for an access token. - """ - - use Ecto.Schema - import Ecto.Changeset - - alias Comfycamp.Accounts.User - alias Comfycamp.SSO.OIDCApp - alias Comfycamp.Rand - - @derive {Phoenix.Param, key: :value} - @primary_key {:value, :string, autogenerate: false} - schema "oidc_codes" do - field :redirect_uri, :string - field :nonce, :string - belongs_to :user, User - - belongs_to :oidc_app, OIDCApp, - type: :string, - foreign_key: :oidc_app_id, - references: :client_id - - timestamps(type: :utc_datetime, updated_at: false) - end - - @doc false - def changeset(oidc_code, attrs) do - oidc_code - |> change(value: Rand.get_random_string(12)) - |> cast(attrs, [:user_id, :oidc_app_id, :redirect_uri, :nonce]) - |> validate_required([:user_id, :oidc_app_id, :redirect_uri]) - end -end diff --git a/lib/comfycamp/sso/oidc_redirect_uri.ex b/lib/comfycamp/sso/oidc_redirect_uri.ex deleted file mode 100644 index e91993c..0000000 --- a/lib/comfycamp/sso/oidc_redirect_uri.ex +++ /dev/null @@ -1,22 +0,0 @@ -defmodule Comfycamp.SSO.OIDCRedirectURI do - use Ecto.Schema - import Ecto.Changeset - - alias Comfycamp.SSO.OIDCApp - - schema "oidc_redirect_uris" do - field :uri, :string - - belongs_to :oidc_app, OIDCApp, - type: :string, - foreign_key: :oidc_app_id, - references: :client_id - end - - @doc false - def changeset(uri, attrs) do - uri - |> cast(attrs, [:uri, :oidc_app_id]) - |> validate_required([:uri, :oidc_app_id]) - end -end diff --git a/lib/comfycamp_web/components/layouts/admin.html.heex b/lib/comfycamp_web/components/layouts/admin.html.heex index 2543e24..8c2fe79 100644 --- a/lib/comfycamp_web/components/layouts/admin.html.heex +++ b/lib/comfycamp_web/components/layouts/admin.html.heex @@ -21,11 +21,6 @@ Пользователи -
  • - <.link href={~p"/admin/oidc_apps"}> - OpenID - -
  • <.link href={~p"/admin/email"}> Email diff --git a/lib/comfycamp_web/controllers/oauth_controller.ex b/lib/comfycamp_web/controllers/oauth_controller.ex deleted file mode 100644 index 9fbe525..0000000 --- a/lib/comfycamp_web/controllers/oauth_controller.ex +++ /dev/null @@ -1,165 +0,0 @@ -defmodule ComfycampWeb.OauthController do - use ComfycampWeb, :controller - - alias Comfycamp.Accounts - alias Comfycamp.SSO - alias Comfycamp.SSO.OIDCApp - alias Comfycamp.SSO.IDToken - alias Comfycamp.Token - - @doc """ - Check the request parameters and current user status, - then ask the user to confirm that he wants to share his info with Relying Party. - """ - def authorize(conn, %{"client_id" => client_id, "redirect_uri" => redirect_uri} = params) do - app = SSO.get_oidc_app!(client_id) - current_user = conn.assigns.current_user - - with {:is_approved, true} <- {:is_approved, current_user.is_approved}, - {:response_type, "code"} <- {:response_type, params["response_type"]}, - {:is_enabled, true} <- {:is_enabled, app.enabled}, - {:has_uri, true} <- {:has_uri, SSO.has_redirect_uri?(client_id, redirect_uri)} do - render(conn, :authorize, - page_title: "Подтвердите вход", - app_name: app.name, - params: URI.encode_query(params) - ) - else - {:is_approved, false} -> - render(conn, :error, - description: - "Ваш аккаунт ещё не был одобрен, подождите немного или свяжитесь с администратором" - ) - - {:response_type, response_type} -> - render(conn, :error, description: "Неподдерживаемый response type: #{response_type}") - - {:is_enabled, false} -> - render(conn, :error, description: "Приложение отключено") - - {:has_uri, false} -> - render(conn, :error, description: "Redirect URI не зарегистрирован или отсутствует") - end - end - - @doc """ - Generate an Authorization Code and redirect the user back to Relying Party. - """ - def generate_code(conn, %{"client_id" => client_id, "redirect_uri" => redirect_uri} = params) do - app = SSO.get_oidc_app!(client_id) - current_user = conn.assigns.current_user - - with {:is_approved, true} <- {:is_approved, current_user.is_approved}, - {:is_enabled, true} <- {:is_enabled, app.enabled}, - {:has_uri, true} <- {:has_uri, SSO.has_redirect_uri?(client_id, redirect_uri)} do - {:ok, code} = - SSO.create_oidc_code(%{ - oidc_app_id: client_id, - user_id: conn.assigns.current_user.id, - redirect_uri: redirect_uri, - nonce: params["nonce"] - }) - - uri = build_redirect_uri(redirect_uri, code.value, params["state"]) - redirect(conn, external: uri) - else - {:is_approved, false} -> - render(conn, :error, - description: - "Ваш аккаунт ещё не был одобрен, подождите немного или свяжитесь с администратором" - ) - - {:is_enabled, false} -> - render(conn, :error, description: "Приложение отключено") - - {:has_uri, false} -> - render(conn, :error, description: "Redirect URI не зарегистрирован или отсутствует") - end - end - - def token(conn, params = %{"code" => code_value, "redirect_uri" => redirect_uri}) do - with {:client_info, {:ok, client_id, client_secret}} <- - {:client_info, get_client_info(conn, params)}, - {:code, code} <- {:code, SSO.get_oidc_code!(code_value)}, - {:uri, ^redirect_uri} <- {:uri, code.redirect_uri}, - {:app, oidc_app = %OIDCApp{enabled: true, client_id: ^client_id}} <- - {:app, SSO.get_oidc_app_by_secret!(client_secret)}, - {:code_ref, ^client_id} <- {:code_ref, code.oidc_app.client_id} do - SSO.delete_oidc_code(code) - - {access_token, refresh_token} = Accounts.generate_oauth_tokens(code.user) - - id_token = IDToken.build_id_token(code.user, oidc_app.client_id, code.nonce) - {:ok, signed_id_token} = Token.sign(id_token, client_secret) - - render(conn, :token, - access_token: Base.url_encode64(access_token), - refresh_token: Base.url_encode64(refresh_token), - id_token: signed_id_token - ) - else - {:client_info, _} -> - render(conn, :error, description: "Нет client id или client secret") - - {:code, _} -> - render(conn, :error, description: "Не удалось найти временный код") - - {:uri, _} -> - render(conn, :error, description: "Redirect URI не совпадает с изначальным значением") - - {:app, _} -> - render(conn, :error, description: "Приложение не найдено или отключено") - - {:code_ref, _} -> - render(conn, :error, description: "Временный код выдан для другого приложения") - end - end - - def openid_discovery(conn, _params) do - render(conn, :openid_discovery) - end - - def user_info(conn, _params) do - render(conn, :user_info, user: conn.assigns.oauth_user) - end - - @doc """ - Extract client id and client secret from request parameters or headers. - Returns {:ok, "client_id", "client_secret"} on success. - """ - def get_client_info(_conn, %{"client_id" => client_id, "client_secret" => client_secret}) do - {:ok, client_id, client_secret} - end - - def get_client_info(conn, _params) do - with [header] <- Plug.Conn.get_req_header(conn, "authorization"), - "Basic " <> b64 <- header, - {:ok, keys} <- Base.decode64(b64), - [client_id, client_secret] <- String.split(keys, ":") do - {:ok, client_id, client_secret} - else - _ -> {:error, "Invalid Authorization header"} - end - end - - defp build_redirect_uri(redirect_uri, code, state) do - parsed_uri = URI.parse(redirect_uri) - - query = - build_query_params(code, state) - |> URI.encode_query() - - %{parsed_uri | query: query} - |> URI.to_string() - end - - defp build_query_params(code, state) do - params = %{"code" => code} - - if state do - Map.put(params, "state", state) - else - params - end - end -end diff --git a/lib/comfycamp_web/controllers/oauth_html.ex b/lib/comfycamp_web/controllers/oauth_html.ex deleted file mode 100644 index 4564efe..0000000 --- a/lib/comfycamp_web/controllers/oauth_html.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule ComfycampWeb.OauthHTML do - use ComfycampWeb, :html - - def authorize(assigns) do - ~H""" -

    Подтвердите вход

    -

    Приложению "<%= @app_name %>" будут доступны:

    - - - <.link href={"/oauth/generate_code?#{@params}"} method="POST">Разрешить доступ - """ - end - - def error(assigns) do - ~H""" -

    Ошибка

    -

    <%= @description %>

    - """ - end -end diff --git a/lib/comfycamp_web/controllers/oauth_json.ex b/lib/comfycamp_web/controllers/oauth_json.ex deleted file mode 100644 index ba24278..0000000 --- a/lib/comfycamp_web/controllers/oauth_json.ex +++ /dev/null @@ -1,39 +0,0 @@ -defmodule ComfycampWeb.OauthJSON do - def token(%{access_token: access_token, refresh_token: refresh_token, id_token: id_token}) do - %{ - access_token: access_token, - token_type: "Bearer", - refresh_token: refresh_token, - id_token: id_token - } - end - - def openid_discovery(_assigns) do - %{ - issuer: "https://comfycamp.space", - authorization_endpoint: "https://comfycamp.space/oauth/authorize", - token_endpoint: "https://comfycamp.space/oauth/token", - userinfo_endpoint: "https://comfycamp.space/oauth/userinfo", - jwks_uri: "https://comfycamp.space/.well-known/jwks.json", - subject_types_supported: ["public"], - response_types_supported: ["code"], - id_token_signing_alg_values_supported: ["HS256"], - scopes_supported: ["openid", "profile", "email"], - claims_supported: ["sub", "email", "preferred_username"] - } - end - - def user_info(%{user: user}) do - %{ - sub: Integer.to_string(user.id), - email: user.email, - preferred_username: user.username - } - end - - def error(assigns) do - %{ - description: assigns["description"] - } - end -end diff --git a/lib/comfycamp_web/controllers/oidc_app_controller.ex b/lib/comfycamp_web/controllers/oidc_app_controller.ex deleted file mode 100644 index 1660ce8..0000000 --- a/lib/comfycamp_web/controllers/oidc_app_controller.ex +++ /dev/null @@ -1,76 +0,0 @@ -defmodule ComfycampWeb.OIDCAppController do - use ComfycampWeb, :controller - - alias Comfycamp.SSO - alias Comfycamp.SSO.OIDCApp - - def index(conn, _params) do - oidc_apps = SSO.list_oidc_apps() - - conn - |> put_layout(html: :admin) - |> render(:index, oidc_apps: oidc_apps) - end - - def new(conn, _params) do - changeset = SSO.change_oidc_app(%OIDCApp{}) - - conn - |> put_layout(html: :admin) - |> render(:new, changeset: changeset) - end - - def create(conn, %{"oidc_app" => oidc_app_params}) do - case SSO.create_oidc_app(oidc_app_params) do - {:ok, oidc_app} -> - conn - |> put_flash(:info, "Oidc app created successfully.") - |> redirect(to: ~p"/admin/oidc_apps/#{oidc_app}") - - {:error, %Ecto.Changeset{} = changeset} -> - conn - |> put_layout(html: :admin) - |> render(:new, changeset: changeset) - end - end - - def show(conn, %{"id" => client_id}) do - oidc_app = SSO.get_oidc_app!(client_id) - - conn - |> put_layout(html: :admin) - |> render(:show, oidc_app: oidc_app) - end - - def edit(conn, %{"id" => client_id}) do - oidc_app = SSO.get_oidc_app!(client_id) - changeset = SSO.change_oidc_app(oidc_app) - - conn - |> put_layout(html: :admin) - |> render(:edit, oidc_app: oidc_app, changeset: changeset) - end - - def update(conn, %{"id" => client_id, "oidc_app" => oidc_app_params}) do - oidc_app = SSO.get_oidc_app!(client_id) - - case SSO.update_oidc_app(oidc_app, oidc_app_params) do - {:ok, oidc_app} -> - conn - |> put_flash(:info, "Oidc app updated successfully.") - |> redirect(to: ~p"/admin/oidc_apps/#{oidc_app}") - - {:error, %Ecto.Changeset{} = changeset} -> - render(conn, :edit, oidc_app: oidc_app, changeset: changeset) - end - end - - def delete(conn, %{"id" => client_id}) do - oidc_app = SSO.get_oidc_app!(client_id) - {:ok, _oidc_app} = SSO.delete_oidc_app(oidc_app) - - conn - |> put_flash(:info, "Oidc app deleted successfully.") - |> redirect(to: ~p"/admin/oidc_apps") - end -end diff --git a/lib/comfycamp_web/controllers/oidc_app_html.ex b/lib/comfycamp_web/controllers/oidc_app_html.ex deleted file mode 100644 index ecee3a8..0000000 --- a/lib/comfycamp_web/controllers/oidc_app_html.ex +++ /dev/null @@ -1,13 +0,0 @@ -defmodule ComfycampWeb.OIDCAppHTML do - use ComfycampWeb, :html - - embed_templates "oidc_app_html/*" - - @doc """ - Renders a oidc_app form. - """ - attr :changeset, Ecto.Changeset, required: true - attr :action, :string, required: true - - def oidc_app_form(assigns) -end diff --git a/lib/comfycamp_web/controllers/oidc_app_html/edit.html.heex b/lib/comfycamp_web/controllers/oidc_app_html/edit.html.heex deleted file mode 100644 index b2b16d0..0000000 --- a/lib/comfycamp_web/controllers/oidc_app_html/edit.html.heex +++ /dev/null @@ -1,10 +0,0 @@ -
    - <.header> - Edit OpenID app "<%= @oidc_app.name %>" - <:subtitle>Use this form to manage oidc_app records in your database. - - - <.back navigate={~p"/admin/oidc_apps"}>Back to OpenID apps - - <.oidc_app_form changeset={@changeset} action={~p"/admin/oidc_apps/#{@oidc_app}"} /> -
    diff --git a/lib/comfycamp_web/controllers/oidc_app_html/index.html.heex b/lib/comfycamp_web/controllers/oidc_app_html/index.html.heex deleted file mode 100644 index f214687..0000000 --- a/lib/comfycamp_web/controllers/oidc_app_html/index.html.heex +++ /dev/null @@ -1,28 +0,0 @@ -
    - <.header> - Listing OpenID Connect apps - <:actions> - <.link href={~p"/admin/oidc_apps/new"}> - <.button>New OpenID Connect app - - - - - <.table id="oidc_apps" rows={@oidc_apps} row_click={&JS.navigate(~p"/admin/oidc_apps/#{&1}")}> - <:col :let={oidc_app} label="Name"><%= oidc_app.name %> - <:col :let={oidc_app} label="Client"><%= oidc_app.client_id %> - <:col :let={oidc_app} label="Client secret"><%= oidc_app.client_secret %> - <:col :let={oidc_app} label="Enabled"><%= oidc_app.enabled %> - <:action :let={oidc_app}> -
    - <.link navigate={~p"/admin/oidc_apps/#{oidc_app}"}>Show -
    - <.link navigate={~p"/admin/oidc_apps/#{oidc_app}/edit"}>Edit - - <:action :let={oidc_app}> - <.link href={~p"/admin/oidc_apps/#{oidc_app}"} method="delete" data-confirm="Are you sure?"> - Delete - - - -
    diff --git a/lib/comfycamp_web/controllers/oidc_app_html/new.html.heex b/lib/comfycamp_web/controllers/oidc_app_html/new.html.heex deleted file mode 100644 index 1971d84..0000000 --- a/lib/comfycamp_web/controllers/oidc_app_html/new.html.heex +++ /dev/null @@ -1,10 +0,0 @@ -
    - <.header> - New OpenID Connect app - <:subtitle>Use this form to manage oidc_app records in your database. - - - <.back navigate={~p"/admin/oidc_apps"}>Back to OpenID apps - - <.oidc_app_form changeset={@changeset} action={~p"/admin/oidc_apps"} /> -
    diff --git a/lib/comfycamp_web/controllers/oidc_app_html/oidc_app_form.html.heex b/lib/comfycamp_web/controllers/oidc_app_html/oidc_app_form.html.heex deleted file mode 100644 index da84b0b..0000000 --- a/lib/comfycamp_web/controllers/oidc_app_html/oidc_app_form.html.heex +++ /dev/null @@ -1,12 +0,0 @@ -
    - <.simple_form :let={f} for={@changeset} action={@action}> - <.error :if={@changeset.action}> - Oops, something went wrong! Please check the errors below. - - <.input field={f[:name]} type="text" label="Name" /> - <.input field={f[:enabled]} type="checkbox" label="Enabled" /> - <:actions> - <.button>Save Oidc app - - -
    diff --git a/lib/comfycamp_web/controllers/oidc_app_html/show.html.heex b/lib/comfycamp_web/controllers/oidc_app_html/show.html.heex deleted file mode 100644 index fe017ee..0000000 --- a/lib/comfycamp_web/controllers/oidc_app_html/show.html.heex +++ /dev/null @@ -1,41 +0,0 @@ -
    - <.header> - OpenID app "<%= @oidc_app.name %>" - <:subtitle>This is a oidc_app record from your database. - <:actions> - <.link href={~p"/admin/oidc_apps/#{@oidc_app}/edit"}> - <.button>Edit OpenID app - - - - - <.list> - <:item title="Name"><%= @oidc_app.name %> - <:item title="Client ID"><%= @oidc_app.client_id %> - <:item title="Client secret"><%= @oidc_app.client_secret %> - <:item title="Enabled"><%= @oidc_app.enabled %> - - -
      - <%= for uri <- @oidc_app.redirect_uris do %> -
    • - <%= uri.uri %> - <.link - href={~p"/admin/oidc_apps/#{@oidc_app}/redirect_uris/#{uri}"} - method="delete" - data-confirm="Хотите удалить ссылку?" - > - Удалить - -
    • - <% end %> -
    - - <.link navigate={~p"/admin/oidc_apps/#{@oidc_app}/redirect_uris/new"}> - <.button> - Добавить redirect URI - - - - <.back navigate={~p"/admin/oidc_apps"}>Back to OpenID apps -
    diff --git a/lib/comfycamp_web/controllers/oidc_uri_controller.ex b/lib/comfycamp_web/controllers/oidc_uri_controller.ex deleted file mode 100644 index 95075cc..0000000 --- a/lib/comfycamp_web/controllers/oidc_uri_controller.ex +++ /dev/null @@ -1,39 +0,0 @@ -defmodule ComfycampWeb.OIDCRedirectURIController do - use ComfycampWeb, :controller - - alias Comfycamp.SSO - alias Comfycamp.SSO.OIDCRedirectURI - - def new(conn, %{"client_id" => client_id}) do - changeset = SSO.change_oidc_redirect_uri(%OIDCRedirectURI{}) - oidc_app = SSO.get_oidc_app!(client_id) - - conn - |> put_layout(html: :admin) - |> render(:new, changeset: changeset, oidc_app: oidc_app) - end - - def create(conn, %{"client_id" => client_id, "oidc_redirect_uri" => uri_params}) do - oidc_app = SSO.get_oidc_app!(client_id) - uri_params = Map.put(uri_params, "oidc_app_id", client_id) - - case SSO.create_oidc_redirect_uri(uri_params) do - {:ok, _uri} -> - conn - |> redirect(to: ~p"/admin/oidc_apps/#{client_id}") - - {:error, %Ecto.Changeset{} = changeset} -> - conn - |> put_layout(html: :admin) - |> render(:new, changeset: changeset, oidc_app: oidc_app) - end - end - - def delete(conn, %{"client_id" => client_id, "id" => uri_id}) do - uri = SSO.get_oidc_redirect_uri!(uri_id) - {:ok, _uri} = SSO.delete_oidc_redirect_uri(uri) - - conn - |> redirect(to: ~p"/admin/oidc_apps/#{client_id}") - end -end diff --git a/lib/comfycamp_web/controllers/oidc_uri_html.ex b/lib/comfycamp_web/controllers/oidc_uri_html.ex deleted file mode 100644 index 373be2f..0000000 --- a/lib/comfycamp_web/controllers/oidc_uri_html.ex +++ /dev/null @@ -1,26 +0,0 @@ -defmodule ComfycampWeb.OIDCRedirectURIHTML do - use ComfycampWeb, :html - - def new(assigns) do - ~H""" -
    - <.header>Новый redirect URI - <.uri_form changeset={@changeset} action={~p"/admin/oidc_apps/#{@oidc_app}/redirect_uris"} /> -
    - """ - end - - def uri_form(assigns) do - ~H""" - <.simple_form :let={f} for={@changeset} action={@action}> - <.error :if={@changeset.action}> - Что-то пошло не так - - <.input field={f[:uri]} type="url" label="Redirect URI" /> - <:actions> - <.button>Сохранить - - - """ - end -end diff --git a/lib/comfycamp_web/router.ex b/lib/comfycamp_web/router.ex index cddb2ab..591eeac 100644 --- a/lib/comfycamp_web/router.ex +++ b/lib/comfycamp_web/router.ex @@ -15,7 +15,6 @@ defmodule ComfycampWeb.Router do pipeline :api do plug :accepts, ["json"] - plug :fetch_bearer_token end scope "/", ComfycampWeb do @@ -29,20 +28,6 @@ defmodule ComfycampWeb.Router do get "/cinema", CinemaController, :index end - scope "/", ComfycampWeb do - pipe_through :api - - post "/oauth/token", OauthController, :token - get "/.well-known/openid-configuration", OauthController, :openid_discovery - end - - scope "/", ComfycampWeb do - pipe_through [:api, :require_oauth] - - get "/oauth/userinfo", OauthController, :user_info - post "/oauth/userinfo", OauthController, :user_info - end - # Enable LiveDashboard and Swoosh mailbox preview in development if Application.compile_env(:comfycamp, :dev_routes) do # If you want to use the LiveDashboard in production, you should put @@ -88,13 +73,6 @@ defmodule ComfycampWeb.Router do scope "/", ComfycampWeb do pipe_through [:browser] - - scope "/" do - pipe_through [:require_authenticated_user] - - get "/oauth/authorize", OauthController, :authorize - post "/oauth/generate_code", OauthController, :generate_code - end end scope "/", ComfycampWeb do @@ -120,10 +98,6 @@ defmodule ComfycampWeb.Router do resources "/notes", NotesEditorController resources "/users", UserEditorController, only: [:index, :show] - resources "/oidc_apps", OIDCAppController - - resources "/oidc_apps/:client_id/redirect_uris", OIDCRedirectURIController, - only: [:new, :create, :delete] put "/users/:id/approve", UserEditorController, :approve put "/users/:id/disapprove", UserEditorController, :disapprove diff --git a/lib/comfycamp_web/user_auth.ex b/lib/comfycamp_web/user_auth.ex index 5567698..f0f7ce5 100644 --- a/lib/comfycamp_web/user_auth.ex +++ b/lib/comfycamp_web/user_auth.ex @@ -110,37 +110,6 @@ defmodule ComfycampWeb.UserAuth do end end - @doc """ - Authenticate the user by looking at Authorization header - and checking Bearer token. - """ - def fetch_bearer_token(conn, _opts) do - case Plug.Conn.get_req_header(conn, "authorization") do - ["Bearer " <> b64token] -> - token = Base.url_decode64!(b64token) - user = Accounts.get_user_by_bearer_token(token) - assign(conn, :oauth_user, user) - - _ -> - conn - end - end - - @doc """ - Check that request contains a valid bearer token. - Call after fetch_bearer_token plug. - """ - def require_oauth(conn, _opts) do - if conn.assigns[:oauth_user] do - conn - else - conn - |> put_status(:unauthorized) - |> json(%{error: "You must use a bearer token to access this page."}) - |> halt() - end - end - @doc """ Handles mounting and authenticating the current_user in LiveViews. diff --git a/priv/repo/migrations/20241020180106_delete_openid.exs b/priv/repo/migrations/20241020180106_delete_openid.exs new file mode 100644 index 0000000..47fb802 --- /dev/null +++ b/priv/repo/migrations/20241020180106_delete_openid.exs @@ -0,0 +1,9 @@ +defmodule Comfycamp.Repo.Migrations.DeleteOpenid do + use Ecto.Migration + + def change do + drop table(:oidc_redirect_uris) + drop table(:oidc_codes) + drop table(:oidc_apps) + end +end diff --git a/test/comfycamp/sso_test.exs b/test/comfycamp/sso_test.exs deleted file mode 100644 index a138511..0000000 --- a/test/comfycamp/sso_test.exs +++ /dev/null @@ -1,72 +0,0 @@ -defmodule Comfycamp.SSOTest do - use Comfycamp.DataCase - - alias Comfycamp.SSO - - describe "oidc_apps" do - alias Comfycamp.SSO.OIDCApp - - import Comfycamp.SSOFixtures - - @invalid_attrs %{enabled: nil, name: nil, client_id: nil, client_secret: nil} - - test "list_oidc_apps/0 returns all oidc_apps" do - oidc_app = oidc_app_fixture() - assert SSO.list_oidc_apps() == [oidc_app] - end - - test "get_oidc_app!/1 returns the oidc_app with given id" do - oidc_app = oidc_app_fixture() - assert SSO.get_oidc_app!(oidc_app.client_id).client_id == oidc_app.client_id - end - - test "create_oidc_app/1 with valid data creates a oidc_app" do - valid_attrs = %{ - enabled: true, - name: "some name", - client_id: "some client_id", - client_secret: "some client_secret" - } - - assert {:ok, %OIDCApp{} = oidc_app} = SSO.create_oidc_app(valid_attrs) - assert oidc_app.enabled == true - assert oidc_app.name == "some name" - end - - test "create_oidc_app/1 with invalid data returns error changeset" do - assert {:error, %Ecto.Changeset{}} = SSO.create_oidc_app(@invalid_attrs) - end - - test "update_oidc_app/2 with valid data updates the oidc_app" do - oidc_app = oidc_app_fixture() - - update_attrs = %{ - enabled: false, - name: "some updated name", - client_id: "some updated client_id", - client_secret: "some updated client_secret" - } - - assert {:ok, %OIDCApp{} = oidc_app} = SSO.update_oidc_app(oidc_app, update_attrs) - assert oidc_app.enabled == false - assert oidc_app.name == "some updated name" - end - - test "update_oidc_app/2 with invalid data returns error changeset" do - oidc_app = oidc_app_fixture() - assert {:error, %Ecto.Changeset{}} = SSO.update_oidc_app(oidc_app, @invalid_attrs) - assert oidc_app.client_id == SSO.get_oidc_app!(oidc_app.client_id).client_id - end - - test "delete_oidc_app/1 deletes the oidc_app" do - oidc_app = oidc_app_fixture() - assert {:ok, %OIDCApp{}} = SSO.delete_oidc_app(oidc_app) - assert_raise Ecto.NoResultsError, fn -> SSO.get_oidc_app!(oidc_app.client_id) end - end - - test "change_oidc_app/1 returns a oidc_app changeset" do - oidc_app = oidc_app_fixture() - assert %Ecto.Changeset{} = SSO.change_oidc_app(oidc_app) - end - end -end diff --git a/test/comfycamp_web/controllers/oidc_app_controller_test.exs b/test/comfycamp_web/controllers/oidc_app_controller_test.exs deleted file mode 100644 index dce266b..0000000 --- a/test/comfycamp_web/controllers/oidc_app_controller_test.exs +++ /dev/null @@ -1,100 +0,0 @@ -defmodule ComfycampWeb.OIDCAppControllerTest do - use ComfycampWeb.ConnCase - - import Comfycamp.SSOFixtures - - @create_attrs %{ - client_id: "some_client_id", - client_secret: "some client_secret", - name: "some name", - enabled: true - } - @update_attrs %{ - client_id: "some_client_id", - client_secret: "some updated client_secret", - name: "some updated name", - enabled: false - } - @invalid_attrs %{enabled: nil, name: nil, client_id: nil, client_secret: nil} - - describe "index" do - setup [:register_and_log_in_admin_user] - - test "lists all oidc_apps", %{conn: conn} do - conn = get(conn, ~p"/admin/oidc_apps") - assert html_response(conn, 200) =~ "Listing OpenID Connect apps" - end - end - - describe "new oidc_app" do - setup [:register_and_log_in_admin_user] - - test "renders form", %{conn: conn} do - conn = get(conn, ~p"/admin/oidc_apps/new") - assert html_response(conn, 200) =~ "New OpenID Connect app" - end - end - - describe "create oidc_app" do - setup [:register_and_log_in_admin_user] - - test "redirects to show when data is valid", %{conn: conn} do - conn = post(conn, ~p"/admin/oidc_apps", oidc_app: @create_attrs) - - assert %{id: client_id} = redirected_params(conn) - assert redirected_to(conn) == ~p"/admin/oidc_apps/#{client_id}" - - conn = get(conn, ~p"/admin/oidc_apps/#{client_id}") - assert html_response(conn, 200) =~ "OpenID app" - end - - test "renders errors when data is invalid", %{conn: conn} do - conn = post(conn, ~p"/admin/oidc_apps", oidc_app: @invalid_attrs) - assert html_response(conn, 200) =~ "New OpenID Connect app" - end - end - - describe "edit oidc_app" do - setup [:create_oidc_app, :register_and_log_in_admin_user] - - test "renders form for editing chosen oidc_app", %{conn: conn, oidc_app: oidc_app} do - conn = get(conn, ~p"/admin/oidc_apps/#{oidc_app}/edit") - assert html_response(conn, 200) =~ "Edit OpenID app" - end - end - - describe "update oidc_app" do - setup [:create_oidc_app, :register_and_log_in_admin_user] - - test "redirects when data is valid", %{conn: conn, oidc_app: oidc_app} do - conn = put(conn, ~p"/admin/oidc_apps/#{oidc_app}", oidc_app: @update_attrs) - assert redirected_to(conn) == ~p"/admin/oidc_apps/#{oidc_app}" - - conn = get(conn, ~p"/admin/oidc_apps/#{oidc_app}") - assert html_response(conn, 200) =~ "some updated name" - end - - test "renders errors when data is invalid", %{conn: conn, oidc_app: oidc_app} do - conn = put(conn, ~p"/admin/oidc_apps/#{oidc_app}", oidc_app: @invalid_attrs) - assert html_response(conn, 200) =~ "Edit OpenID app" - end - end - - describe "delete oidc_app" do - setup [:create_oidc_app, :register_and_log_in_admin_user] - - test "deletes chosen oidc_app", %{conn: conn, oidc_app: oidc_app} do - conn = delete(conn, ~p"/admin/oidc_apps/#{oidc_app}") - assert redirected_to(conn) == ~p"/admin/oidc_apps" - - assert_error_sent 404, fn -> - get(conn, ~p"/admin/oidc_apps/#{oidc_app}") - end - end - end - - defp create_oidc_app(_) do - oidc_app = oidc_app_fixture() - %{oidc_app: oidc_app} - end -end diff --git a/test/support/fixtures/sso_fixtures.ex b/test/support/fixtures/sso_fixtures.ex deleted file mode 100644 index 33f7de4..0000000 --- a/test/support/fixtures/sso_fixtures.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule Comfycamp.SSOFixtures do - @moduledoc """ - This module defines test helpers for creating - entities via the `Comfycamp.SSO` context. - """ - - @doc """ - Generate a oidc_app. - """ - def oidc_app_fixture(attrs \\ %{}) do - {:ok, oidc_app} = - attrs - |> Enum.into(%{ - client_id: "some_client_id", - client_secret: "some client_secret", - name: "some name", - enabled: true - }) - |> Comfycamp.SSO.create_oidc_app() - - oidc_app - end -end