views:

221

answers:

3

Here's the issue. I'm using ASP.NET Forms Authentication for an account balance type website. Once a user logs in, they are able to make a payment against their account by going to a 3rd party website (3pw). When the user clicks to make a payment, this is what happens:

  1. My website makes a request to the 3pw passing an id.
  2. The 3pw does a request back to my site passing the id plus a security id.
  3. I verify stuff....
  4. More stuff happens that you don't need to care about...

When I'm testing this process I can see in the web logs that I'm getting to the one-time payment page on my site. Using something like Live HTTPHeaders I can see the request to the 3pw website (step#1). Then the web logs show a request from the 3pw to my site (step#2), but the very next entry in the logs is a new request to the login page for my site.

login.aspx?ReturnUrl=mypage.aspx

The 3pw doesn't know how to handle the redirect to the login page and then fails. The question is why does my site think the user is no longer authenticated when the request comes in from the 3pw to mypage.aspx? I've watched my cookies and the cookie that was created when I logged in is still there. Shouldn't that tell the server that I'm still an authenticated user?

Here's what I have in my web.config

<authentication mode="Forms">
  <forms defaultUrl="~/somepage.aspx" 
     loginUrl="~/login.aspx"
         protection="All"
     timeout="30" 
     name="MyCookieName"
     enableCrossAppRedirects="true"
     requireSSL="true"/>
</authentication>

<location path="manage">
  <system.web>
    <authorization>
      <allow roles="UserRole" />
      <deny users="?" />
    </authorization>
  </system.web>
</location>

Authenticated users are in the role UserRole. The page the 3pw is requesting is in the Manage directory. The 3pw is not written in .NET and I have no control over its configuration.

Update:

I apologize if I'm not being as clear as I could be. Let me restate the steps.

  1. A user logs into my website and is authenticated.
  2. The user goes to the one-time payment page on my website.
  3. On the one-time payment page, the user clicks a Make Payment button.
  4. The Make Payment button makes a GET request to a 3pw passing an id in the query string.
  5. The 3pw see the request and makes a POST request to a verification page on my website.

It's the post to the verification page that the error happens. According to the log file, the request to the verification page is being redirected to the login page. My web server is seeing the request come in, tries to serve the page but realizes the user is not authenticated, and redirects the request to the login. This part confuses me because I thought the server would look to see if the user was authenticated and since they still are because the cookie still exists, serve up the requested page.

Maybe I don't fully understand the whole process, but since the request to the 3pw initiated from my logged in user, wouldn't any requests back to my site from the 3pw still fall under my user?

A: 

You're saying that the 3rd party website makes a request to your site (step 2)?

If I am understanding this correctly, this request wouldn't be authenticated because it's not coming from the user but instead is coming from the 3rd party website.

Edit:

Based on the information you've updated, my initial thoughts were correct. The ASP.NET runtime has no way of knowing that requests from the 3rd party website are "from the user" because it is a separate POST request altogether from a different location.

There are a few ways to remediate this, one way as Daniel Auger suggests you can open up your accountPostback.aspx page to everyone. This will probably work well enough for you.

If you want to lock it down a little, I suppose you could do something like this (assuming the 3rd party website has a static IP address):

// In Global.asax...
void Authenticate_Request(object sender, EventArgs e)
{
    if (Context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] == System.Web.Configuration.WebConfigurationManager.AppSettings["ThirdPartyWebsiteIP"])
    {
        Context.User = new System.Security.Principal.GenericPrincipal(new System.Security.Principal.GenericIdentity("ThirdPartyWebsite"), new string[] {"AccountPostbackPermission"});
    }
}

and update your web.config appSettings:

<configuration>
  <configSections>
    <appSettings>
      <add key="ThirdPartyWebsiteIP" value="127.0.0.1" /> // edit this IP address to match the 3rd party's website's IP address
    </appSettings>
  <configSections>
<configuration>

and also the authorization:

<location path="manage">
  <system.web>
    <authorization>
      <allow roles="AccountPostbackPermission" />
      <deny users="?" />
    </authorization>
  </system.web>
</location>

Of course if the site uses a dynamic IP address this will not work and you'd be forced to just allow everyone to the page.

John Rasch
If this is the case, how do I get around this. I hate even suggesting it, but do I need to use an iframe.
Notorious2tall
A: 

Could you clarify what you mean by "request"? If you mean they literally initiate a GET or POST request from their server to yours, then John Rasch is correct: they don't have your authentication cookie. If you mean that they redirect to your site, then the authenticated user's browser is actually making the request, in which case it seems like it should be working.

Clarify please...thanks!

Matt Peterson
Updated my question.
Notorious2tall
Yes, after my GET to their url. They do a POST to one of my pages.
Notorious2tall
A: 

If you want the third party website to post back to a page on your website, you need to make an exception for that page in the forms authentication configuration. You don't want the page that is being posted to to be protected.

example of allowing a resource to be unprotected:

  <location path="accountPostback.aspx">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
Daniel Auger