From dadeb5c36ae5a3796f3e31931a1be8ec6958fd3e Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 1 Mar 2021 06:40:03 +0100 Subject: [PATCH] OpenAPI: OAuth Controllers --- .../web/api_spec/operations/o_auth_operation.ex | 250 +++++++++++++++++++++ lib/pleroma/web/auth/authenticator.ex | 2 +- lib/pleroma/web/o_auth/o_auth_controller.ex | 37 +-- lib/pleroma/web/o_auth/token/utils.ex | 2 +- lib/pleroma/web/router.ex | 8 +- .../controllers/account_controller_test.exs | 124 ++++++---- .../pleroma/web/o_auth/ldap_authorization_test.exs | 18 +- test/pleroma/web/o_auth/mfa_controller_test.exs | 12 +- test/pleroma/web/o_auth/o_auth_controller_test.exs | 46 ++-- 9 files changed, 397 insertions(+), 102 deletions(-) create mode 100644 lib/pleroma/web/api_spec/operations/o_auth_operation.ex diff --git a/lib/pleroma/web/api_spec/operations/o_auth_operation.ex b/lib/pleroma/web/api_spec/operations/o_auth_operation.ex new file mode 100644 index 000000000..d507fddd5 --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/o_auth_operation.ex @@ -0,0 +1,250 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.OAuthOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.Schemas.ApiError + + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + defp client_id_parameter(opts) do + Operation.parameter( + :client_id, + :query, + :string, + "Client ID, obtained during app registration", + opts + ) + end + + defp client_secret_parameter(opts) do + Operation.parameter( + :client_secret, + :query, + :string, + "Client secret, obtained during app registration", + opts + ) + end + + defp redirect_uri_parameter(opts) do + Operation.parameter( + :redirect_uri, + :query, + :string, + "Set a URI to redirect the user to. If this parameter is set to `urn:ietf:wg:oauth:2.0:oob` then the token will be shown instead. Must match one of the redirect URIs declared during app registration.", + opts + ) + end + + defp scope_parameter(opts) do + Operation.parameter( + :scope, + :query, + :string, + "List of requested OAuth scopes, separated by spaces. Must be a subset of scopes declared during app registration. If not provided, defaults to `read`.", + opts + ) + end + + def token_exchange_operation do + %Operation{ + tags: ["OAuth"], + summary: "Access Token Request", + operationId: "OAuthController.token_exchange", + parameters: [ + # code is required when grant_type == "authorization_code" + # Mastodon requires `redirect_uri`, we don't + client_id_parameter(required: true), + client_secret_parameter(required: true), + redirect_uri_parameter([]), + scope_parameter([]), + Operation.parameter( + :code, + :query, + :string, + "A user authorization code, obtained via /oauth/authorize" + ), + Operation.parameter( + :grant_type, + :query, + :string, + "Set equal to `authorization_code` if `code` is provided in order to gain user-level access. Set equal to `password` if `username` and `password` are provided. Otherwise, set equal to `client_credentials` to obtain app-level access only.", + required: true + ), + Operation.parameter(:username, :query, :string, "User's username, used with `grant_type=password`"), + Operation.parameter(:password, :query, :string, "User's password, used with `grant_type=password`") + ], + responses: %{ + 200 => + Operation.response("Success", "application/json", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError), + 403 => Operation.response("Error", "application/json", ApiError) + } + } + end + + def token_revoke_operation do + %Operation{ + tags: ["OAuth"], + summary: "Revokes token", + operationId: "OAuthController.token_revoke", + parameters: [], + responses: %{ + 200 => + Operation.response("Success", "application/json", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError) + } + } + end + + def registration_details_operation do + %Operation{ + tags: ["OAuth"], + summary: "Register", + operationId: "OAuthController.registration_details", + parameters: [], + responses: %{ + 200 => + Operation.response("Success", "application/json", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError) + } + } + end + + def authorize_operation do + %Operation{ + tags: ["OAuth"], + summary: "OAuth callback", + operationId: "OAuthController.authorize", + parameters: [ + client_id_parameter(required: true), + client_secret_parameter([]), + Operation.parameter( + :response_type, + :query, + :string, + "Note: `code` is the only value supported (MastodonAPI and OAuth 2.1)", + required: true + ), + redirect_uri_parameter([]), + scope_parameter([]), + Operation.parameter( + :state, + :query, + :string, + "An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client." + ) + ], + responses: %{ + 200 => + Operation.response("Success", "application/json", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError) + } + } + end + + def create_authorization_operation do + %Operation{ + tags: ["OAuth"], + summary: "Create Authorization", + operationId: "OAuthController.create_authorization", + parameters: [], + responses: %{ + 200 => + Operation.response("Success", "application/json", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError) + } + } + end + + def prepare_request_operation do + %Operation{ + tags: ["OAuth"], + summary: "Prepare OAuth request for third-party auth providers", + operationId: "OAuthController.prepare_request", + parameters: [], + responses: %{ + 302 => + Operation.response("Success", "text/html", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError) + } + } + end + + # The following operations should be moved to another controller, they aren't meant to be into OpenAPI + + def request_operation do + %Operation{ + tags: ["OAuth"], + summary: "", + operationId: "OAuthController.request", + parameters: [], + responses: %{ + 200 => + Operation.response("Success", "application/json", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError) + } + } + end + + def register_operation do + %Operation{ + tags: ["OAuth"], + summary: "", + operationId: "OAuthController.register", + parameters: [], + responses: %{ + 200 => + Operation.response("Success", "application/json", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError) + } + } + end + + def callback_operation do + %Operation{ + tags: ["OAuth"], + summary: "", + operationId: "OAuthController.callback", + parameters: [], + responses: %{ + 200 => + Operation.response("Success", "application/json", %Schema{ + type: :object, + properties: %{status: %Schema{type: :string, example: "success"}} + }), + 400 => Operation.response("Error", "application/json", ApiError) + } + } + end +end diff --git a/lib/pleroma/web/auth/authenticator.ex b/lib/pleroma/web/auth/authenticator.ex index 84741ee11..496c3973c 100644 --- a/lib/pleroma/web/auth/authenticator.ex +++ b/lib/pleroma/web/auth/authenticator.ex @@ -60,7 +60,7 @@ defmodule Pleroma.Web.Auth.Authenticator do %{"authorization" => %{"name" => name, "password" => password}} -> {:ok, {name, password}} - %{"grant_type" => "password", "username" => name, "password" => password} -> + %{grant_type: "password", username: name, password: password} -> {:ok, {name, password}} _ -> diff --git a/lib/pleroma/web/o_auth/o_auth_controller.ex b/lib/pleroma/web/o_auth/o_auth_controller.ex index 215d97b3a..741f57195 100644 --- a/lib/pleroma/web/o_auth/o_auth_controller.ex +++ b/lib/pleroma/web/o_auth/o_auth_controller.ex @@ -29,6 +29,11 @@ defmodule Pleroma.Web.OAuth.OAuthController do if Pleroma.Config.oauth_consumer_enabled?(), do: plug(Ueberauth) + plug( + Pleroma.Web.ApiSpec.CastAndValidate + when action not in [:prepare_request, :callback, :request, :register] + ) + plug(:fetch_session) plug(:fetch_flash) @@ -43,14 +48,16 @@ defmodule Pleroma.Web.OAuth.OAuthController do @oob_token_redirect_uri "urn:ietf:wg:oauth:2.0:oob" + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.OAuthOperation + # Note: this definition is only called from error-handling methods with `conn.params` as 2nd arg - def authorize(%Plug.Conn{} = conn, %{"authorization" => _} = params) do - {auth_attrs, params} = Map.pop(params, "authorization") + def authorize(%Plug.Conn{} = conn, %{authorization: _} = params) do + {auth_attrs, params} = Map.pop(params, :authorization) authorize(conn, Map.merge(params, auth_attrs)) end - def authorize(%Plug.Conn{assigns: %{token: %Token{}}} = conn, %{"force_login" => _} = params) do - if ControllerHelper.truthy_param?(params["force_login"]) do + def authorize(%Plug.Conn{assigns: %{token: %Token{}}} = conn, %{force_login: _} = params) do + if ControllerHelper.truthy_param?(params[:force_login]) do do_authorize(conn, params) else handle_existing_authorization(conn, params) @@ -63,7 +70,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do # So we have to check client and token. def authorize( %Plug.Conn{assigns: %{token: %Token{} = token}} = conn, - %{"client_id" => client_id} = params + %{client_id: client_id} = params ) do with %Token{} = t <- Repo.get_by(Token, token: token.token) |> Repo.preload(:app), ^client_id <- t.app.client_id do @@ -147,7 +154,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do create_authorization(conn, params, user: user) end - def create_authorization(%Plug.Conn{} = conn, %{"authorization" => _} = params, opts) do + def create_authorization(%Plug.Conn{} = conn, %{authorization: _} = params, opts) do with {:ok, auth, user} <- do_create_authorization(conn, params, opts[:user]), {:mfa_required, _, _, false} <- {:mfa_required, user, auth, MFA.require?(user)} do after_create_authorization(conn, auth, params) @@ -255,7 +262,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do @doc "Renew access_token with refresh_token" def token_exchange( %Plug.Conn{} = conn, - %{"grant_type" => "refresh_token", "refresh_token" => token} = _params + %{grant_type: "refresh_token", refresh_token: token} = _params ) do with {:ok, app} <- Token.Utils.fetch_app(conn), {:ok, %{user: user} = token} <- Token.get_by_refresh_token(app, token), @@ -266,9 +273,9 @@ defmodule Pleroma.Web.OAuth.OAuthController do end end - def token_exchange(%Plug.Conn{} = conn, %{"grant_type" => "authorization_code"} = params) do + def token_exchange(%Plug.Conn{} = conn, %{grant_type: "authorization_code"} = params) do with {:ok, app} <- Token.Utils.fetch_app(conn), - fixed_token = Token.Utils.fix_padding(params["code"]), + fixed_token = Token.Utils.fix_padding(params[:code]), {:ok, auth} <- Authorization.get_by_token(app, fixed_token), %User{} = user <- User.get_cached_by_id(auth.user_id), {:ok, token} <- Token.exchange_token(app, auth) do @@ -281,7 +288,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do def token_exchange( %Plug.Conn{} = conn, - %{"grant_type" => "password"} = params + %{grant_type: "password"} = params ) do with {:ok, %User{} = user} <- Authenticator.get_user(conn), {:ok, app} <- Token.Utils.fetch_app(conn), @@ -296,7 +303,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do def token_exchange( %Plug.Conn{} = conn, - %{"grant_type" => "password", "name" => name, "password" => _password} = params + %{grant_type: "password", name: name, password: _password} = params ) do params = params @@ -306,7 +313,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do token_exchange(conn, params) end - def token_exchange(%Plug.Conn{} = conn, %{"grant_type" => "client_credentials"} = _params) do + def token_exchange(%Plug.Conn{} = conn, %{grant_type: "client_credentials"} = _params) do with {:ok, app} <- Token.Utils.fetch_app(conn), {:ok, auth} <- Authorization.create_authorization(app, %User{}), {:ok, token} <- Token.exchange_token(app, auth) do @@ -379,7 +386,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do render_invalid_credentials_error(conn) end - def token_revoke(%Plug.Conn{} = conn, %{"token" => token}) do + def token_revoke(%Plug.Conn{} = conn, %{token: token}) do with {:ok, %Token{} = oauth_token} <- Token.get_by_token(token), {:ok, oauth_token} <- RevokeToken.revoke(oauth_token) do conn = @@ -477,7 +484,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do conn |> put_session_registration_id(registration.id) - |> registration_details(%{"authorization" => registration_params}) + |> registration_details(%{authorization: registration_params}) end else error -> @@ -493,7 +500,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do Map.merge(params, Jason.decode!(state)) end - def registration_details(%Plug.Conn{} = conn, %{"authorization" => auth_attrs}) do + def registration_details(%Plug.Conn{} = conn, %{authorization: auth_attrs}) do render(conn, "register.html", %{ client_id: auth_attrs["client_id"], redirect_uri: auth_attrs["redirect_uri"], diff --git a/lib/pleroma/web/o_auth/token/utils.ex b/lib/pleroma/web/o_auth/token/utils.ex index b572dc9cf..11ee34c72 100644 --- a/lib/pleroma/web/o_auth/token/utils.ex +++ b/lib/pleroma/web/o_auth/token/utils.ex @@ -41,7 +41,7 @@ defmodule Pleroma.Web.OAuth.Token.Utils do ) do {id, secret} else - _ -> {conn.params["client_id"], conn.params["client_secret"]} + _ -> {conn.params[:client_id], conn.params[:client_secret]} end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 8ba0fc702..34df3f365 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -30,11 +30,17 @@ defmodule Pleroma.Web.Router do plug(:fetch_session) end + pipeline :fetch_session_api do + plug(:fetch_session) + plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec) + end + pipeline :oauth do plug(:fetch_session) plug(Pleroma.Web.Plugs.OAuthPlug) plug(Pleroma.Web.Plugs.UserEnabledPlug) plug(Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug) + plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec) end # Note: expects _user_ authentication (user-unbound app-bound tokens don't qualify) @@ -344,7 +350,7 @@ defmodule Pleroma.Web.Router do end scope [] do - pipe_through(:fetch_session) + pipe_through(:fetch_session_api) post("/token", OAuthController, :token_exchange) post("/revoke", OAuthController, :token_revoke) diff --git a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs index 3036e25b3..d14c7ef2e 100644 --- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs @@ -1049,7 +1049,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do clear_config([:instance, :account_activation_required], false) clear_config([:instance, :account_approval_required], false) - conn = + apps_response = conn |> put_req_header("content-type", "application/json") |> post("/api/v1/apps", %{ @@ -1057,6 +1057,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do redirect_uris: "urn:ietf:wg:oauth:2.0:oob", scopes: "read, write, follow" }) + |> json_response_and_validate_schema(200) assert %{ "client_id" => client_id, @@ -1066,17 +1067,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob", "vapid_key" => _, "website" => nil - } = json_response_and_validate_schema(conn, 200) + } = apps_response - conn = - post(conn, "/oauth/token", %{ - grant_type: "client_credentials", - client_id: client_id, - client_secret: client_secret - }) + token_response = + conn + |> put_req_header("content-type", "application/x-www-form-urlencoded") + |> post( + "/oauth/token?#{ + URI.encode_query(%{ + "grant_type" => "client_credentials", + "client_id" => client_id, + "client_secret" => client_secret + }) + }" + ) + |> json_response_and_validate_schema(200) assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} = - json_response(conn, 200) + token_response assert token token_from_db = Repo.get_by(Token, token: token) @@ -1131,7 +1139,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do clear_config([:instance, :account_activation_required], true) clear_config([:instance, :account_approval_required], false) - conn = + register_response = conn |> put_req_header("content-type", "application/json") |> post("/api/v1/apps", %{ @@ -1139,6 +1147,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do redirect_uris: "urn:ietf:wg:oauth:2.0:oob", scopes: "read, write, follow" }) + |> json_response_and_validate_schema(200) assert %{ "client_id" => client_id, @@ -1148,17 +1157,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob", "vapid_key" => _, "website" => nil - } = json_response_and_validate_schema(conn, 200) + } = register_response - conn = - post(conn, "/oauth/token", %{ - grant_type: "client_credentials", - client_id: client_id, - client_secret: client_secret - }) + token_response = + conn + |> put_req_header("content-type", "application/x-www-form-urlencoded") + |> post( + "/oauth/token?#{ + URI.encode_query(%{ + "grant_type" => "client_credentials", + "client_id" => client_id, + "client_secret" => client_secret + }) + }" + ) + |> json_response_and_validate_schema(200) assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} = - json_response(conn, 200) + token_response assert token token_from_db = Repo.get_by(Token, token: token) @@ -1166,19 +1182,19 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do assert refresh assert scope == "read write follow" - conn = - build_conn() - |> put_req_header("content-type", "multipart/form-data") - |> put_req_header("authorization", "Bearer " <> token) - |> post("/api/v1/accounts", %{ - username: "lain", - email: "lain@example.org", - password: "PlzDontHackLain", - bio: "Test Bio", - agreement: true - }) + assert response = + conn + |> put_req_header("content-type", "multipart/form-data") + |> put_req_header("authorization", "Bearer " <> token) + |> post("/api/v1/accounts", %{ + username: "lain", + email: "lain@example.org", + password: "PlzDontHackLain", + bio: "Test Bio", + agreement: true + }) + |> json_response_and_validate_schema(200) - response = json_response_and_validate_schema(conn, 200) assert %{"identifier" => "missing_confirmed_email"} = response refute response["access_token"] refute response["token_type"] @@ -1191,7 +1207,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do clear_config([:instance, :account_approval_required], true) clear_config([:instance, :account_activation_required], false) - conn = + apps_response = conn |> put_req_header("content-type", "application/json") |> post("/api/v1/apps", %{ @@ -1199,6 +1215,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do redirect_uris: "urn:ietf:wg:oauth:2.0:oob", scopes: "read, write, follow" }) + |> json_response_and_validate_schema(200) assert %{ "client_id" => client_id, @@ -1208,17 +1225,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob", "vapid_key" => _, "website" => nil - } = json_response_and_validate_schema(conn, 200) + } = apps_response - conn = - post(conn, "/oauth/token", %{ - grant_type: "client_credentials", - client_id: client_id, - client_secret: client_secret - }) + token_response = + conn + |> put_req_header("content-type", "application/x-www-form-urlencoded") + |> post( + "/oauth/token?#{ + URI.encode_query(%{ + "grant_type" => "client_credentials", + "client_id" => client_id, + "client_secret" => client_secret + }) + }" + ) + |> json_response_and_validate_schema(200) assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} = - json_response(conn, 200) + token_response assert token token_from_db = Repo.get_by(Token, token: token) @@ -1226,7 +1250,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do assert refresh assert scope == "read write follow" - conn = + response = build_conn() |> put_req_header("content-type", "multipart/form-data") |> put_req_header("authorization", "Bearer " <> token) @@ -1238,8 +1262,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do agreement: true, reason: "I'm a cool dude, bro" }) + |> json_response_and_validate_schema(200) - response = json_response_and_validate_schema(conn, 200) assert %{"identifier" => "awaiting_approval"} = response refute response["access_token"] refute response["token_type"] @@ -1372,13 +1396,19 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do conn = build_conn() - |> post("/oauth/token", %{ - "grant_type" => "client_credentials", - "client_id" => app.client_id, - "client_secret" => app.client_secret - }) + |> put_req_header("content-type", "application/x-www-form-urlencoded") + |> post( + "/oauth/token?#{ + URI.encode_query(%{ + "grant_type" => "client_credentials", + "client_id" => app.client_id, + "client_secret" => app.client_secret + }) + }" + ) - assert %{"access_token" => token, "token_type" => "Bearer"} = json_response(conn, 200) + assert %{"access_token" => token, "token_type" => "Bearer"} = + json_response_and_validate_schema(conn, 200) response = build_conn() diff --git a/test/pleroma/web/o_auth/ldap_authorization_test.exs b/test/pleroma/web/o_auth/ldap_authorization_test.exs index 61b9ce6b7..a839ed4a7 100644 --- a/test/pleroma/web/o_auth/ldap_authorization_test.exs +++ b/test/pleroma/web/o_auth/ldap_authorization_test.exs @@ -37,15 +37,15 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do ] do conn = build_conn() - |> post("/oauth/token", %{ + |> post("/oauth/token?#{URI.encode_query(%{ "grant_type" => "password", "username" => user.nickname, "password" => password, "client_id" => app.client_id, "client_secret" => app.client_secret - }) + })}") - assert %{"access_token" => token} = json_response(conn, 200) + assert %{"access_token" => token} = json_response_and_validate_schema(conn, 200) token = Repo.get_by(Token, token: token) @@ -81,15 +81,15 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do ] do conn = build_conn() - |> post("/oauth/token", %{ + |> post("/oauth/token?#{URI.encode_query(%{ "grant_type" => "password", "username" => user.nickname, "password" => password, "client_id" => app.client_id, "client_secret" => app.client_secret - }) + })}") - assert %{"access_token" => token} = json_response(conn, 200) + assert %{"access_token" => token} = json_response_and_validate_schema(conn, 200) token = Repo.get_by(Token, token: token) |> Repo.preload(:user) @@ -120,15 +120,15 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do ] do conn = build_conn() - |> post("/oauth/token", %{ + |> post("/oauth/token?#{URI.encode_query(%{ "grant_type" => "password", "username" => user.nickname, "password" => password, "client_id" => app.client_id, "client_secret" => app.client_secret - }) + })}") - assert %{"error" => "Invalid credentials"} = json_response(conn, 400) + assert %{"error" => "Invalid credentials"} = json_response_and_validate_schema(conn, 400) assert_received :close_connection end end diff --git a/test/pleroma/web/o_auth/mfa_controller_test.exs b/test/pleroma/web/o_auth/mfa_controller_test.exs index 17bbde85b..041ab3f41 100644 --- a/test/pleroma/web/o_auth/mfa_controller_test.exs +++ b/test/pleroma/web/o_auth/mfa_controller_test.exs @@ -164,7 +164,7 @@ defmodule Pleroma.Web.OAuth.MFAControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) ap_id = user.ap_id @@ -192,7 +192,7 @@ defmodule Pleroma.Web.OAuth.MFAControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(400) + |> json_response_and_validate_schema(400) assert response == %{"error" => "Invalid code"} end @@ -209,7 +209,7 @@ defmodule Pleroma.Web.OAuth.MFAControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(400) + |> json_response_and_validate_schema(400) assert response == %{"error" => "Invalid code"} end @@ -227,7 +227,7 @@ defmodule Pleroma.Web.OAuth.MFAControllerTest do "client_id" => "xxx", "client_secret" => "xxx" }) - |> json_response(400) + |> json_response_and_validate_schema(400) assert response == %{"error" => "Invalid code"} end @@ -272,7 +272,7 @@ defmodule Pleroma.Web.OAuth.MFAControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) ap_id = user.ap_id @@ -296,7 +296,7 @@ defmodule Pleroma.Web.OAuth.MFAControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(400) + |> json_response_and_validate_schema(400) assert error_response == %{"error" => "Invalid code"} end diff --git a/test/pleroma/web/o_auth/o_auth_controller_test.exs b/test/pleroma/web/o_auth/o_auth_controller_test.exs index 312500feb..c0f243a75 100644 --- a/test/pleroma/web/o_auth/o_auth_controller_test.exs +++ b/test/pleroma/web/o_auth/o_auth_controller_test.exs @@ -780,7 +780,8 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_secret" => app.client_secret }) - assert %{"access_token" => token, "me" => ap_id} = json_response(conn, 200) + assert %{"access_token" => token, "me" => ap_id} = + json_response_and_validate_schema(conn, 200) token = Repo.get_by(Token, token: token) assert token @@ -805,7 +806,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_secret" => app.client_secret }) - assert %{"access_token" => token} = json_response(conn, 200) + assert %{"access_token" => token} = json_response_and_validate_schema(conn, 200) token = Repo.get_by(Token, token: token) assert token @@ -836,7 +837,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(403) + |> json_response_and_validate_schema(403) assert match?( %{ @@ -872,7 +873,8 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "redirect_uri" => OAuthController.default_redirect_uri(app) }) - assert %{"access_token" => token, "scope" => scope} = json_response(conn, 200) + assert %{"access_token" => token, "scope" => scope} = + json_response_and_validate_schema(conn, 200) assert scope == "scope1 scope2" @@ -893,7 +895,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do }) assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} = - json_response(conn, 200) + json_response_and_validate_schema(conn, 200) assert token token_from_db = Repo.get_by(Token, token: token) @@ -917,7 +919,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "redirect_uri" => OAuthController.default_redirect_uri(app) }) - assert resp = json_response(conn, 400) + assert resp = json_response_and_validate_schema(conn, 400) assert %{"error" => _} = resp refute Map.has_key?(resp, "access_token") end @@ -945,7 +947,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_secret" => app.client_secret }) - assert resp = json_response(conn, 403) + assert resp = json_response_and_validate_schema(conn, 403) assert %{"error" => _} = resp refute Map.has_key?(resp, "access_token") end @@ -970,7 +972,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(403) + |> json_response_and_validate_schema(403) assert resp == %{ "error" => "Your account is currently disabled", @@ -998,7 +1000,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(403) + |> json_response_and_validate_schema(403) assert resp == %{ "error" => "Password reset is required", @@ -1027,7 +1029,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(403) + |> json_response_and_validate_schema(403) assert resp == %{ "error" => "Your login is missing a confirmed e-mail address", @@ -1058,7 +1060,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_secret" => app.client_secret }) - assert resp = json_response(conn, 403) + assert resp = json_response_and_validate_schema(conn, 403) assert %{"error" => _} = resp refute Map.has_key?(resp, "access_token") end @@ -1076,8 +1078,8 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_secret" => app.client_secret }) - assert resp = json_response(conn, 400) - assert %{"error" => _} = json_response(conn, 400) + assert resp = json_response_and_validate_schema(conn, 400) + assert %{"error" => _} = json_response_and_validate_schema(conn, 400) refute Map.has_key?(resp, "access_token") end end @@ -1101,7 +1103,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(200) + |> json_response_and_validate_schema(200) ap_id = user.ap_id @@ -1140,7 +1142,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(200) + |> json_response_and_validate_schema(200) ap_id = user.ap_id @@ -1178,7 +1180,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(400) + |> json_response_and_validate_schema(400) assert %{"error" => "Invalid credentials"} == response end @@ -1194,7 +1196,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(400) + |> json_response_and_validate_schema(400) assert %{"error" => "Invalid credentials"} == response end @@ -1222,7 +1224,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do "client_id" => app.client_id, "client_secret" => app.client_secret }) - |> json_response(200) + |> json_response_and_validate_schema(200) ap_id = user.ap_id @@ -1251,7 +1253,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do response = build_conn() |> post("/oauth/token", %{}) - |> json_response(500) + |> json_response_and_validate_schema(500) assert %{"error" => "Bad request"} == response end @@ -1268,7 +1270,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do |> AuthHelper.put_session_token(oauth_token.token) |> post("/oauth/revoke", %{"token" => oauth_token.token}) - assert json_response(conn, 200) + assert json_response_and_validate_schema(conn, 200) refute AuthHelper.get_session_token(conn) assert Token.get_by_token(oauth_token.token) == {:error, :not_found} @@ -1287,7 +1289,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do |> AuthHelper.put_session_token(oauth_token.token) |> post("/oauth/revoke", %{"token" => other_app_oauth_token.token}) - assert json_response(conn, 200) + assert json_response_and_validate_schema(conn, 200) assert AuthHelper.get_session_token(conn) == oauth_token.token assert Token.get_by_token(other_app_oauth_token.token) == {:error, :not_found} @@ -1297,7 +1299,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do response = build_conn() |> post("/oauth/revoke", %{}) - |> json_response(500) + |> json_response_and_validate_schema(500) assert %{"error" => "Bad request"} == response end