1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.OAuth.OAuthControllerTest do
6 use Pleroma.Web.ConnCase
10 alias Pleroma.MFA.TOTP
13 alias Pleroma.Web.OAuth.Authorization
14 alias Pleroma.Web.OAuth.OAuthController
15 alias Pleroma.Web.OAuth.Token
20 signing_salt: "cooldude"
22 setup do: clear_config([:instance, :account_activation_required])
24 describe "in OAuth consumer mode, " do
27 app: insert(:oauth_app),
30 |> Plug.Session.call(Plug.Session.init(@session_opts))
35 setup do: clear_config([:auth, :oauth_consumer_strategies], ~w(twitter facebook))
37 test "GET /oauth/authorize renders auth forms, including OAuth consumer form", %{
46 "response_type" => "code",
47 "client_id" => app.client_id,
48 "redirect_uri" => OAuthController.default_redirect_uri(app),
53 assert response = html_response(conn, 200)
54 assert response =~ "Sign in with Twitter"
55 assert response =~ o_auth_path(conn, :prepare_request)
58 test "GET /oauth/prepare_request encodes parameters as `state` and redirects", %{
65 "/oauth/prepare_request",
67 "provider" => "twitter",
69 "scope" => "read follow",
70 "client_id" => app.client_id,
71 "redirect_uri" => OAuthController.default_redirect_uri(app),
77 assert response = html_response(conn, 302)
79 redirect_query = URI.parse(redirected_to(conn)).query
80 assert %{"state" => state_param} = URI.decode_query(redirect_query)
81 assert {:ok, state_components} = Poison.decode(state_param)
83 expected_client_id = app.client_id
84 expected_redirect_uri = app.redirect_uris
87 "scope" => "read follow",
88 "client_id" => ^expected_client_id,
89 "redirect_uri" => ^expected_redirect_uri,
94 test "with user-bound registration, GET /oauth/<provider>/callback redirects to `redirect_uri` with `code`",
95 %{app: app, conn: conn} do
96 registration = insert(:registration)
97 redirect_uri = OAuthController.default_redirect_uri(app)
100 "scope" => Enum.join(app.scopes, " "),
101 "client_id" => app.client_id,
102 "redirect_uri" => redirect_uri,
108 |> assign(:ueberauth_auth, %{provider: registration.provider, uid: registration.uid})
110 "/oauth/twitter/callback",
112 "oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM",
113 "oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs",
114 "provider" => "twitter",
115 "state" => Poison.encode!(state_params)
119 assert response = html_response(conn, 302)
120 assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/
123 test "with user-unbound registration, GET /oauth/<provider>/callback renders registration_details page",
124 %{app: app, conn: conn} do
128 "scope" => "read write",
129 "client_id" => app.client_id,
130 "redirect_uri" => OAuthController.default_redirect_uri(app),
136 |> assign(:ueberauth_auth, %{
139 info: %{nickname: user.nickname, email: user.email, name: user.name, description: nil}
142 "/oauth/twitter/callback",
144 "oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM",
145 "oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs",
146 "provider" => "twitter",
147 "state" => Poison.encode!(state_params)
151 assert response = html_response(conn, 200)
152 assert response =~ ~r/name="op" type="submit" value="register"/
153 assert response =~ ~r/name="op" type="submit" value="connect"/
154 assert response =~ user.email
155 assert response =~ user.nickname
158 test "on authentication error, GET /oauth/<provider>/callback redirects to `redirect_uri`", %{
163 "scope" => Enum.join(app.scopes, " "),
164 "client_id" => app.client_id,
165 "redirect_uri" => OAuthController.default_redirect_uri(app),
171 |> assign(:ueberauth_failure, %{errors: [%{message: "(error description)"}]})
173 "/oauth/twitter/callback",
175 "oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM",
176 "oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs",
177 "provider" => "twitter",
178 "state" => Poison.encode!(state_params)
182 assert response = html_response(conn, 302)
183 assert redirected_to(conn) == app.redirect_uris
184 assert get_flash(conn, :error) == "Failed to authenticate: (error description)."
187 test "GET /oauth/registration_details renders registration details form", %{
194 "/oauth/registration_details",
196 "authorization" => %{
197 "scopes" => app.scopes,
198 "client_id" => app.client_id,
199 "redirect_uri" => OAuthController.default_redirect_uri(app),
200 "state" => "a_state",
202 "email" => "john@doe.com"
207 assert response = html_response(conn, 200)
208 assert response =~ ~r/name="op" type="submit" value="register"/
209 assert response =~ ~r/name="op" type="submit" value="connect"/
212 test "with valid params, POST /oauth/register?op=register redirects to `redirect_uri` with `code`",
217 registration = insert(:registration, user: nil, info: %{"nickname" => nil, "email" => nil})
218 redirect_uri = OAuthController.default_redirect_uri(app)
222 |> put_session(:registration_id, registration.id)
227 "authorization" => %{
228 "scopes" => app.scopes,
229 "client_id" => app.client_id,
230 "redirect_uri" => redirect_uri,
231 "state" => "a_state",
232 "nickname" => "availablenick",
233 "email" => "available@email.com"
238 assert response = html_response(conn, 302)
239 assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/
242 test "with unlisted `redirect_uri`, POST /oauth/register?op=register results in HTTP 401",
247 registration = insert(:registration, user: nil, info: %{"nickname" => nil, "email" => nil})
248 unlisted_redirect_uri = "http://cross-site-request.com"
252 |> put_session(:registration_id, registration.id)
257 "authorization" => %{
258 "scopes" => app.scopes,
259 "client_id" => app.client_id,
260 "redirect_uri" => unlisted_redirect_uri,
261 "state" => "a_state",
262 "nickname" => "availablenick",
263 "email" => "available@email.com"
268 assert response = html_response(conn, 401)
271 test "with invalid params, POST /oauth/register?op=register renders registration_details page",
276 another_user = insert(:user)
277 registration = insert(:registration, user: nil, info: %{"nickname" => nil, "email" => nil})
281 "authorization" => %{
282 "scopes" => app.scopes,
283 "client_id" => app.client_id,
284 "redirect_uri" => OAuthController.default_redirect_uri(app),
285 "state" => "a_state",
286 "nickname" => "availablenickname",
287 "email" => "available@email.com"
291 for {bad_param, bad_param_value} <-
292 [{"nickname", another_user.nickname}, {"email", another_user.email}] do
293 bad_registration_attrs = %{
294 "authorization" => Map.put(params["authorization"], bad_param, bad_param_value)
297 bad_params = Map.merge(params, bad_registration_attrs)
301 |> put_session(:registration_id, registration.id)
302 |> post("/oauth/register", bad_params)
304 assert html_response(conn, 403) =~ ~r/name="op" type="submit" value="register"/
305 assert get_flash(conn, :error) == "Error: #{bad_param} has already been taken."
309 test "with valid params, POST /oauth/register?op=connect redirects to `redirect_uri` with `code`",
314 user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt("testpassword"))
315 registration = insert(:registration, user: nil)
316 redirect_uri = OAuthController.default_redirect_uri(app)
320 |> put_session(:registration_id, registration.id)
325 "authorization" => %{
326 "scopes" => app.scopes,
327 "client_id" => app.client_id,
328 "redirect_uri" => redirect_uri,
329 "state" => "a_state",
330 "name" => user.nickname,
331 "password" => "testpassword"
336 assert response = html_response(conn, 302)
337 assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/
340 test "with unlisted `redirect_uri`, POST /oauth/register?op=connect results in HTTP 401`",
345 user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt("testpassword"))
346 registration = insert(:registration, user: nil)
347 unlisted_redirect_uri = "http://cross-site-request.com"
351 |> put_session(:registration_id, registration.id)
356 "authorization" => %{
357 "scopes" => app.scopes,
358 "client_id" => app.client_id,
359 "redirect_uri" => unlisted_redirect_uri,
360 "state" => "a_state",
361 "name" => user.nickname,
362 "password" => "testpassword"
367 assert response = html_response(conn, 401)
370 test "with invalid params, POST /oauth/register?op=connect renders registration_details page",
376 registration = insert(:registration, user: nil)
380 "authorization" => %{
381 "scopes" => app.scopes,
382 "client_id" => app.client_id,
383 "redirect_uri" => OAuthController.default_redirect_uri(app),
384 "state" => "a_state",
385 "name" => user.nickname,
386 "password" => "wrong password"
392 |> put_session(:registration_id, registration.id)
393 |> post("/oauth/register", params)
395 assert html_response(conn, 401) =~ ~r/name="op" type="submit" value="connect"/
396 assert get_flash(conn, :error) == "Invalid Username/Password"
400 describe "GET /oauth/authorize" do
403 app: insert(:oauth_app, redirect_uris: "https://redirect.url"),
406 |> Plug.Session.call(Plug.Session.init(@session_opts))
411 test "renders authentication page", %{app: app, conn: conn} do
417 "response_type" => "code",
418 "client_id" => app.client_id,
419 "redirect_uri" => OAuthController.default_redirect_uri(app),
424 assert html_response(conn, 200) =~ ~s(type="submit")
427 test "properly handles internal calls with `authorization`-wrapped params", %{
436 "authorization" => %{
437 "response_type" => "code",
438 "client_id" => app.client_id,
439 "redirect_uri" => OAuthController.default_redirect_uri(app),
445 assert html_response(conn, 200) =~ ~s(type="submit")
448 test "renders authentication page if user is already authenticated but `force_login` is tru-ish",
449 %{app: app, conn: conn} do
450 token = insert(:oauth_token, app: app)
454 |> put_session(:oauth_token, token.token)
458 "response_type" => "code",
459 "client_id" => app.client_id,
460 "redirect_uri" => OAuthController.default_redirect_uri(app),
462 "force_login" => "true"
466 assert html_response(conn, 200) =~ ~s(type="submit")
469 test "renders authentication page if user is already authenticated but user request with another client",
474 token = insert(:oauth_token, app: app)
478 |> put_session(:oauth_token, token.token)
482 "response_type" => "code",
483 "client_id" => "another_client_id",
484 "redirect_uri" => OAuthController.default_redirect_uri(app),
489 assert html_response(conn, 200) =~ ~s(type="submit")
492 test "with existing authentication and non-OOB `redirect_uri`, redirects to app with `token` and `state` params",
497 token = insert(:oauth_token, app: app)
501 |> put_session(:oauth_token, token.token)
505 "response_type" => "code",
506 "client_id" => app.client_id,
507 "redirect_uri" => OAuthController.default_redirect_uri(app),
508 "state" => "specific_client_state",
513 assert URI.decode(redirected_to(conn)) ==
514 "https://redirect.url?access_token=#{token.token}&state=specific_client_state"
517 test "with existing authentication and unlisted non-OOB `redirect_uri`, redirects without credentials",
522 unlisted_redirect_uri = "http://cross-site-request.com"
523 token = insert(:oauth_token, app: app)
527 |> put_session(:oauth_token, token.token)
531 "response_type" => "code",
532 "client_id" => app.client_id,
533 "redirect_uri" => unlisted_redirect_uri,
534 "state" => "specific_client_state",
539 assert redirected_to(conn) == unlisted_redirect_uri
542 test "with existing authentication and OOB `redirect_uri`, redirects to app with `token` and `state` params",
547 token = insert(:oauth_token, app: app)
551 |> put_session(:oauth_token, token.token)
555 "response_type" => "code",
556 "client_id" => app.client_id,
557 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
562 assert html_response(conn, 200) =~ "Authorization exists"
566 describe "POST /oauth/authorize" do
567 test "redirects with oauth authorization, " <>
568 "granting requested app-supported scopes to both admin- and non-admin users" do
569 app_scopes = ["read", "write", "admin", "secret_scope"]
570 app = insert(:oauth_app, scopes: app_scopes)
571 redirect_uri = OAuthController.default_redirect_uri(app)
573 non_admin = insert(:user, is_admin: false)
574 admin = insert(:user, is_admin: true)
575 scopes_subset = ["read:subscope", "write", "admin"]
577 # In case scope param is missing, expecting _all_ app-supported scopes to be granted
578 for user <- [non_admin, admin],
579 {requested_scopes, expected_scopes} <-
580 %{scopes_subset => scopes_subset, nil: app_scopes} do
586 "authorization" => %{
587 "name" => user.nickname,
588 "password" => "test",
589 "client_id" => app.client_id,
590 "redirect_uri" => redirect_uri,
591 "scope" => requested_scopes,
592 "state" => "statepassed"
597 target = redirected_to(conn)
598 assert target =~ redirect_uri
600 query = URI.parse(target).query |> URI.query_decoder() |> Map.new()
602 assert %{"state" => "statepassed", "code" => code} = query
603 auth = Repo.get_by(Authorization, token: code)
605 assert auth.scopes == expected_scopes
609 test "redirect to on two-factor auth page" do
610 otp_secret = TOTP.generate_secret()
614 multi_factor_authentication_settings: %MFA.Settings{
616 totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
620 app = insert(:oauth_app, scopes: ["read", "write", "follow"])
624 |> post("/oauth/authorize", %{
625 "authorization" => %{
626 "name" => user.nickname,
627 "password" => "test",
628 "client_id" => app.client_id,
629 "redirect_uri" => app.redirect_uris,
630 "scope" => "read write",
631 "state" => "statepassed"
635 result = html_response(conn, 200)
637 mfa_token = Repo.get_by(MFA.Token, user_id: user.id)
638 assert result =~ app.redirect_uris
639 assert result =~ "statepassed"
640 assert result =~ mfa_token.token
641 assert result =~ "Two-factor authentication"
644 test "returns 401 for wrong credentials", %{conn: conn} do
646 app = insert(:oauth_app)
647 redirect_uri = OAuthController.default_redirect_uri(app)
651 |> post("/oauth/authorize", %{
652 "authorization" => %{
653 "name" => user.nickname,
654 "password" => "wrong",
655 "client_id" => app.client_id,
656 "redirect_uri" => redirect_uri,
657 "state" => "statepassed",
658 "scope" => Enum.join(app.scopes, " ")
661 |> html_response(:unauthorized)
664 assert result =~ app.client_id
665 assert result =~ redirect_uri
668 assert result =~ "Invalid Username/Password"
671 test "returns 401 for missing scopes" do
672 user = insert(:user, is_admin: false)
673 app = insert(:oauth_app, scopes: ["read", "write", "admin"])
674 redirect_uri = OAuthController.default_redirect_uri(app)
678 |> post("/oauth/authorize", %{
679 "authorization" => %{
680 "name" => user.nickname,
681 "password" => "test",
682 "client_id" => app.client_id,
683 "redirect_uri" => redirect_uri,
684 "state" => "statepassed",
688 |> html_response(:unauthorized)
691 assert result =~ app.client_id
692 assert result =~ redirect_uri
695 assert result =~ "This action is outside the authorized scopes"
698 test "returns 401 for scopes beyond app scopes hierarchy", %{conn: conn} do
700 app = insert(:oauth_app, scopes: ["read", "write"])
701 redirect_uri = OAuthController.default_redirect_uri(app)
705 |> post("/oauth/authorize", %{
706 "authorization" => %{
707 "name" => user.nickname,
708 "password" => "test",
709 "client_id" => app.client_id,
710 "redirect_uri" => redirect_uri,
711 "state" => "statepassed",
712 "scope" => "read write follow"
715 |> html_response(:unauthorized)
718 assert result =~ app.client_id
719 assert result =~ redirect_uri
722 assert result =~ "This action is outside the authorized scopes"
726 describe "POST /oauth/token" do
727 test "issues a token for an all-body request" do
729 app = insert(:oauth_app, scopes: ["read", "write"])
731 {:ok, auth} = Authorization.create_authorization(app, user, ["write"])
735 |> post("/oauth/token", %{
736 "grant_type" => "authorization_code",
737 "code" => auth.token,
738 "redirect_uri" => OAuthController.default_redirect_uri(app),
739 "client_id" => app.client_id,
740 "client_secret" => app.client_secret
743 assert %{"access_token" => token, "me" => ap_id} = json_response(conn, 200)
745 token = Repo.get_by(Token, token: token)
747 assert token.scopes == auth.scopes
748 assert user.ap_id == ap_id
751 test "issues a token for `password` grant_type with valid credentials, with full permissions by default" do
752 password = "testpassword"
753 user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))
755 app = insert(:oauth_app, scopes: ["read", "write"])
757 # Note: "scope" param is intentionally omitted
760 |> post("/oauth/token", %{
761 "grant_type" => "password",
762 "username" => user.nickname,
763 "password" => password,
764 "client_id" => app.client_id,
765 "client_secret" => app.client_secret
768 assert %{"access_token" => token} = json_response(conn, 200)
770 token = Repo.get_by(Token, token: token)
772 assert token.scopes == app.scopes
775 test "issues a mfa token for `password` grant_type, when MFA enabled" do
776 password = "testpassword"
777 otp_secret = TOTP.generate_secret()
781 password_hash: Pbkdf2.hash_pwd_salt(password),
782 multi_factor_authentication_settings: %MFA.Settings{
784 totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
788 app = insert(:oauth_app, scopes: ["read", "write"])
792 |> post("/oauth/token", %{
793 "grant_type" => "password",
794 "username" => user.nickname,
795 "password" => password,
796 "client_id" => app.client_id,
797 "client_secret" => app.client_secret
799 |> json_response(403)
803 "supported_challenge_types" => "totp",
805 "error" => "mfa_required"
810 token = Repo.get_by(MFA.Token, token: response["mfa_token"])
811 assert token.user_id == user.id
812 assert token.authorization_id
815 test "issues a token for request with HTTP basic auth client credentials" do
817 app = insert(:oauth_app, scopes: ["scope1", "scope2", "scope3"])
819 {:ok, auth} = Authorization.create_authorization(app, user, ["scope1", "scope2"])
820 assert auth.scopes == ["scope1", "scope2"]
823 (URI.encode_www_form(app.client_id) <> ":" <> URI.encode_www_form(app.client_secret))
828 |> put_req_header("authorization", "Basic " <> app_encoded)
829 |> post("/oauth/token", %{
830 "grant_type" => "authorization_code",
831 "code" => auth.token,
832 "redirect_uri" => OAuthController.default_redirect_uri(app)
835 assert %{"access_token" => token, "scope" => scope} = json_response(conn, 200)
837 assert scope == "scope1 scope2"
839 token = Repo.get_by(Token, token: token)
841 assert token.scopes == ["scope1", "scope2"]
844 test "issue a token for client_credentials grant type" do
845 app = insert(:oauth_app, scopes: ["read", "write"])
849 |> post("/oauth/token", %{
850 "grant_type" => "client_credentials",
851 "client_id" => app.client_id,
852 "client_secret" => app.client_secret
855 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
856 json_response(conn, 200)
859 token_from_db = Repo.get_by(Token, token: token)
862 assert scope == "read write"
865 test "rejects token exchange with invalid client credentials" do
867 app = insert(:oauth_app)
869 {:ok, auth} = Authorization.create_authorization(app, user)
873 |> put_req_header("authorization", "Basic JTIxOiVGMCU5RiVBNCVCNwo=")
874 |> post("/oauth/token", %{
875 "grant_type" => "authorization_code",
876 "code" => auth.token,
877 "redirect_uri" => OAuthController.default_redirect_uri(app)
880 assert resp = json_response(conn, 400)
881 assert %{"error" => _} = resp
882 refute Map.has_key?(resp, "access_token")
885 test "rejects token exchange for valid credentials belonging to unconfirmed user and confirmation is required" do
886 Pleroma.Config.put([:instance, :account_activation_required], true)
887 password = "testpassword"
890 insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))
891 |> User.confirmation_changeset(need_confirmation: true)
892 |> User.update_and_set_cache()
894 refute Pleroma.User.account_status(user) == :active
896 app = insert(:oauth_app)
900 |> post("/oauth/token", %{
901 "grant_type" => "password",
902 "username" => user.nickname,
903 "password" => password,
904 "client_id" => app.client_id,
905 "client_secret" => app.client_secret
908 assert resp = json_response(conn, 403)
909 assert %{"error" => _} = resp
910 refute Map.has_key?(resp, "access_token")
913 test "rejects token exchange for valid credentials belonging to deactivated user" do
914 password = "testpassword"
918 password_hash: Pbkdf2.hash_pwd_salt(password),
922 app = insert(:oauth_app)
926 |> post("/oauth/token", %{
927 "grant_type" => "password",
928 "username" => user.nickname,
929 "password" => password,
930 "client_id" => app.client_id,
931 "client_secret" => app.client_secret
933 |> json_response(403)
936 "error" => "Your account is currently disabled",
937 "identifier" => "account_is_disabled"
941 test "rejects token exchange for user with password_reset_pending set to true" do
942 password = "testpassword"
946 password_hash: Pbkdf2.hash_pwd_salt(password),
947 password_reset_pending: true
950 app = insert(:oauth_app, scopes: ["read", "write"])
954 |> post("/oauth/token", %{
955 "grant_type" => "password",
956 "username" => user.nickname,
957 "password" => password,
958 "client_id" => app.client_id,
959 "client_secret" => app.client_secret
961 |> json_response(403)
964 "error" => "Password reset is required",
965 "identifier" => "password_reset_required"
969 test "rejects token exchange for user with confirmation_pending set to true" do
970 Pleroma.Config.put([:instance, :account_activation_required], true)
971 password = "testpassword"
975 password_hash: Pbkdf2.hash_pwd_salt(password),
976 confirmation_pending: true
979 app = insert(:oauth_app, scopes: ["read", "write"])
983 |> post("/oauth/token", %{
984 "grant_type" => "password",
985 "username" => user.nickname,
986 "password" => password,
987 "client_id" => app.client_id,
988 "client_secret" => app.client_secret
990 |> json_response(403)
993 "error" => "Your login is missing a confirmed e-mail address",
994 "identifier" => "missing_confirmed_email"
998 test "rejects an invalid authorization code" do
999 app = insert(:oauth_app)
1003 |> post("/oauth/token", %{
1004 "grant_type" => "authorization_code",
1005 "code" => "Imobviouslyinvalid",
1006 "redirect_uri" => OAuthController.default_redirect_uri(app),
1007 "client_id" => app.client_id,
1008 "client_secret" => app.client_secret
1011 assert resp = json_response(conn, 400)
1012 assert %{"error" => _} = json_response(conn, 400)
1013 refute Map.has_key?(resp, "access_token")
1017 describe "POST /oauth/token - refresh token" do
1018 setup do: clear_config([:oauth2, :issue_new_refresh_token])
1020 test "issues a new access token with keep fresh token" do
1021 Pleroma.Config.put([:oauth2, :issue_new_refresh_token], true)
1022 user = insert(:user)
1023 app = insert(:oauth_app, scopes: ["read", "write"])
1025 {:ok, auth} = Authorization.create_authorization(app, user, ["write"])
1026 {:ok, token} = Token.exchange_token(app, auth)
1030 |> post("/oauth/token", %{
1031 "grant_type" => "refresh_token",
1032 "refresh_token" => token.refresh_token,
1033 "client_id" => app.client_id,
1034 "client_secret" => app.client_secret
1036 |> json_response(200)
1043 "token_type" => "Bearer",
1044 "expires_in" => 600,
1045 "access_token" => _,
1046 "refresh_token" => _,
1052 refute Repo.get_by(Token, token: token.token)
1053 new_token = Repo.get_by(Token, token: response["access_token"])
1054 assert new_token.refresh_token == token.refresh_token
1055 assert new_token.scopes == auth.scopes
1056 assert new_token.user_id == user.id
1057 assert new_token.app_id == app.id
1060 test "issues a new access token with new fresh token" do
1061 Pleroma.Config.put([:oauth2, :issue_new_refresh_token], false)
1062 user = insert(:user)
1063 app = insert(:oauth_app, scopes: ["read", "write"])
1065 {:ok, auth} = Authorization.create_authorization(app, user, ["write"])
1066 {:ok, token} = Token.exchange_token(app, auth)
1070 |> post("/oauth/token", %{
1071 "grant_type" => "refresh_token",
1072 "refresh_token" => token.refresh_token,
1073 "client_id" => app.client_id,
1074 "client_secret" => app.client_secret
1076 |> json_response(200)
1083 "token_type" => "Bearer",
1084 "expires_in" => 600,
1085 "access_token" => _,
1086 "refresh_token" => _,
1092 refute Repo.get_by(Token, token: token.token)
1093 new_token = Repo.get_by(Token, token: response["access_token"])
1094 refute new_token.refresh_token == token.refresh_token
1095 assert new_token.scopes == auth.scopes
1096 assert new_token.user_id == user.id
1097 assert new_token.app_id == app.id
1100 test "returns 400 if we try use access token" do
1101 user = insert(:user)
1102 app = insert(:oauth_app, scopes: ["read", "write"])
1104 {:ok, auth} = Authorization.create_authorization(app, user, ["write"])
1105 {:ok, token} = Token.exchange_token(app, auth)
1109 |> post("/oauth/token", %{
1110 "grant_type" => "refresh_token",
1111 "refresh_token" => token.token,
1112 "client_id" => app.client_id,
1113 "client_secret" => app.client_secret
1115 |> json_response(400)
1117 assert %{"error" => "Invalid credentials"} == response
1120 test "returns 400 if refresh_token invalid" do
1121 app = insert(:oauth_app, scopes: ["read", "write"])
1125 |> post("/oauth/token", %{
1126 "grant_type" => "refresh_token",
1127 "refresh_token" => "token.refresh_token",
1128 "client_id" => app.client_id,
1129 "client_secret" => app.client_secret
1131 |> json_response(400)
1133 assert %{"error" => "Invalid credentials"} == response
1136 test "issues a new token if token expired" do
1137 user = insert(:user)
1138 app = insert(:oauth_app, scopes: ["read", "write"])
1140 {:ok, auth} = Authorization.create_authorization(app, user, ["write"])
1141 {:ok, token} = Token.exchange_token(app, auth)
1144 Ecto.Changeset.change(
1146 %{valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), -86_400 * 30)}
1149 {:ok, access_token} = Repo.update(change)
1153 |> post("/oauth/token", %{
1154 "grant_type" => "refresh_token",
1155 "refresh_token" => access_token.refresh_token,
1156 "client_id" => app.client_id,
1157 "client_secret" => app.client_secret
1159 |> json_response(200)
1166 "token_type" => "Bearer",
1167 "expires_in" => 600,
1168 "access_token" => _,
1169 "refresh_token" => _,
1175 refute Repo.get_by(Token, token: token.token)
1176 token = Repo.get_by(Token, token: response["access_token"])
1178 assert token.scopes == auth.scopes
1179 assert token.user_id == user.id
1180 assert token.app_id == app.id
1184 describe "POST /oauth/token - bad request" do
1185 test "returns 500" do
1188 |> post("/oauth/token", %{})
1189 |> json_response(500)
1191 assert %{"error" => "Bad request"} == response
1195 describe "POST /oauth/revoke - bad request" do
1196 test "returns 500" do
1199 |> post("/oauth/revoke", %{})
1200 |> json_response(500)
1202 assert %{"error" => "Bad request"} == response