Closed kitplummer closed 5 years ago
The preload happens when you run the conn through the ExOauth2Provider.Plug.VerifyHeader
plug, with ExOauth2Provider.authenticate_token/2
:
defp load_resource_owner({:ok, access_token}, config) do
repo = Config.repo(config)
access_token = repo.preload(access_token, :resource_owner)
{:ok, access_token}
end
ExOauth2Provider.Plug.current_resource_owner/1
pulls this from the preloaded assoc:
def current_resource_owner(conn, the_key \\ :default) do
conn
|> current_access_token(the_key)
|> case do
nil -> nil
access_token -> access_token.resource_owner
end
end
If resource_owner_id
isn't set, it may be because it's an application wide token. Are you using the client credentials flow? In that case, there'll be no resource owner, and you should instead pull the application id to get that as a resource.
Ah yes. Just using the Client Credentials flow...so that makes sense. Thanks again, much appreciated!
So...I've been unable to cleanly get to the user - through the chain of resources: token[application.id]-> get_application_uid() -> application[owner_id] -> get_user() -> get_the_thing_i_actually_am_controlling() - because of the empty OauthAccessToken:
%Plug.Conn{
adapter: {Plug.Cowboy.Conn, :...},
assigns: %{current_user: nil},
before_send: [#Function<0.35161479/1 in Plug.Session.before_send/2>,
#Function<0.66442134/1 in Plug.Telemetry.call/2>,
#Function<0.50969320/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>],
body_params: %{},
cookies: %{},
halted: false,
host: "localhost",
method: "GET",
owner: #PID<0.749.0>,
params: %{},
path_info: ["api", "v1", "queries"],
path_params: %{},
port: 4000,
private: %{
LeiApiWeb.Router => {[], %{}},
:ex_oauth2_provider_default_access_token => {:ok,
%LeiApi.OauthAccessTokens.OauthAccessToken{
__meta__: #Ecto.Schema.Metadata<:loaded, "oauth_access_tokens">,
application: #Ecto.Association.NotLoaded<association :application is not loaded>,
application_id: 1,
expires_in: 7200,
id: 7,
inserted_at: ~N[2019-08-09 16:21:24],
previous_refresh_token: "",
refresh_token: nil,
resource_owner: nil,
resource_owner_id: nil,
revoked_at: nil,
scopes: "",
token: "d510a15b5e450d52df74778a0c0eff08bf83c90878f8c8516e2c6e54100bbf19",
updated_at: ~N[2019-08-09 16:21:24]
}},
:phoenix_action => :index,
:phoenix_controller => LeiApiWeb.API.V1.QueryApiController,
:phoenix_endpoint => LeiApiWeb.Endpoint,
:phoenix_format => "json",
:phoenix_layout => {LeiApiWeb.LayoutView, :app},
:phoenix_router => LeiApiWeb.Router,
:phoenix_view => LeiApiWeb.API.V1.QueryApiView,
:plug_session => %{},
:plug_session_fetch => :done,
:pow_config => [
mod: Pow.Plug.Session,
plug: Pow.Plug.Session,
otp_app: :lei_api
]
},
Maybe I just grabbing at straws (easier implementation on my side) but even if it is an "application-wide" token - wouldn't it still belong to a resource_owner
and then make sense to be able to get the User from the conn
? If I'm just being daft I'll keep trudging.
No, typically an application wide token would give access to all resource owners under that application. There is no single user that has authorized anything when using client credentials, it's the whole application that has been given access to. It should only be used when you control both client and server.
If you need to retrieve a user, then it would be the owner of the application, so you should preload the application, and then the owner.
Ok, thanks.
the same as if I use Authorization Code grant. The token gets issued as I'd expected, but if I:
user is
nil
. I do see the OauthAccessToken struct, andresource_owner
andresource_owner_id
are nil too.Am I wrong in expecting that a token granted by either means should work in a controller the same? Really hoping I don't need the Authorize step - just need an API token.
Sorry for squeekin on this stuff. Really appreciate the help, and the effort you've put into the project(s).