Using ueberauth and guardian to implement Auth, I get the token, but when I put the token in the header to access other routers, it still {"message": "invalid_token"}

When I visit http://localhost:4004/auth/sign_in The result is correct

	"data": {
		"id": 1,
		"token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIiLCJleHAiOjE2Njc0NjAzODcsImlhdCI6MTY2NzQ1ODU4NywiaXNzIjoiIiwianRpIjoiYjQ1Yzc2NWUtNTJkYS00MTIxLWEyNGUtN2VjNGYwODFhZDZmIiwibmJmIjoxNjY3NDU4NTg2LCJzdWIiOiIxIiwidHlwIjoiYWNjZXNzIn0.jPlcZjVo784A6_nPyZ8fJatO343TDxsvv-YFp9_Gs5dTSH3DjOqg12lQ24ciRi-JElG36__8I9ybBNazv7nnbA",
		"user_name": "gaofeng"

And then I took the token to visit http://localhost:4004/user , the token is set in the header, and the result is incorrect
Header is

Result is


"message": "invalid_token"


This is the new content in my code
In config.exs.

config :ueberauth, Ueberauth,
  base_path: "/auth/sign_in",
  providers: [
    identity: {Ueberauth.Strategy.Identity, [
      callback_methods: ["POST", "GET"],
      nickname_field: :username,
      param_nesting: "user",
      uid_field: :username

config :store_api, StoreApiWeb.Guardian,
        issure: "XXX",
        secret_key: "secret_key"
config :store_api, StoreApiWeb.Plug.AuthAccessPipeline,
  module: StoreApi.Auth,
  error_handler: StoreApiWeb.Plug.AuthErrorHandler

In auth module(auth.ex)

defmodule StoreApi.Auth do
  use Guardian, otp_app: :store_api

  def subject_for_token(%{id: id}, _claims) do
    {:ok, to_string(id)}

  def subject_for_token(_, _) do
    IO.inspect "subject_for_token"
    {:error, :reason_for_error}

  def resource_from_claims(%{"sub" => id}) do
    # Here we'll look up our resource from the claims, the subject can be
    # found in the `"sub"` key. In above `subject_for_token/2` we returned
    # the resource id so here we'll rely on that to look it up.
    resource = StoreApi.Accounts.get_user!(id)
    IO.inspect "resource_from_claims"
    IO.inspect resource
    {:ok,  resource}

  def resource_from_claims(_claims) do
    IO.inspect "resource_from_claims=====_claims"
    {:error, :no_claims_sub}

Auth Controller(authentication_controller.ex)

defmodule StoreApiWeb.AuthenticationController do
  use StoreApiWeb, :controller

  alias StoreApi.Accounts
  alias StoreApi.Accounts.User

  plug Ueberauth

  def identity_callback(conn, %{"user" => user_params}) do
    user_name = user_params["user_name"]
    password = user_params["password"]
    handle_user_conn(Accounts.check_user(user_name, password), conn)

  defp handle_user_conn(user, conn) do
    # IO.inspect(user)
    case user do
      {:ok, user} ->
        {:ok, jwt, _full_claims} =
          StoreApi.Auth.encode_and_sign(user, %{}, secret: "custom", ttl: {30, :minute})
        |> put_resp_header("authorization", "Bearer " <> jwt)
        |> json(%{data: %{token: jwt, user_name: user.user_name, id:}})

      # Handle our own error to keep it generic
      {:error, msg} ->
        |> put_status(401)
        |> json(%{data: %{ status: false, msg: msg}})

In pulg

defmodule StoreApiWeb.Plug.AuthAccessPipeline do
  use Guardian.Plug.Pipeline, otp_app: :store_api

  plug Guardian.Plug.VerifySession, claims: %{"typ" => "access"}
  plug Guardian.Plug.VerifyHeader, realm: "Bearer", claims: %{"typ" => "access"}
  plug Guardian.Plug.EnsureAuthenticated
  plug Guardian.Plug.LoadResource, ensure: true


defmodule StoreApiWeb.Plug.AuthErrorHandler do
  import Plug.Conn
  import Phoenix.Controller, only: [json: 2]

  def auth_error(conn, {type, _reason}, _opts) do
    |> put_status(401)
    |> json(%{message: to_string(type)})
    |> halt()

In my routers

defmodule StoreApiWeb.Router do
  use StoreApiWeb, :router

  pipeline :api do
    plug :accepts, ["json"]

  scope "/api", StoreApiWeb do
    pipe_through :api
    resources "/user", UserController, except: [:new, :edit]

  pipeline :browser do
    plug(:accepts, ["json"])

  pipeline :authenticated do
    plug StoreApiWeb.Plug.AuthAccessPipeline

  # 用户登录
  scope "/auth", StoreApiWeb do
    pipe_through :browser

    post "/sign_in", AuthenticationController, :identity_callback

  @doc """
  scope "/user", StoreApiWeb do
    pipe_through :browser
    pipe_through :authenticated

    # 获取所有用户信息
    resources "/", UserController, except: [:new, :edit]
    post "/detail", UserController, :show
    #post "/delete", UserController, :delete

  @doc """
  scope "/appinfo", StoreApiWeb do
    pipe_through :browser

    # 获取应用信息信息
    resources "/", AppinfoController, except: [:new, :edit]
    # 新增应用
    #post "/user_create", UserController, :user_create

  # Enables LiveDashboard only for development
  # If you want to use the LiveDashboard in production, you should put
  # it behind authentication and allow only admins to access it.
  # If your application does not have an admins-only section yet,
  # you can use Plug.BasicAuth to set up some basic authentication
  # as long as you are also using SSL (which you should anyway).
  if Mix.env() in [:dev, :test] do
    import Phoenix.LiveDashboard.Router

    scope "/" do
      pipe_through [:fetch_session, :protect_from_forgery]

      live_dashboard "/dashboard", metrics: StoreApiWeb.Telemetry

  # Enables the Swoosh mailbox preview in development.
  # Note that preview only shows emails that were sent by the same
  # node running the Phoenix server.
  if Mix.env() == :dev do
    scope "/dev" do
      pipe_through [:fetch_session, :protect_from_forgery]

      forward "/mailbox", Plug.Swoosh.MailboxPreview

Thanks indeed!!!

I haven’t used Guardian, but the token should probably be sent as a “bearer token” in the Authorization header. So I suspect you have to set the Authorization header value to “Bearer eyJhbGciOiJIUzUxMiIsInR…”

1 Like

Thank you, I’ll try

when I set the Authorization header value to “Bearer eyJhbGciOiJIUzUxMiIsInR…”
returned the


"message": "invalid_token"


Thank you sincerely!

It is quite confusing when you update the original post to show progress in resolving your issue: people who previously looked at this thread may skip over it thinking they’ve already seen it, and for people new to the thread the earlier replies don’t match the original question anymore.

Anyway, it looks like now Guardian can find the token in the header. Hopefully someone with experience with Guardian can review your setup and identify any further issues that would explain why it does not accept your token. Does the plug not write a more detailed failure reason to the application’s logs?

Thank you for your suggestion. I have revised the title to make them look as consistent as possible,
Thank you also for helping me,Guardian can find the token in the header.

I haven’t used either of these so I may not be the best person to troubleshoot this but the message says the token itself is invalid and doesn’t suggest that it’s missing.

You could try putting the token into something like or any number of other jwt decoders I found in a google search.

If I’m reading the line plug Guardian.Plug.VerifyHeader, realm: "Bearer", claims: %{"typ" => "access"} then the claim part should match that map. You can also try to inspect the module Guardian.Plug.VerifyHeader for what returns the “invalid_token” error message and maybe gain insight onto why that triggers here. My guess is it’s looking for something to be included in the token that perhaps isn’t there.

guardian/verify_header.ex at master · ueberauth/guardian · GitHub I believe shows that it should be trying to match the :claims option you’re passing in. If that claim isn’t included my guess is on line 92 Guardian.decode_and_verify(module, token, claims_to_check, opts) will trigger the error.

thanks very much !
I will try it!

Thanks everyone!
I found a solution.
My config.exs is incorrect

config :store_api, StoreApi.Guardian,
        issure: "store_api",
        secret_key: "xMIfc......"


config :store_api, StoreApi.Auth,
        issure: "store_api",
        secret_key: "xMIfc......"

auth.exs is my guardian module. But I made a mistake

Thank you all so much!!!!