Add tests for LDAP authorization
authorlink0ff <juri@linkov.net>
Fri, 15 Mar 2019 14:28:46 +0000 (16:28 +0200)
committerlink0ff <juri@linkov.net>
Fri, 15 Mar 2019 14:28:46 +0000 (16:28 +0200)
test/web/oauth/ldap_authorization_test.exs [new file with mode: 0644]

diff --git a/test/web/oauth/ldap_authorization_test.exs b/test/web/oauth/ldap_authorization_test.exs
new file mode 100644 (file)
index 0000000..570e41f
--- /dev/null
@@ -0,0 +1,187 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
+  use Pleroma.Web.ConnCase
+  alias Pleroma.Repo
+  alias Pleroma.Web.OAuth.Token
+  import Pleroma.Factory
+  import ExUnit.CaptureLog
+  import Mock
+
+  setup_all do
+    ldap_authenticator = Pleroma.Config.get([Pleroma.Web.Auth.Authenticator])
+    ldap_enabled = Pleroma.Config.get([:ldap, :enabled])
+
+    on_exit(fn ->
+      Pleroma.Config.put([Pleroma.Web.Auth.Authenticator], ldap_authenticator)
+      Pleroma.Config.put([:ldap, :enabled], ldap_enabled)
+    end)
+
+    Pleroma.Config.put([Pleroma.Web.Auth.Authenticator], Pleroma.Web.Auth.LDAPAuthenticator)
+    Pleroma.Config.put([:ldap, :enabled], true)
+
+    :ok
+  end
+
+  test "authorizes the existing user using LDAP credentials" do
+    password = "testpassword"
+    user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
+    app = insert(:oauth_app, scopes: ["read", "write"])
+
+    host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
+    port = Pleroma.Config.get([:ldap, :port])
+
+    with_mocks [
+      {:eldap, [],
+       [
+         open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
+         simple_bind: fn _connection, _dn, ^password -> :ok end,
+         close: fn _connection ->
+           send(self(), :close_connection)
+           :ok
+         end
+       ]}
+    ] do
+      conn =
+        build_conn()
+        |> post("/oauth/token", %{
+          "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)
+
+      token = Repo.get_by(Token, token: token)
+
+      assert token.user_id == user.id
+      assert_received :close_connection
+    end
+  end
+
+  test "creates a new user after successful LDAP authorization" do
+    password = "testpassword"
+    user = build(:user)
+    app = insert(:oauth_app, scopes: ["read", "write"])
+
+    host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
+    port = Pleroma.Config.get([:ldap, :port])
+
+    with_mocks [
+      {:eldap, [],
+       [
+         open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
+         simple_bind: fn _connection, _dn, ^password -> :ok end,
+         equalityMatch: fn _type, _value -> :ok end,
+         wholeSubtree: fn -> :ok end,
+         search: fn _connection, _options ->
+           {:ok,
+            {:eldap_search_result, [{:eldap_entry, '', [{'mail', [to_charlist(user.email)]}]}],
+             []}}
+         end,
+         close: fn _connection ->
+           send(self(), :close_connection)
+           :ok
+         end
+       ]}
+    ] do
+      conn =
+        build_conn()
+        |> post("/oauth/token", %{
+          "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)
+
+      token = Repo.get_by(Token, token: token) |> Repo.preload(:user)
+
+      assert token.user.nickname == user.nickname
+      assert_received :close_connection
+    end
+  end
+
+  test "falls back to the default authorization when LDAP is unavailable" do
+    password = "testpassword"
+    user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
+    app = insert(:oauth_app, scopes: ["read", "write"])
+
+    host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
+    port = Pleroma.Config.get([:ldap, :port])
+
+    with_mocks [
+      {:eldap, [],
+       [
+         open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:error, 'connect failed'} end,
+         simple_bind: fn _connection, _dn, ^password -> :ok end,
+         close: fn _connection ->
+           send(self(), :close_connection)
+           :ok
+         end
+       ]}
+    ] do
+      log =
+        capture_log(fn ->
+          conn =
+            build_conn()
+            |> post("/oauth/token", %{
+              "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)
+
+          token = Repo.get_by(Token, token: token)
+
+          assert token.user_id == user.id
+        end)
+
+      assert log =~ "Could not open LDAP connection: 'connect failed'"
+      refute_received :close_connection
+    end
+  end
+
+  test "disallow authorization for wrong LDAP credentials" do
+    password = "testpassword"
+    user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
+    app = insert(:oauth_app, scopes: ["read", "write"])
+
+    host = Pleroma.Config.get([:ldap, :host]) |> to_charlist
+    port = Pleroma.Config.get([:ldap, :port])
+
+    with_mocks [
+      {:eldap, [],
+       [
+         open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
+         simple_bind: fn _connection, _dn, ^password -> {:error, :invalidCredentials} end,
+         close: fn _connection ->
+           send(self(), :close_connection)
+           :ok
+         end
+       ]}
+    ] do
+      conn =
+        build_conn()
+        |> post("/oauth/token", %{
+          "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_received :close_connection
+    end
+  end
+end