oqtane / oqtane.framework

CMS & Application Framework for Blazor & .NET MAUI
http://www.oqtane.org
MIT License
1.89k stars 546 forks source link

Get an AntiforgeryValidationExeption on the next POST after returning from Stripe-payment #2604

Closed beolafsen closed 1 year ago

beolafsen commented 1 year ago

After return from Stripe-Payment I can work with the solution - but when I try to do a POST (add new customer, do a new Stripe-payemnt, or something like that) I get a AnitforgeryValidationExeption.

Does this have someting to do with the other issue I had with Stripe-payment. Ref. Issue #2080 - see your last comment. If so - do you know a workaround for this?

Are there anything I can do to recover the AntiforgeryToken?

(I'm logged in as a HOST user.)

Message: Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException HResult=0x80131500 _Message=The provided antiforgery token was meant for a different claims-based user than the current user._ Source=Microsoft.AspNetCore.Antiforgery StackTrace: at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet) at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.d9.MoveNext() at Oqtane.Security.AutoValidateAntiforgeryTokenFilter.d3.MoveNext() in C:\Users\beola\source\repos\oqtane\framework\ActualDevelop\Oqtane.Server\Security\AutoValidateAntiforgeryTokenFilter.cs:line 41

This exception was originally thrown at this call stack: [External Code] Oqtane.Security.AutoValidateAntiforgeryTokenFilter.OnAuthorizationAsync(Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext) in AutoValidateAntiforgeryTokenFilter.cs

image

beolafsen commented 1 year ago

If I remove all Antiforgery test on POST - everything works fine except logout. When I try to logout I get this message:

image

sbwalker commented 1 year ago

My guess is that you need to pass the antiforgery token value to Stripe so that it can include it in the payload when it posts back to your site. This is a common scenario when dealing with OIDC servers as well - it is one of the main reasons for the "state" parameter in the OIDC spec so that you can pass the antiforgery token value and have it posted back.

beolafsen commented 1 year ago

OK - I tried to add the SiteState.AntiforgeryToken to the SuccessURL and the CancelURL like this:

        vmStripeDirectPaymentInput = new VMStripeDirectPaymentInput
        {
........
.......
            SuccessUrl = $"{basisUrl}ttadmin/ttadminregistration?stripestatus=ok&tavlingid={_currentTavlingsdata.Id}&klubbid={klubbid}&useremail={GetUserEmail()}&state={SiteState.AntiForgeryToken}&sessionid=" + "{CHECKOUT_SESSION_ID}",
            CancelUrl = $"{basisUrl}ttadmin/ttadminregistration?stripestatus=nok&tavlingid={_currentTavlingsdata.Id}&state={SiteState.AntiForgeryToken}"
        };

And then I redirected it to the StripeCheckout like this:

            var interop = new OqtaneLibrary.Client.InteropLibrary(JSRuntime);
            await interop.RedirectToCheckout(result.Checkout_Session_Id, _stripePublishableKey, StripeAccount);

I then got the AntiforgeryToken value in the reply from Stripe (in the state property) - but I don't know what to do with it. Any ideas?

Respons from Stripe: https://localhost:44323/ttadmin/ttadminregistration?stripestatus=nok&tavlingid=262&state=CfDJ8ITHcaoKPMhDogO0sy3csVAPuL8-uXzKzkCnK8oqWcOK5Xheg5Ih9E1xg_5bUD5T-H7rcQmKFCxjbxHwh_YjbN7cSs6b2hK_5dEPnGLnFiIFQdWcj3_6iq_9bS1UzoPGxw96avVk3bbWtPEAF-XFV2IoEGH-S6vuQgU8rvIeEH5RcWT5XE5WDXXkY0jfUGKXkA

sbwalker commented 1 year ago

You shouldn't need to do anything with it - the AntiForgery middleware will validate the token automatically and it should prevent any antiforgery errors on subsequent requests.

beolafsen commented 1 year ago

Yes - but I get the message ex = {"The provided antiforgery token was meant for a different claims-based user than the current user."} on the next POST after comming back from Stripe.

beolafsen commented 1 year ago

Hi! I have made a new installation with the latest OqtaneFramework and implemented one module with the minimum of code to communicate with Stripe.

StripeTest Index image

All the Stripe parameters etc are hardcoded to make it a minimumsoulution. On the testsceen I show to buttons: 1) "Call Stripe with JS" and this function use this code to call Stripe.

 var interop = new Interop(JSRuntime);
 await interop.RedirectToCheckout(result.Checkout_Session_Id, "pk_testcccccccccc....MjUhdMDMK4dotZ00Z9vtz7oT", "acct_......");

2) "Call Stripe with NavigationManager" and this function use this code to call Stripe. NavigationManager.NavigateTo(result.Checkout_Session_Url);

Both of them call Stripe and give a Antiforgery error on the fist POST after returning.

Video-Tue-Mar-28-2023-13-46-29.webm

I've posted this version (w/oqtaneframework + one module) on github under https://github.com/beolafsen/OqtaneStripeTest with the hope that you have the time and inclination to find out what this error is coming from. If there's a problem in Oqtane, it would be nice to find out. We will be hosting a European Championship in table tennis in a couple of months and the idea is to use Oqtane for registration and payment of additional services not covered by the official sw version. About 1500 participants are expected from all over Europe.

sbwalker commented 1 year ago

@beolafsen thank you for the minimal repro project - I will investigate further.

One thing which comes to mind is that I had a similar problem when implementing the OIDC integration. In order to resolve the problem I added support for a querystring parameter of "reload=post". The Return Url sent to the OIDC provider includes this parameter so that when the browser is redirected back to the site it contains this parameter. When the site router sees this parameter it does a POST operation to the /pages/external path... which essentially redirects the user back to their current site url. However this additional "postback" forces the Antiforgery middleware to create a new cookie. This blog describes more detail: https://www.oqtane.org/blog/!/43/antiforgery-and-blazor

So I am curious if you could simply include a "&reload=post" to the Return Url you pass to Stripe.

beolafsen commented 1 year ago

Thank you for helping. This change work fine - also with Hostingmodel -Prerender = Yes.

Thanks. Bjørn-Even