]> Entropealabs - wampex_router.git/commitdiff
initial multi-auth support
authorChristopher Coté <ccote@cohesionib.com>
Thu, 19 Nov 2020 03:24:29 +0000 (21:24 -0600)
committerChristopher Coté <ccote@cohesionib.com>
Thu, 19 Nov 2020 03:24:29 +0000 (21:24 -0600)
lib/router.ex
lib/router/session.ex

index d099f0bde49b953f165fdb571117f68acaf298b6..0be57e6a939967902c529b2505f68fe6658ddeec 100644 (file)
@@ -10,8 +10,8 @@ defmodule Wampex.Router do
           topologies: [],
           replicas: integer(),
           quorum: integer(),
-          authentication_module: module(),
-          authorization_module: module()
+          authentication_module: module() | map(),
+          authorization_module: module() | map()
         ) ::
           {:ok, pid()}
           | {:error, {:already_started, pid()} | {:shutdown, term()} | term()}
index 7bf57bdced3928e908c3411e897f3315a5ae1a71..5ee1e13fa61e01709915730c51f321a4901abe4f 100644 (file)
@@ -72,8 +72,8 @@ defmodule Wampex.Router.Session do
           realm: String.t() | nil,
           name: module() | nil,
           challenge: Challenge.t() | nil,
-          authentication_module: module(),
-          authorization_module: module(),
+          authentication_module: module() | map(),
+          authorization_module: module() | map(),
           roles: [module()],
           registrations: [],
           subscriptions: [],
@@ -187,7 +187,7 @@ defmodule Wampex.Router.Session do
             } = data
         } = sl
       ) do
-    {actions, challenge} = maybe_challenge(auth, realm, options, session_id, tt, t)
+    {actions, challenge, module} = maybe_challenge(auth, realm, options, session_id, tt, t)
 
     {:ok,
      %SL{
@@ -196,7 +196,8 @@ defmodule Wampex.Router.Session do
            data
            | challenge: challenge,
              hello_received: true,
-             realm: realm
+             realm: realm,
+             authentication_module: module
          }
      }, [{:next_event, :internal, :transition}] ++ actions}
   end
@@ -237,6 +238,7 @@ defmodule Wampex.Router.Session do
               transport: tt,
               transport_pid: t,
               subscriptions: subs,
+              challenge: %Challenge{auth_method: method},
               realm: realm,
               authorization_module: am,
               peer: peer,
@@ -246,7 +248,7 @@ defmodule Wampex.Router.Session do
         } = sl
       ) do
     {data, actions} =
-      case is_authorized?(am, peer, :subscribe, topic) do
+      case is_authorized?(am, peer, :subscribe, topic, method) do
         true ->
           id = RealmSession.get_id()
           wc = RealmSession.subscribe(db, realm, topic, {id, {self(), Node.self()}}, opts)
@@ -297,6 +299,7 @@ defmodule Wampex.Router.Session do
             transport: tt,
             transport_pid: t,
             db: db,
+            challenge: %Challenge{auth_method: method},
             authorization_module: am,
             peer: peer,
             id: session_id,
@@ -305,7 +308,7 @@ defmodule Wampex.Router.Session do
         } = sl
       ) do
     {data, actions} =
-      case is_authorized?(am, peer, :publish, topic) do
+      case is_authorized?(am, peer, :publish, topic, method) do
         true ->
           pub_id = RealmSession.get_id()
 
@@ -377,6 +380,7 @@ defmodule Wampex.Router.Session do
               registrations: regs,
               db: db,
               realm: realm,
+              challenge: %Challenge{auth_method: method},
               authorization_module: am,
               peer: peer,
               register: %Register{request_id: rid, procedure: procedure}
@@ -384,7 +388,7 @@ defmodule Wampex.Router.Session do
         } = sl
       ) do
     {data, actions} =
-      case is_authorized?(am, peer, :register, procedure) do
+      case is_authorized?(am, peer, :register, procedure, method) do
         true ->
           id = RealmSession.get_id()
           RealmSession.register(db, realm, procedure, {id, {self(), Node.self()}})
@@ -416,6 +420,7 @@ defmodule Wampex.Router.Session do
               transport_pid: t,
               realm: realm,
               request_id: ri,
+              challenge: %Challenge{auth_method: method},
               authorization_module: am,
               id: session_id,
               peer: peer,
@@ -424,7 +429,7 @@ defmodule Wampex.Router.Session do
         } = sl
       ) do
     {data, actions} =
-      case is_authorized?(am, peer, :call, proc) do
+      case is_authorized?(am, peer, :call, proc, method) do
         true ->
           with {callees, index} <- RealmSession.callees(db, realm, proc),
                {id, {pid, node}} <- get_live_callee(proxy, callees, index, 3) do
@@ -720,6 +725,8 @@ defmodule Wampex.Router.Session do
   defp maybe_challenge(auth, realm, details, session_id, tt, t) do
     case details do
       %{"authid" => ai, "authmethods" => am} ->
+        auth = get_auth_module(auth, am)
+
         case auth.authenticate?(am) do
           true ->
             ch = auth.challenge(realm, ai, session_id)
@@ -735,10 +742,10 @@ defmodule Wampex.Router.Session do
               t
             )
 
-            {[], ch}
+            {[], ch, auth}
 
           false ->
-            Logger.error("Not a supported authentication method: #{am}")
+            Logger.error("Not a supported authentication method: #{inspect(am)}")
             {[{:next_event, :internal, :abort}], nil}
         end
 
@@ -748,6 +755,15 @@ defmodule Wampex.Router.Session do
     end
   end
 
+  defp get_auth_module(auth, methods) when is_map(auth) do
+    case Enum.find(auth, fn {k, _v} -> k in methods end) do
+      {_, mod} -> mod
+      nil -> Logger.error("Unsupported authentication methods #{inspect(methods)}: Supported #{inspect(auth)}")
+    end
+  end
+
+  defp get_auth_module(auth, _methods), do: auth
+
   defp get_live_callee(_proxy, [], _index, 0) do
     Logger.error("No live callees, tried all replicas")
     {:error, :no_live_callees}
@@ -794,7 +810,8 @@ defmodule Wampex.Router.Session do
 
   defp maybe_update_response(data, resp), do: {data, resp}
 
-  def is_authorized?(am, peer, type, uri) do
+  def is_authorized?(am, peer, type, uri, method) do
+    am = get_auth_module(am, [method])
     am.authorized?(type, uri, peer)
   end