Pass on execution to main Router module after successful validation of remote client in the authentication module

Hello Team,

I am working on an HMAC authorization script.
If the remote client passes the validation, I want to make it possible for him to access my endpoints (routes).
How do i do that?
Please find my code below:

def call(conn, opts) do
IO.inspect conn.request_path

    authenticate(conn, opts)
end


def authenticate(conn, opts) do
    IO.inspect conn.req_headers
    IO.inspect remote_ip=conn.remote_ip
    
    with {:ok, auth_str} <- parse_header(conn.req_headers)
    do
        # pass on execution to the router where the endpoints are located
    else
        {:error, reason} ->
            conn
            |> send_resp(401, Poison.encode!(reason))
            |> halt
    end
end

You can just return conn and plug the router anywhere later in the plug pipeline. Using halt() already makes sure no further plugs will be called.

2 Likes

Many thanks for the quick response.

I tried it and It works.

Did you mean to mark LostKobrakai’s post as the solution? As-is your post is showing up in the solution area and it doesn’t contain the solution. ^.^

Below is the solution:

with {:ok, auth_str} <- parse_header(conn.req_headers),
{:ok, id} <- parse_id(parsed[“id”])
do
validate_signature(auth_str, id)

        conn
        send_resp(conn, 200, "")
    else
        {:error, reason} ->
            conn
            |> send_resp(401, Poison.encode!(reason))
            |> halt
    end

With this, if validation fails, status code 401 is returned to the remote client application.
If validation passes, execution is passed on to the router module where the API endpoints have been set up as routes.

Another issue has cropped up.
I’ve been trying to fix it since yesterday but there hasn’t been a solution yet.

I was trying to build upon the earlier solution but things have turned out bad.
Can someone point me to what I may be doing wrong?
I want processing to be passed on to the router when validation is successful.
But is not what is happening currently.

      case validate_tokens(auth, user_id, ip, body) do
            {:ok, msg} ->
                conn
                send_resp(conn, 200, Poison.encode(msg))
            {:error, msg} ->
                conn
                |> send_resp(200, Poison.encode!(msg))
                |> halt
            _ ->
                IO.puts "\nThere was a problem\n"
                conn
                |> send_resp(200, err_request_failure)
                |> halt
        end

What’s that send_resp in the success case about? Why would you send a response if your request has still to go through routing and all the stuff after that?

Also you’re returning 200 status codes if there are errors, which does work, but is semantically incorrect.

1 Like

When I take off the send_resp, I get the error below:

16:37:38.575 [error] #PID<0.578.0> running App.Router (connection #PID<0.577.0>, stream id 1) terminated
Server: localhost:5000 (http)
Request: POST /exec_main
** (exit) an exception was raised:
** (MatchError) no match of right hand side value: {:error, :invalid, 0}

I have taken note of your comment concerning the status code. Will get it updated.
Thanks.

Can anyone help me out on what to do?

Can you perhaps provide a minified project which reproduces your problem on github or similar?

1 Like

Okay. Will do that

1 Like