Closed kitplummer closed 5 years ago
I think I've found my solution...stealing from this repo's controller tests. Just need to setup the fixtures for application, access_token, and access_grant.
Great! Just to write it out for others who may find this issue, you can use the ExOauth2Provider.Plug.set_current_access_token/1
to set the access token for the conn.
Could look like this:
ExOauth2Provider.Plug.set_current_access_token(conn, {:ok, access_token})`
Alternatively, you can set the auth header, and let your pipeline deal with auth:
Plug.Conn.put_req_header(conn, "authorization", "Bearer #{access_token.token}")
Well...I was a little too optimistic. Think I missing something in the setup of the user. Any ideas?
Test case:
defmodule LeiApiWeb.API.V1.UserControllerTest do
use LeiApiWeb.ConnCase
setup %{conn: conn} do
user = user_fixture()
conn = assign(conn, :current_user, user)
application = application(%{user: user, redirect_uri: "urn:ietf:wg:oauth:2.0:oob"})
access_token = access_grant(%{application: application, user: user})
#ExOauth2Provider.Plug.set_current_access_token(conn, access_token)
conn = Plug.Conn.put_req_header(conn, "authorization", access_token.token)
conn = Plug.Conn.put_req_header(conn, "accept", "application/json")
{:ok, conn: conn}
end
describe "index" do
test "lists all users", %{conn: conn} do
conn = get(conn, Routes.user_path(conn, :index))
IO.inspect conn
assert json_response(conn, 200)["data"] == []
end
end
end
Output:
..................%Plug.Conn{
adapter: {Plug.Adapters.Test.Conn, :...},
assigns: %{
current_user: %LeiApi.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
confirm_password: "abcdefghijk",
current_password: nil,
email: "bob963@example.com",
id: 270,
inserted_at: ~N[2019-08-06 21:02:53],
password: "abcdefghijk",
password_hash: "$pbkdf2-sha512$100000$J1172bf8L9VGCkjqBkF6HQ==$e5noOYKW74KtXYJyUs0kn4DHP/UD106YoIejNOO9LNIA2qXrbTuNNUIW95vkUzKEnOXfra1+v53w04Kx2xZL2A==",
queries: #Ecto.Association.NotLoaded<association :queries is not loaded>,
updated_at: ~N[2019-08-06 21:02:53]
},
ex_oauth2_provider_failure: :no_session
},
before_send: [#Function<0.66442134/1 in Plug.Telemetry.call/2>],
body_params: %{},
cookies: %Plug.Conn.Unfetched{aspect: :cookies},
halted: true,
host: "www.example.com",
method: "GET",
owner: #PID<0.418.0>,
params: %{},
path_info: ["api", "v1", "accounts"],
path_params: %{},
port: 80,
private: %{
LeiApiWeb.Router => {[], %{}},
:phoenix_endpoint => LeiApiWeb.Endpoint,
:phoenix_format => "json",
:phoenix_recycled => false,
:phoenix_router => LeiApiWeb.Router,
:plug_session_fetch => #Function<1.35161479/1 in Plug.Session.fetch_session/1>,
:plug_skip_csrf_protection => true,
:pow_config => [
mod: Pow.Plug.Session,
plug: Pow.Plug.Session,
otp_app: :lei_api
]
},
query_params: %{},
query_string: "",
remote_ip: {127, 0, 0, 1},
req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
req_headers: [
{"authorization",
"6c53cce675fe8ed47b16f6794245dbda5cd4e0044b63c4fb17b1471360acff10"},
{"accept", "application/json"}
],
request_path: "/api/v1/accounts",
resp_body: "{\"errors\":[\"Unauthenticated\"]}",
resp_cookies: %{},
resp_headers: [
{"cache-control", "max-age=0, private, must-revalidate"},
{"x-request-id", "FbhxPBqBduA2438AAAGB"},
{"content-type", "application/json; charset=utf-8"}
],
scheme: :http,
script_name: [],
secret_key_base: :...,
state: :sent,
status: 401
}
1) test index lists all users (LeiApiWeb.API.V1.UserControllerTest)
test/lei_api_web/controllers/api/v1/user_controller_test.exs:17
** (RuntimeError) expected response with status 200, got: 401, with body:
{"errors":["Unauthenticated"]}
code: assert json_response(conn, 200)["data"] == []
stacktrace:
(phoenix) lib/phoenix/test/conn_test.ex:373: Phoenix.ConnTest.response/2
(phoenix) lib/phoenix/test/conn_test.ex:419: Phoenix.ConnTest.json_response/2
test/lei_api_web/controllers/api/v1/user_controller_test.exs:20: (test)
.
Finished in 2.9 seconds
20 tests, 1 failure
Oh, use this instead:
Plug.Conn.put_req_header(conn, "authorization", "Bearer #{access_token.token}")
I forgot that you used the bearer realm for the plug (which is what's used for the examples as well). I'll updated the above example as well.
Thanks. I did try that...and the header is received with the "Bearer" prefix. But still getting the 401
in the test.
But now I get ex_oauth2_provider_failure: :token_not_found
:
..................%Plug.Conn{
adapter: {Plug.Adapters.Test.Conn, :...},
assigns: %{
current_user: %LeiApi.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
confirm_password: "abcdefghijk",
current_password: nil,
email: "bob867@example.com",
id: 288,
inserted_at: ~N[2019-08-07 13:15:56],
password: "abcdefghijk",
password_hash: "$pbkdf2-sha512$100000$UALQQwh7fCftb6X7/H49lg==$DBfCFV6vG4Y2ymu/TQvDR9W5APoyp9+5KNDUWGQ585wDryCMC5HABlm6IFuzGMfAMvuUhRCw1sjHfQcxgljXjw==",
queries: #Ecto.Association.NotLoaded<association :queries is not loaded>,
updated_at: ~N[2019-08-07 13:15:56]
},
ex_oauth2_provider_failure: :token_not_found
},
What does access_grant
do? You'll need to set up an access token, sounds like you just set up the grant.
Doh, in my troubleshooting of things I forgot to change it back to access_token
from access_grant
after adding the "Bearer" prefix. Doing so, has the auth pipeline working in my controller test. Awesome...thanks!
Ok, next question. :) Trying to get my API controller tests to pass. Obviously my user fixture is "Unauthenticated". But, I'm not quite sure how to make that so. Again sorry to bug, but am hopeful a lil help will get me moving again. Is there something I can 'set' in the fixture? Inspecting the
conn
value isn't overly helpful as I don't see something that would indicated "authenticated". Realize also that these are kinda just question, and not sure if there is a better forum for asking.