Forbidden magic link

Can't get magic link to work all of a sudden. I receive the magic link in dev/mailbox but when I click it I'm taken to a page that has a "sign in" button, and once I click that, I get:
[warning] Authentication failed:
Bread Crumbs:
> Error returned from: MyApp.Accounts.User.sign_in_with_magic_link

Forbidden Error

* Invalid magic_link token
[warning] Authentication failed:
Bread Crumbs:
> Error returned from: MyApp.Accounts.User.sign_in_with_magic_link

Forbidden Error

* Invalid magic_link token
Details: %AshAuthentication.Errors.AuthenticationFailed{
caused_by: %Ash.Error.Forbidden{
bread_crumbs: ["Error returned from: MyApp.Accounts.User.sign_in_with_magic_link"],
changeset: "#Changeset<>",
errors: [
%AshAuthentication.Errors.InvalidToken{
type: :magic_link,
field: :token,
splode: Ash.Error,
bread_crumbs: ["Error returned from: MyApp.Accounts.User.sign_in_with_magic_link"],
vars: [],
path: [],
stacktrace: #Splode.Stacktrace<>,
class: :forbidden
}
]
},
changeset: nil,
field: nil,
query: nil,
strategy: %AshAuthentication.Strategy.MagicLink{
identity_field: :email,
lookup_action_name: :get_by_email,
name: :magic_link,
prevent_hijacking?: true,
registration_enabled?: true,
request_action_name: :request_magic_link,
require_interaction?: true,
resource: MyApp.Accounts.User,
sender: {MyApp.Accounts.User.Senders.SendMagicLinkEmail, []},
sign_in_action_name: :sign_in_with_magic_link,
single_use_token?: true,
token_lifetime: {10, :minutes},
token_param_name: :token
},
splode: nil,
bread_crumbs: [],
vars: [],
path: [],
stacktrace: #Splode.Stacktrace<>,
class: :forbidden
}
Details: %AshAuthentication.Errors.AuthenticationFailed{
caused_by: %Ash.Error.Forbidden{
bread_crumbs: ["Error returned from: MyApp.Accounts.User.sign_in_with_magic_link"],
changeset: "#Changeset<>",
errors: [
%AshAuthentication.Errors.InvalidToken{
type: :magic_link,
field: :token,
splode: Ash.Error,
bread_crumbs: ["Error returned from: MyApp.Accounts.User.sign_in_with_magic_link"],
vars: [],
path: [],
stacktrace: #Splode.Stacktrace<>,
class: :forbidden
}
]
},
changeset: nil,
field: nil,
query: nil,
strategy: %AshAuthentication.Strategy.MagicLink{
identity_field: :email,
lookup_action_name: :get_by_email,
name: :magic_link,
prevent_hijacking?: true,
registration_enabled?: true,
request_action_name: :request_magic_link,
require_interaction?: true,
resource: MyApp.Accounts.User,
sender: {MyApp.Accounts.User.Senders.SendMagicLinkEmail, []},
sign_in_action_name: :sign_in_with_magic_link,
single_use_token?: true,
token_lifetime: {10, :minutes},
token_param_name: :token
},
splode: nil,
bread_crumbs: [],
vars: [],
path: [],
stacktrace: #Splode.Stacktrace<>,
class: :forbidden
}
57 Replies
sevenseacat
sevenseacat•3mo ago
is the token expired?
Yahya Oxley
Yahya OxleyOP•3mo ago
I don't beleieve so. It is set to expire after 10 mins and I am clicking it immediately.
ZachDaniel
ZachDaniel•3mo ago
What does your link format look like? Perhaps using the wrong parameter name etc? Newer versions of Ash authentication have you doing it with a path param not a query param etc.
Yahya Oxley
Yahya OxleyOP•3mo ago
My link looks like this:
No description
Yahya Oxley
Yahya OxleyOP•3mo ago
A bit of extra disclosure. I added a set_tenant plug that looks like:
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {MyAppWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
plug :set_tenant
end
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {MyAppWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
plug :set_tenant
end
# Temporarily hard code tenant
defp set_tenant(conn, _opts),
do: Ash.PlugHelpers.set_tenant(conn, "5f26b63c-62be-4660-bf6c-1a7185fdfdd9")
# Temporarily hard code tenant
defp set_tenant(conn, _opts),
do: Ash.PlugHelpers.set_tenant(conn, "5f26b63c-62be-4660-bf6c-1a7185fdfdd9")
Not sure if this could be causing an issue
ZachDaniel
ZachDaniel•3mo ago
Is your token resource multitenant?
Yahya Oxley
Yahya OxleyOP•3mo ago
To be honest, I am not sure how to check that. I just finished reading the Ash Framework book a few days ago. My Token module is too big to paste here but running a search on it for the word multi returns no results:
No description
ZachDaniel
ZachDaniel•3mo ago
Hmm...so it shouldn't be then. In your first message you said "all of a sudden" does this mean this was working and then stopped?
Yahya Oxley
Yahya OxleyOP•3mo ago
Yes it worked a couple days ago.. I was happy and went to sleep. This is the story: at first I could not get it to work after I added multi tenancy following this tutorial: https://alembic.com.au/blog/multitenancy-in-ash-framework but I got help in the Ash slack and added the plug I mentioned. It worked at that moment. Then today I used: mix ash_phoenix.gen.live --domain MyApp.Facilities --resource MyApp.Facilities.RegionalOffice And you know how it asks you something about usiong :current_user? I said yes. After that I could no longer log in via magic links. Though this observation of mine may be completely unrelated. I am just trying to provide more context.
Alembic
šŸ” Mastering Multitenancy in Ash Framework
Learn how to keep customer data securely separated in your Elixir apps - without the headache. All you need to know from basic setup to advanced ID management.
ZachDaniel
ZachDaniel•3mo ago
šŸ¤” hmm...that shouldn't modify the magic link process We can potentially improve that error message to provide more context but other than that it might be worth rolling back your changes/checking out an older commit to see exactly which changes caused the issue
Yahya Oxley
Yahya OxleyOP•3mo ago
Thank you, I will try that No dice.. I am not sure what the problem is 😦 is there a place where I can put some logging in order to find out what the issue is?
ZachDaniel
ZachDaniel•3mo ago
I'll look and see if we're swallowing a more descriptive error somewhere but you can also add some logic to the sign_in_with_magic_link action which I believe should be a create action in the standard setup
Yahya Oxley
Yahya OxleyOP•3mo ago
Kk thank you so much
ZachDaniel
ZachDaniel•3mo ago
so you can do something like:
change debug_log("a label for the logs")
change debug_log("a label for the logs")
in the log which should print out a bunch of details about the action And/or you can do your own thing there:
change fn changeset, _ ->
IO.inspect(changeset.attributes)
IO.inspect(changeset.arguments)
changeset
end
change fn changeset, _ ->
IO.inspect(changeset.attributes)
IO.inspect(changeset.arguments)
changeset
end
for example
Yahya Oxley
Yahya OxleyOP•3mo ago
This seems like a hint?
[info] POST /auth/user/magic_link
[debug] Processing with AshAuthentication.Phoenix.StrategyRouter
Parameters: %{"_csrf_token" => "REMOVED FOR BREVITY"}
Pipelines: [:browser]
[debug] QUERY OK source="tokens" db=0.7ms idle=337.3ms
SELECT TRUE FROM "tokens" AS t0 WHERE (t0."purpose"::text = $1::text) AND (t0."jti"::text = $2::text) LIMIT 1 ["revocation", "31b2sdiqmhfqnipikk0002c6"]
↳ anonymous fn/5 in AshSql.AggregateQuery.add_single_aggs/5, at: lib/aggregate_query.ex:119
[debug] Claim %{"tenant" => "5f26b63c-62be-4660-bf6c-1a7185fdfdd9"} did not pass validation.

Current time: 1753639968
[info] POST /auth/user/magic_link
[debug] Processing with AshAuthentication.Phoenix.StrategyRouter
Parameters: %{"_csrf_token" => "REMOVED FOR BREVITY"}
Pipelines: [:browser]
[debug] QUERY OK source="tokens" db=0.7ms idle=337.3ms
SELECT TRUE FROM "tokens" AS t0 WHERE (t0."purpose"::text = $1::text) AND (t0."jti"::text = $2::text) LIMIT 1 ["revocation", "31b2sdiqmhfqnipikk0002c6"]
↳ anonymous fn/5 in AshSql.AggregateQuery.add_single_aggs/5, at: lib/aggregate_query.ex:119
[debug] Claim %{"tenant" => "5f26b63c-62be-4660-bf6c-1a7185fdfdd9"} did not pass validation.

Current time: 1753639968
[debug] TEST LABEL - input - MyApp.Accounts.User.sign_in_with_magic_link: %{"_csrf_token" => "CQo1cAhnDnwlBydRb0EUWC4VbTVFGQYVKNb5q7i5rRWb80r9HmTF6NJw", "token" => "REMOVED FOR BREVITY"}
[debug] TEST LABEL - casted attributes - MyApp.Accounts.User.sign_in_with_magic_link: %{}
[debug] TEST LABEL - casted arguments - MyApp.Accounts.User.sign_in_with_magic_link: %{token: "REMOVED FOR BREVITY"}
[debug] TEST LABEL - final changeset - MyApp.Accounts.User.sign_in_with_magic_link: #Ash.Changeset<domain: MyApp.Accounts, action_type: :create, action: :sign_in_with_magic_link, tenant: "5f26b63c-62be-4660-bf6c-1a7185fdfdd9", attributes: %{id: "77fc1e7a-23fb-439a-b98b-1a25d33adf8e"}, relationships: %{}, arguments: %{token: "REMOVED FOR BREVITY"}, errors: [%AshAuthentication.Errors.InvalidToken{type: :magic_link, field: :token, splode: nil, bread_crumbs: [], vars: [], path: [], stacktrace: #Splode.Stacktrace<>, class: :forbidden}], data: %MyApp.Accounts.User{id: nil, email: nil, organization_id: nil, organization: #Ash.NotLoaded<:relationship, field: :organization>, __meta__: #Ecto.Schema.Metadata<:built, "users">}, valid?: false>
[debug] TEST LABEL - action result - MyApp.Accounts.User.sign_in_with_magic_link: {:error, %Ash.Error.Forbidden{changeset: "#Changeset<>", errors: [%AshAuthentication.Errors.InvalidToken{type: :magic_link, field: :token, splode: Ash.Error, bread_crumbs: [], vars: [], path: [], stacktrace: #Splode.Stacktrace<>, class: :forbidden}]}}
[debug] TEST LABEL - input - MyApp.Accounts.User.sign_in_with_magic_link: %{"_csrf_token" => "CQo1cAhnDnwlBydRb0EUWC4VbTVFGQYVKNb5q7i5rRWb80r9HmTF6NJw", "token" => "REMOVED FOR BREVITY"}
[debug] TEST LABEL - casted attributes - MyApp.Accounts.User.sign_in_with_magic_link: %{}
[debug] TEST LABEL - casted arguments - MyApp.Accounts.User.sign_in_with_magic_link: %{token: "REMOVED FOR BREVITY"}
[debug] TEST LABEL - final changeset - MyApp.Accounts.User.sign_in_with_magic_link: #Ash.Changeset<domain: MyApp.Accounts, action_type: :create, action: :sign_in_with_magic_link, tenant: "5f26b63c-62be-4660-bf6c-1a7185fdfdd9", attributes: %{id: "77fc1e7a-23fb-439a-b98b-1a25d33adf8e"}, relationships: %{}, arguments: %{token: "REMOVED FOR BREVITY"}, errors: [%AshAuthentication.Errors.InvalidToken{type: :magic_link, field: :token, splode: nil, bread_crumbs: [], vars: [], path: [], stacktrace: #Splode.Stacktrace<>, class: :forbidden}], data: %MyApp.Accounts.User{id: nil, email: nil, organization_id: nil, organization: #Ash.NotLoaded<:relationship, field: :organization>, __meta__: #Ecto.Schema.Metadata<:built, "users">}, valid?: false>
[debug] TEST LABEL - action result - MyApp.Accounts.User.sign_in_with_magic_link: {:error, %Ash.Error.Forbidden{changeset: "#Changeset<>", errors: [%AshAuthentication.Errors.InvalidToken{type: :magic_link, field: :token, splode: Ash.Error, bread_crumbs: [], vars: [], path: [], stacktrace: #Splode.Stacktrace<>, class: :forbidden}]}}
My guess is that by adding the following set_tenantplug I messed something up: It felt like a hack from the beginning but cant find documentation as to how to set the user to the appropriate organization when they attempt to login:
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {Web.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
plug :set_tenant
end
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {Web.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
plug :set_tenant
end
# Temporarily hard code tenant
defp set_tenant(conn, _opts),
do: Ash.PlugHelpers.set_tenant(conn, "5f26b63c-62be-4660-bf6c-1a7185fdfdd9")
# Temporarily hard code tenant
defp set_tenant(conn, _opts),
do: Ash.PlugHelpers.set_tenant(conn, "5f26b63c-62be-4660-bf6c-1a7185fdfdd9")
ZachDaniel
ZachDaniel•3mo ago
Right, so this depends a lot on your setup When you say "set the user to the appropriate organization when they attempt to login", what do you mean? I've pushed something up to main of ash_authentication that should provide more detailed error information as part of the magic link flow
Yahya Oxley
Yahya OxleyOP•3mo ago
I mean, lets say johny@test.com is a member of organization_id 1. And mickey@hey.com is a member of organization_id 2 When johny comes to localhost:4000/sign_in he does not need to tell us his organization, he jsut types in his email and we already know, so to speak, that he belongs to organization 1
ZachDaniel
ZachDaniel•3mo ago
how do you enforce that? What if organization 1 & organization 2 have users w/ the same email?
Yahya Oxley
Yahya OxleyOP•3mo ago
Ah I didn't know that was possible
ZachDaniel
ZachDaniel•3mo ago
Well, it depends on how you've set up multitenancy Each resource is in control of its own multitenant definition So how is the multitenancy on your user resource configured?
Yahya Oxley
Yahya OxleyOP•3mo ago
multitenancy do
strategy :attribute
attribute :organization_id
end
multitenancy do
strategy :attribute
attribute :organization_id
end
I frankly don't fully understand how multitenancy works in Ash. In previous projects (Phoenix only) I would have to add an org_id column to each and every one of my "objects" but I get the sense that this is not the case with Ash
ZachDaniel
ZachDaniel•3mo ago
Its effectively the same for Ash when you use the attribute multitenancy approach The only difference is that setting the tenant does the filtering etc. The main thing is that with that setup as you have it now, you have essentially a chicken and an egg problem You can't ever fetch a user because it requires a tenant to be given but you won't know the tenant until you fetch the user In many cases, what people do is use subdomains for tenants for example so that users visit org1.myapp.com and org2.myapp.com for example then you fetch the org first thing and you can set a tenant and you're off to the races
Yahya Oxley
Yahya OxleyOP•3mo ago
that makes sense, and I am happy to use subdomains, but how would this work in dev? would I do tenant.localhost:4000?
ZachDaniel
ZachDaniel•3mo ago
Locally its a bit complex, you have to modify your /etc/hosts (are you on a mac/linux?)
Yahya Oxley
Yahya OxleyOP•3mo ago
Linux. I am on Ubuntu 24.04
ZachDaniel
ZachDaniel•3mo ago
127.0.0.1 foo.localhost
127.0.0.1 bar.localhost
127.0.0.1 foo.localhost
127.0.0.1 bar.localhost
For local testing you have to tell your machine about those subdomains put something like that in your /etc/hosts and then you can visit foo.localhost and bar.localhost then, early on in your pipeline, you fetch the corresponding organization (this is typically done by having orgs choose a unique subdomain when they are created), and then use Ash.PlugHelpers.set_tenant. Now, with all that said, you have a different chicken and egg problem when it comes to registration šŸ˜†. This often requires building custom sign in views because we don't provide this one out of the box. Because now you have a user who can't be created until an organization exists for them to be a part of. So you have to modify your register action to have inputs that can create an organization etc.
Yahya Oxley
Yahya OxleyOP•3mo ago
and that makes sense Do you think my set_tenant plug is too late here?
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {VezaWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
plug :set_tenant
end
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {VezaWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
plug :set_tenant
end
ZachDaniel
ZachDaniel•3mo ago
Your life will in general be much simpler instead of you choose to make users not multitenant at all, but I don't know if thats on the table for you. yes, likely so should be above load_from_session If you're familiar with how github models it for example, you can have one global users table, that has a many_to_many to the organizations they have access to. After a user signs in, if there is only one organization they are a part of, you can redirect to that_org.your_app.com. If there are many, you can redirect them to a page to select the organization they'd like to view, for example.
Yahya Oxley
Yahya OxleyOP•3mo ago
Interstingly, I dont actually see a sign-in route in my router.ex but somehow I am able to visit localhost:4000/sign-in
ZachDaniel
ZachDaniel•3mo ago
Yeah, that is added by the ash_authentication code Like this stuff:
magic_sign_in_route(Example.Accounts.User, :magic_link,
auth_routes_prefix: "/auth",
overrides: [DevWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default]
)

sign_in_route(
path: "/sign-in",
overrides: [DevWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default],
auth_routes_prefix: "/auth"
)

auth_routes(AuthController, Example.Accounts.User)
magic_sign_in_route(Example.Accounts.User, :magic_link,
auth_routes_prefix: "/auth",
overrides: [DevWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default]
)

sign_in_route(
path: "/sign-in",
overrides: [DevWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default],
auth_routes_prefix: "/auth"
)

auth_routes(AuthController, Example.Accounts.User)
Yahya Oxley
Yahya OxleyOP•3mo ago
ah, cool! Should I just update all my deps and see if the error is more descriptive?
ZachDaniel
ZachDaniel•3mo ago
You'll have to point to main {:ash_authentication, github: "team-alembic/ash_authentication", override: true} since its not released yet
Yahya Oxley
Yahya OxleyOP•3mo ago
kk thanks so much I will do so now
ZachDaniel
ZachDaniel•3mo ago
LMK how it goes šŸ˜„
Yahya Oxley
Yahya OxleyOP•3mo ago
Done. Not sure if the extra logging is contained here? https://pastebin.com/k7FzpPPq
Pastebin
[warning] Authentication failed: Bread Crumbs: > Error returned fr...
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Yahya Oxley
Yahya OxleyOP•3mo ago
And I modified my pipeline to look like this:
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {VezaWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :set_tenant
plug :load_from_session
end
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {VezaWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :set_tenant
plug :load_from_session
end
ZachDaniel
ZachDaniel•3mo ago
Hmm... sorry its not extra logging but that message should just have more stuff in it šŸ¤”
Yahya Oxley
Yahya OxleyOP•3mo ago
What I did is modified my mix.exs and then mix deps.update --all
ZachDaniel
ZachDaniel•3mo ago
hmmmm the stacktrace doesn't look quite right šŸ¤¦ā€ā™‚ļø sorry mix deps.update ash_authentication it helps if I push the changes...
Yahya Oxley
Yahya OxleyOP•3mo ago
# {:ash_authentication, "~> 4.0"},
{:ash_authentication, github: "team-alembic/ash_authentication", override: true},
# {:ash_authentication, "~> 4.0"},
{:ash_authentication, github: "team-alembic/ash_authentication", override: true},
Should I still use the one you provided or the original one? by the way nothing to be sorry about Ash is absolutely incredible, I can't even believe it exists
ZachDaniel
ZachDaniel•3mo ago
Yeah still use the one I provided šŸ˜„
Yahya Oxley
Yahya OxleyOP•3mo ago
Thank you. This is what I see: https://pastebin.com/VzQQwpFy
Pastebin
[debug] HANDLE EVENT "submit" in AshAuthentication.Phoenix.MagicSig...
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
ZachDaniel
ZachDaniel•3mo ago
šŸ¤” hmmmmmm Okay I think your tokens need to be tenanted just like your users can you set them up the same way?
Yahya Oxley
Yahya OxleyOP•3mo ago
add this to the Token module?
multitenancy do
strategy :attribute
attribute :organization_id
end
multitenancy do
strategy :attribute
attribute :organization_id
end
ZachDaniel
ZachDaniel•3mo ago
yep šŸ™‚ and mix ash.codegen <name>
Yahya Oxley
Yahya OxleyOP•3mo ago
kk doing it now while I do this, can I ask you if you think this is something I have caused? I would like to stick to the "official" Ash way of doing things as much as possible
ZachDaniel
ZachDaniel•3mo ago
Honestly I think there is likely just something simple that isn't set up as expected, either something misconfigured or something not documented properly on our end etc. There are plenty of people using Ash Authentication w/ multitenant setups so its definitely doable šŸ˜„
Yahya Oxley
Yahya OxleyOP•3mo ago
kk awesome! I have added these two under the Token resource:
multitenancy do
strategy :attribute
attribute :organization_id
end

relationships do
belongs_to :organization, MyApp.Core.Organization
end
multitenancy do
strategy :attribute
attribute :organization_id
end

relationships do
belongs_to :organization, MyApp.Core.Organization
end
And applied the migrations in question
[error] Error while checking if token is revoked.
We must assume that it is revoked for security purposes.

** (Ash.Error.Invalid)
Invalid Error

* Queries against the MyApp.Accounts.Token resource require a tenant to be specified
(ash 3.5.32) lib/ash/error/invalid/tenant_required.ex:4: Ash.Error.Invalid.TenantRequired.exception/1
(ash 3.5.32) lib/ash/actions/read/read.ex:2564: Ash.Actions.Read.validate_multitenancy/1
(ash 3.5.32) lib/ash/actions/read/read.ex:2428: Ash.Actions.Read.handle_multitenancy/1
(ash 3.5.32) lib/ash/actions/aggregate.ex:80: anonymous fn/5 in Ash.Actions.Aggregate.run/4
(elixir 1.18.4) lib/enum.ex:4968: Enumerable.List.reduce/3
(elixir 1.18.4) lib/enum.ex:2600: Enum.reduce_while/3
(ash 3.5.32) lib/ash.ex:1041: Ash.aggregate/3
(ash 3.5.32) lib/ash.ex:1173: Ash.exists/2
(ash 3.5.32) lib/ash/resource/actions/action/implementation.ex:21: Ash.Resource.Actions.Implementation.run/4
(ash 3.5.32) lib/ash/actions/action.ex:322: Ash.Actions.Action.run_with_hooks/5
(ash 3.5.32) lib/ash/actions/action.ex:163: Ash.Actions.Action.run_without_transaction/6
(ash 3.5.32) lib/ash/actions/action.ex:59: Ash.Actions.Action.run_with_lifecycle/3
(ash 3.5.32) lib/ash.ex:1900: Ash.run_action/2
(ash_authentication 4.9.8) lib/ash_authentication/token_resource/actions.ex:190: AshAuthentication.TokenResource.Actions.jti_revoked?/3
(ash_authentication 4.9.8) lib/ash_authentication/token_resource/actions.ex:250: AshAuthentication.TokenResource.Actions.valid_jti?/3
(joken 2.6.2) lib/joken.ex:379: anonymous fn/5 in Joken.reduce_validations/3
(elixir 1.18.4) lib/enum.ex:4968: Enumerable.List.reduce/3
(elixir 1.18.4) lib/enum.ex:2600: Enum.reduce_while/3
(joken 2.6.2) lib/joken.ex:376: Joken.reduce_validations/3
[error] Error while checking if token is revoked.
We must assume that it is revoked for security purposes.

** (Ash.Error.Invalid)
Invalid Error

* Queries against the MyApp.Accounts.Token resource require a tenant to be specified
(ash 3.5.32) lib/ash/error/invalid/tenant_required.ex:4: Ash.Error.Invalid.TenantRequired.exception/1
(ash 3.5.32) lib/ash/actions/read/read.ex:2564: Ash.Actions.Read.validate_multitenancy/1
(ash 3.5.32) lib/ash/actions/read/read.ex:2428: Ash.Actions.Read.handle_multitenancy/1
(ash 3.5.32) lib/ash/actions/aggregate.ex:80: anonymous fn/5 in Ash.Actions.Aggregate.run/4
(elixir 1.18.4) lib/enum.ex:4968: Enumerable.List.reduce/3
(elixir 1.18.4) lib/enum.ex:2600: Enum.reduce_while/3
(ash 3.5.32) lib/ash.ex:1041: Ash.aggregate/3
(ash 3.5.32) lib/ash.ex:1173: Ash.exists/2
(ash 3.5.32) lib/ash/resource/actions/action/implementation.ex:21: Ash.Resource.Actions.Implementation.run/4
(ash 3.5.32) lib/ash/actions/action.ex:322: Ash.Actions.Action.run_with_hooks/5
(ash 3.5.32) lib/ash/actions/action.ex:163: Ash.Actions.Action.run_without_transaction/6
(ash 3.5.32) lib/ash/actions/action.ex:59: Ash.Actions.Action.run_with_lifecycle/3
(ash 3.5.32) lib/ash.ex:1900: Ash.run_action/2
(ash_authentication 4.9.8) lib/ash_authentication/token_resource/actions.ex:190: AshAuthentication.TokenResource.Actions.jti_revoked?/3
(ash_authentication 4.9.8) lib/ash_authentication/token_resource/actions.ex:250: AshAuthentication.TokenResource.Actions.valid_jti?/3
(joken 2.6.2) lib/joken.ex:379: anonymous fn/5 in Joken.reduce_validations/3
(elixir 1.18.4) lib/enum.ex:4968: Enumerable.List.reduce/3
(elixir 1.18.4) lib/enum.ex:2600: Enum.reduce_while/3
(joken 2.6.2) lib/joken.ex:376: Joken.reduce_validations/3
ZachDaniel
ZachDaniel•3mo ago
Did you issue a new token or are you using one that was already sent? Also, what does your browser pipeline look like now?
Yahya Oxley
Yahya OxleyOP•3mo ago
This is my pipeline:
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {VezaWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :set_tenant
plug :load_from_session
end
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {VezaWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :set_tenant
plug :load_from_session
end
I went to localhost:4000/sign-in and generated a new token that way. Then received the email in dev/mailbox, clicked the magic link and then clicked "sign in" on the page that I was taken to
ZachDaniel
ZachDaniel•3mo ago
Hum This may in fact be a bug try updating to latest main again So maybe I'm wrong and people arne't using magic link w/ tenanted users Or perhaps folks haven't upgraded to whichever version introduced this bug its good and bad, the builtin protections prevent from making invalid queries, so its not a security issue, but of course needs fixing
Yahya Oxley
Yahya OxleyOP•3mo ago
it worked!
ZachDaniel
ZachDaniel•3mo ago
🄳 You may also not need the multitenant token setup But hard to say šŸ™‚
Yahya Oxley
Yahya OxleyOP•3mo ago
how do I roll that back? hah
ZachDaniel
ZachDaniel•3mo ago
two ways you can roll "forward" and just remove that stuff, and regen migrations or you can delete the snapshots you added, and the migrations, and reset your local database The --dev flag can help in the future, if you use that then all the migrations are marked as _dev migrations and will be rolled back and deleted when you do mix ash.codegen without the --dev flag
Yahya Oxley
Yahya OxleyOP•3mo ago
ah interesting, thank you! do you know what the issue was? I hope I was at least a little help :p
ZachDaniel
ZachDaniel•3mo ago
Absolutely! You helped find a bug that anyone trying what you tried would have had šŸ™‚ Essentially just not passing an option down when verifying the token 😭 Will release the fix for it tomorrow or the day after.

Did you find this page helpful?