Introduce support for 3rd-party auth (OAuth2 & LDAP)
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
34
test/service/auth/authentificator_test.exs
Normal file
34
test/service/auth/authentificator_test.exs
Normal file
@@ -0,0 +1,34 @@
|
||||
defmodule Mobilizon.Service.Auth.AuthenticatorTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
alias Mobilizon.Service.Auth.Authenticator
|
||||
alias Mobilizon.Users
|
||||
alias Mobilizon.Users.User
|
||||
import Mobilizon.Factory
|
||||
|
||||
@email "email@domain.tld"
|
||||
@password "password"
|
||||
|
||||
describe "test authentification" do
|
||||
test "authenticate/1 checks the user's password" do
|
||||
{:ok, %User{} = user} = Users.register(%{email: @email, password: @password})
|
||||
Users.update_user(user, %{confirmed_at: DateTime.utc_now()})
|
||||
|
||||
assert {:ok, _} = Authenticator.authenticate(@email, @password)
|
||||
|
||||
assert {:error, :bad_password} ==
|
||||
Authenticator.authenticate(@email, "completely wrong password")
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch_user/1" do
|
||||
test "returns user by email" do
|
||||
user = insert(:user)
|
||||
assert Authenticator.fetch_user(user.email).id == user.id
|
||||
end
|
||||
|
||||
test "returns nil" do
|
||||
assert Authenticator.fetch_user("email") == {:error, :user_not_found}
|
||||
end
|
||||
end
|
||||
end
|
||||
238
test/service/auth/ldap_authentificator_test.exs
Normal file
238
test/service/auth/ldap_authentificator_test.exs
Normal file
@@ -0,0 +1,238 @@
|
||||
defmodule Mobilizon.Service.Auth.LDAPAuthenticatorTest do
|
||||
use Mobilizon.Web.ConnCase
|
||||
use Mobilizon.Tests.Helpers
|
||||
|
||||
alias Mobilizon.GraphQL.AbsintheHelpers
|
||||
alias Mobilizon.Service.Auth.{Authenticator, LDAPAuthenticator}
|
||||
alias Mobilizon.Users.User
|
||||
alias Mobilizon.Web.Auth.Guardian
|
||||
|
||||
import Mobilizon.Factory
|
||||
import ExUnit.CaptureLog
|
||||
import Mock
|
||||
|
||||
@skip if !Code.ensure_loaded?(:eldap), do: :skip
|
||||
@admin_password "admin_password"
|
||||
|
||||
setup_all do
|
||||
clear_config([:ldap, :enabled], true)
|
||||
clear_config([:ldap, :bind_uid], "admin")
|
||||
clear_config([:ldap, :bind_password], @admin_password)
|
||||
end
|
||||
|
||||
setup_all do:
|
||||
clear_config(
|
||||
Authenticator,
|
||||
LDAPAuthenticator
|
||||
)
|
||||
|
||||
@login_mutation """
|
||||
mutation Login($email: String!, $password: String!) {
|
||||
login(email: $email, password: $password) {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
user {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
describe "login" do
|
||||
@tag @skip
|
||||
test "authorizes the existing user using LDAP credentials", %{conn: conn} do
|
||||
user_password = "testpassword"
|
||||
admin_password = "admin_password"
|
||||
user = insert(:user, password_hash: Argon2.hash_pwd_salt(user_password))
|
||||
|
||||
host = [:ldap, :host] |> Mobilizon.Config.get() |> to_charlist
|
||||
port = Mobilizon.Config.get([:ldap, :port])
|
||||
|
||||
with_mocks [
|
||||
{:eldap, [],
|
||||
[
|
||||
open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
|
||||
simple_bind: fn _connection, _dn, password ->
|
||||
case password do
|
||||
^admin_password -> :ok
|
||||
^user_password -> :ok
|
||||
end
|
||||
end,
|
||||
equalityMatch: fn _type, _value -> :ok end,
|
||||
wholeSubtree: fn -> :ok end,
|
||||
search: fn _connection, _options ->
|
||||
{:ok,
|
||||
{:eldap_search_result, [{:eldap_entry, '', [{'cn', [to_charlist("MyUser")]}]}], []}}
|
||||
end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
]}
|
||||
] do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @login_mutation,
|
||||
variables: %{email: user.email, password: user_password}
|
||||
)
|
||||
|
||||
assert is_nil(res["error"])
|
||||
assert token = res["data"]["login"]["accessToken"]
|
||||
|
||||
{:ok, %User{} = user_from_token, _claims} = Guardian.resource_from_token(token)
|
||||
|
||||
assert user_from_token.id == user.id
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
|
||||
@tag @skip
|
||||
test "creates a new user after successful LDAP authorization", %{conn: conn} do
|
||||
user_password = "testpassword"
|
||||
admin_password = "admin_password"
|
||||
user = build(:user)
|
||||
|
||||
host = [:ldap, :host] |> Mobilizon.Config.get() |> to_charlist
|
||||
port = Mobilizon.Config.get([:ldap, :port])
|
||||
|
||||
with_mocks [
|
||||
{:eldap, [],
|
||||
[
|
||||
open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:ok, self()} end,
|
||||
simple_bind: fn _connection, _dn, password ->
|
||||
case password do
|
||||
^admin_password -> :ok
|
||||
^user_password -> :ok
|
||||
end
|
||||
end,
|
||||
equalityMatch: fn _type, _value -> :ok end,
|
||||
wholeSubtree: fn -> :ok end,
|
||||
search: fn _connection, _options ->
|
||||
{:ok,
|
||||
{:eldap_search_result, [{:eldap_entry, '', [{'cn', [to_charlist("MyUser")]}]}], []}}
|
||||
end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
]}
|
||||
] do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @login_mutation,
|
||||
variables: %{email: user.email, password: user_password}
|
||||
)
|
||||
|
||||
assert is_nil(res["error"])
|
||||
assert token = res["data"]["login"]["accessToken"]
|
||||
|
||||
{:ok, %User{} = user_from_token, _claims} = Guardian.resource_from_token(token)
|
||||
|
||||
assert user_from_token.email == user.email
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
|
||||
@tag @skip
|
||||
test "falls back to the default authorization when LDAP is unavailable", %{conn: conn} do
|
||||
user_password = "testpassword"
|
||||
admin_password = "admin_password"
|
||||
user = insert(:user, password_hash: Argon2.hash_pwd_salt(user_password))
|
||||
|
||||
host = [:ldap, :host] |> Mobilizon.Config.get() |> to_charlist
|
||||
port = Mobilizon.Config.get([:ldap, :port])
|
||||
|
||||
with_mocks [
|
||||
{:eldap, [],
|
||||
[
|
||||
open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:error, 'connect failed'} end,
|
||||
simple_bind: fn _connection, _dn, password ->
|
||||
case password do
|
||||
^admin_password -> :ok
|
||||
^user_password -> :ok
|
||||
end
|
||||
end,
|
||||
equalityMatch: fn _type, _value -> :ok end,
|
||||
wholeSubtree: fn -> :ok end,
|
||||
search: fn _connection, _options ->
|
||||
{:ok,
|
||||
{:eldap_search_result, [{:eldap_entry, '', [{'cn', [to_charlist("MyUser")]}]}], []}}
|
||||
end,
|
||||
close: fn _connection ->
|
||||
send(self(), :close_connection)
|
||||
:ok
|
||||
end
|
||||
]}
|
||||
] do
|
||||
log =
|
||||
capture_log(fn ->
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @login_mutation,
|
||||
variables: %{email: user.email, password: user_password}
|
||||
)
|
||||
|
||||
assert is_nil(res["error"])
|
||||
assert token = res["data"]["login"]["accessToken"]
|
||||
|
||||
{:ok, %User{} = user_from_token, _claims} = Guardian.resource_from_token(token)
|
||||
|
||||
assert user_from_token.email == user.email
|
||||
end)
|
||||
|
||||
assert log =~ "Could not open LDAP connection: 'connect failed'"
|
||||
refute_received :close_connection
|
||||
end
|
||||
end
|
||||
|
||||
@tag @skip
|
||||
test "disallow authorization for wrong LDAP credentials", %{conn: conn} do
|
||||
user_password = "testpassword"
|
||||
user = insert(:user, password_hash: Argon2.hash_pwd_salt(user_password))
|
||||
|
||||
host = [:ldap, :host] |> Mobilizon.Config.get() |> to_charlist
|
||||
port = Mobilizon.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
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @login_mutation,
|
||||
variables: %{email: user.email, password: user_password}
|
||||
)
|
||||
|
||||
refute is_nil(res["errors"])
|
||||
|
||||
assert assert hd(res["errors"])["message"] ==
|
||||
"Impossible to authenticate, either your email or password are invalid."
|
||||
|
||||
assert_received :close_connection
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "can change" do
|
||||
test "password" do
|
||||
assert LDAPAuthenticator.can_change_password?(%User{provider: "ldap"}) == false
|
||||
assert LDAPAuthenticator.can_change_password?(%User{provider: nil}) == true
|
||||
end
|
||||
|
||||
test "email" do
|
||||
assert LDAPAuthenticator.can_change_password?(%User{provider: "ldap"}) == false
|
||||
assert LDAPAuthenticator.can_change_password?(%User{provider: nil}) == true
|
||||
end
|
||||
end
|
||||
end
|
||||
29
test/service/auth/mobilizon_authentificator_test.exs
Normal file
29
test/service/auth/mobilizon_authentificator_test.exs
Normal file
@@ -0,0 +1,29 @@
|
||||
defmodule Mobilizon.Service.Auth.MobilizonAuthenticatorTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
alias Mobilizon.Service.Auth.MobilizonAuthenticator
|
||||
alias Mobilizon.Users.User
|
||||
import Mobilizon.Factory
|
||||
|
||||
setup do
|
||||
password = "testpassword"
|
||||
email = "someone@somewhere.tld"
|
||||
user = insert(:user, email: email, password_hash: Argon2.hash_pwd_salt(password))
|
||||
{:ok, [user: user, email: email, password: password]}
|
||||
end
|
||||
|
||||
test "login", %{email: email, password: password, user: user} do
|
||||
assert {:ok, %User{} = returned_user} = MobilizonAuthenticator.login(email, password)
|
||||
assert returned_user.id == user.id
|
||||
end
|
||||
|
||||
test "login with invalid password", %{email: email} do
|
||||
assert {:error, :bad_password} == MobilizonAuthenticator.login(email, "invalid")
|
||||
assert {:error, :bad_password} == MobilizonAuthenticator.login(email, nil)
|
||||
end
|
||||
|
||||
test "login with no credentials" do
|
||||
assert {:error, :user_not_found} == MobilizonAuthenticator.login("some@email.com", nil)
|
||||
assert {:error, :user_not_found} == MobilizonAuthenticator.login(nil, nil)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user