I'm scrapping a page which is the result of a redirect: I visit page1 first, then it redirects to page2 via http-equiv="refresh". I'm scrapping page2. Content on page2 is based on some cookies page1 sets. I see page1 returns 2 cookies, but when I request page 2 (sending the same CookieContainer, one cookie is missing. What's wrong in my code?
Thank you:
First :
I create a CookieContainer and an HttpWebRequest and request for page1.
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(eQuery);
req.AllowAutoRedirect = true; // but it doesn't autoredirects the meta-refresh
req.CookieContainer = cookiesContainer;
This is the result I get this from visiting page1
HTTP/1.1 200 OK
Date: Tue, 12 Apr 2011 19:14:06 GMT
Server: (...)
Set-Cookie: NAME1=VALUE1; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: NAME2=VALUE2; expires=Wed, 13-Apr-2011 19:14:06 GMT
Content-Length: 174
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
(...)
Everything is fine so far, I get two cookies are there and I get two cookie objects within the container.
Then I parse the "content" value of the meta http-equiv for the next url. And request it using a similar code and using the same container. But only one cookie is sent. Here is the HTTP sent:
GET DETECTED_URL_IN_HTTP_EQUIV_REFRESH HTTP/1.1
User-Agent: (...)
Host: example.com
Cookie: NAME1=VALUE1
As you see cookie NAME2 is missing. Why is that happening? is something related differences in the two cookies (one has path and other has expiration date)?
Any idea how can I pass the two cookies?
PS: I don't have access to page1, so I can't set path, or expiration for cookies. I'm scrapping those pages.
Thank you.
If you don't specify a path on your cookie it will default to the path it was requested on. So if you received a cookie on this request with no path declaration:
http://contoso.com/subfolder/test.aspx
The browser would only send back that cookie for more requests in the /subfolder/ directory. To have the browser send it back for all paths you need to include path=/ when setting the cookie.
Related
Using ASP.NET Web API 2, if I want to return HttpResponseMessage with Unauthorized status code, I'll get different response headers - with or without WWW-Authenticate header field - depending on whether this response message has content or not.
WWW-Authenticate header field is a required field for Unauthorized response according to Status Code Definitions.
And the lack of WWW-Authenticate header field in the response causes an error for the next request.
To see the problem you can create a new Web API project and to add a simple test controller:
public class TestController : ApiController
{
public HttpResponseMessage Get()
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
// Content = new StringContent("You are not authorized"),
};
return responseMessage;
}
}
If the response message doesn't have a content we'll get normal 401 responses for our calls:
With responses:
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Bearer
X-SourceFiles: =?UTF-8?B?RDpcUHJvamVjdHNcVGVzdEFwaVxUZXN0QXBpXGFwaVxUZXN0?=
X-Powered-By: ASP.NET
Date: Fri, 01 May 2015 05:31:20 GMT
Content-Length: 0
If we add content to the response message (uncomment the content line), each second response will be not 401, but 500
The responses with 401 will have the following headers:
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 22
Content-Type: text/plain; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcUHJvamVjdHNcVGVzdEFwaVxUZXN0QXBpXGFwaVxUZXN0?=
X-Powered-By: ASP.NET
Date: Fri, 01 May 2015 05:34:38 GMT
You are not authorized
And the responses with 500 will say
Server cannot append header after HTTP headers have been sent.
Description: an unhandled exception occurred during the execution of the current web request.Please review the stack trace for more information about the error and where it originated in the code..... Exception Details: System.Web.HttpException: Server cannot append header after HTTP headers have been sent.
So it looks like it happens because previous responses are illegal - they don't contain WWW-Authenticate header attribute.
But it doesn't help even if I try to add WWW-Authenticate manually
public class TestController : ApiController
{
public HttpResponseMessage Get()
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new StringContent("You are not authorized"),
};
responseMessage.Headers.Add("WWW-Authenticate", "Bearer");
return responseMessage;
}
}
Now it's in the response
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 22
Content-Type: text/plain; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
WWW-Authenticate: Bearer
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcUHJvamVjdHNcVGVzdEFwaVxUZXN0QXBpXGFwaVxUZXN0?=
X-Powered-By: ASP.NET
Date: Fri, 01 May 2015 05:43:51 GMT
You are not authorized
but I still have every second request 500 instead of 401.
Can anyone clarify what's going on here and how to make it work properly?
The Server cannot append header after HTTP headers have been sent. error message from the response with 500 is caused by a module trying to write http headers into the response stream once your action has executed - since your action has already written both the headers and the body.
The usual culprits are FormsAuthentication and Owin cookie authentication kicking in and trying to replace 401 with 302 (redirect to login page).
Scenario:
1. your action executed - added header 401 Unauthorized to the headers collection plus wrote the header into the response stream and then wrote the body (You are not authorized) to the response stream.
2. FormsAuthenticationModule sees 401 Unauthorized header in the response headers collection and attempts to change that to 302 Redirect to login page, plus attempts to write the corresponding header to the response stream - which fails with Server cannot append header after HTTP headers have been sent., since the headers were already written earlier.
Possible fixes:
1) if FormsAuthenticationModule is in your request pipeline
consider disabling it if you are not using it
in .net 4.5 you you can suppress forms authentication redirection by setting HttpResponse.SuppressFormsAuthenticationRedirect property to false
if not on .net 4.5, consider using HttpModule which will suppress this redirection
Phil Haack blogged on all the above options.
2) if using OWIN cookie authentication - consider not setting LoginPath property
I was hoping the following code would yield a non-zero value:
var webRequest = (HttpWebRequest) WebRequest.Create(loginUrl);
var webResponse = (HttpWebResponse)webRequest.GetResponse();
Console.WriteLine(webResponse.Cookies.Count);
yet no cookies seem to show up in webRespone.Cookies. I'm positive the cookies are there, as I'm sniffing the data with Fiddler. This is the response I'm getting:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
Set-Cookie: __Abc=Def; path=/; HttpOnly
PS-ResponseTime: 00:00:00.0624001
PS-Build: 2013-03-19-11-36-59
PS-Node: 02
Date: Tue, 19 Mar 2013 21:14:51 GMT
Content-Length: 57872
Does it have anything to do with the fact the cookie is HttpOnly?
Edit
It's seems I can get them through HttpWebRequest's CookieContainer which is certainly useful if I intend to proceed to a sequence of requests/responses. But why can't I access them the same through the HttpWebResponse.Cookies field, anyway?
Thanks
You're right, you'll need to hand the request an instance of CookieContainer and then reference that instance to see the cookies. Basically, HttpWebResponse does not directly expose cookies on the response that are marked as HttpOnly.
So I'm in the process of attempting to simulate multiple logins all generating exceptions at the same time on our corporate website for the purpose of testing our logging framework (which we think there may be issues with thread synchronization). Anyway, so I need to log in to our website programatically. Here's what I have so far:
// Block 1
Uri url = new Uri("http://withheld");
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "GET";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
string viewState = string.Empty;
string previousPage = string.Empty;
string eventValidation = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string strResponse = reader.ReadToEnd();
viewState = HttpUtility.UrlEncode(GetTagValue(strResponse, "__VIEWSTATE"));
previousPage = HttpUtility.UrlEncode(GetTagValue(strResponse, "__PREVIOUSPAGE"));
eventValidation = HttpUtility.UrlEncode(GetTagValue(strResponse, "__EVENTVALIDATION"));
}
// Block 2
string username = "user01";
string password = "password99";
HttpWebRequest request2 = WebRequest.Create(url) as HttpWebRequest;
request2.KeepAlive = true;
request2.Method = "POST";
request2.ContentType = "application/x-www-form-urlencoded";
string postData = string.Format("__LASTFOCUS=&ctrlCreateNewPassword_scriptManagerMaster_HiddenField=&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE={0}&__PREVIOUSPAGE={1}&__EVENTVALIDATION={2}&UserName={3}&Password={4}&LoginButton=Log+in", new string[] { viewState, previousPage, eventValidation, username, password});
byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(postData);
request2.ContentLength = dataBytes.Length;
using (Stream postStream = request2.GetRequestStream())
{
// Here's the problem
postStream.Write(dataBytes, 0, dataBytes.Length);
}
HttpWebResponse httpResponse = request2.GetResponse() as HttpWebResponse;
// At this point httpResponse.Cookies is null
// I believe it's because the line above has actually initiated another
// request/response which DOES NOT include the authentication cookie.
// See fiddler output below to understand why I think that.
// Block 3
//Uri url2 = new Uri("http://Withheld/GenerateException.aspx");
//http = WebRequest.Create(url2) as HttpWebRequest;
//http.CookieContainer = new CookieContainer();
//http.CookieContainer.Add(httpResponse.Cookies);
//HttpWebResponse httpResponse2 = http.GetResponse() as HttpWebResponse;
Looks reasonably straightforward right? Well it doesn't work. I don't know whether I need the viewState and whatnot or not, but I figured I'd mimic what a regular browser does as closely as possible.
Near as I can tell what's happening is this:
We hit the page with a simple GET. That gives us the viewstate, etc which is parsed out to be included in the following request.
We now post the viewstate, username, password, etc to the server using postStream.Write(). The server at this point responds with an authentication cookie, and forwards us off to /Default.aspx.
Now we execute reqest2.GetResponse(), but instead of getting the response that forwarded us to /default.aspx and had he authentication cookie, it looks like this line is actually causing ANOTHER request to get us the resource at /default.aspx. The problem is httpWebResponse DOES NOT include the authentication cookie we need for the next request (which is commented out currently).
Why? Why is this behaving in this manor, and how do I handle it properly. Here's the output from fiddler to further explain what's going on:
Block 1 generates this request/response
Request Header:
GET http://withheld/Login.aspx HTTP/1.1
Host: withheld
Connection: Keep-Alive
Response Header:
HTTP/1.1 200 OK
Connection: close
Date: Mon, 04 Feb 2013 16:37:37 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Set-Cookie: .EXTASPXAUTH=; expires=Tue, 12-Oct-1999 04:00:00 GMT; path=/; HttpOnly
Cache-Control: private, no-cache="Set-Cookie"
Content-Type: text/html; charset=utf-8
Content-Length: 16975
Response is the actual login webpage. Omitted for obvious reasons.
Stepping through the code, this request/response is generated immediately following the call to postStream.Write:
Request:
POST http://Withheld/Login.aspx HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: withheld
Content-Length: 2109
Expect: 100-continue
__LASTFOCUS=&ctrlCreateNewPassword_scriptManagerMaster_HiddenField=&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2fwEPDwUJNTE1NTIxNjkxD2QWAgIDD2QWBgIDDxYCHgVjbGFzcwUQaGVhZGVyX2Jhbm5lcl9lbhYCAgEPFgQeB29uY2xpY2sFI3dpbmRvdy5sb2NhdGlvbj0naHR0cDovL3d3dy5tZG0uY2EnHwAFFmhlYWRlcl9iYW5uZXJfZW5fc21hbGxkAgUPZBYQAgcPDxYEHhdQYXJ0aWFsUmVuZGVyaW5nQ2hlY2tlZGceGUlzUGFydGlhbFJlbmRlcmluZ0VuYWJsZWRoZGQCCQ8PFgQfAmcfA2hkZAIPDw8WBB8CZx8DaGRkAhEPDxYCHg1PbkNsaWVudENsaWNrBcEBamF2YXNjcmlwdDpQYWdlX0NsaWVudFZhbGlkYXRlKCdMb2dpbkN0cmwnKTsgaWYgKFBhZ2VfSXNWYWxpZCkgeyBMb2dpbkJ1dHRvbi5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7IExvZ2luQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7IExvZ2luQnV0dG9uRGlzYWJsZWQuc3R5bGUudmlzaWJpbGl0eSA9ICd2aXNpYmxlJzsgfWRkAhkPDxYCHgRUZXh0Bc0BSWYgeW91IHJlcXVpcmUgYXNzaXN0YW5jZSwgb3VyIE1EIE9ubGluZSBTdXBwb3J0IFNwZWNpYWxpc3RzIGNhbiBiZSByZWFjaGVkIGF0ICg4NzcpIDQzMS0wMzMwIG9yIGJ5IGUtbWFpbCBhdCA8YSBocmVmPSJtYWlsdG86d2Vic3VwcG9ydEBjbWEuY2EiPndlYnN1cHBvcnRAY21hLmNhPC9hPi48YnI%2bPGJyPldlIGVuY291cmFnZSB5b3UgdG8gcmV2aWV3IHRoZWRkAhsPDxYCHwQFOXdpbmRvdy5vcGVuKCdodHRwOi8vMTkyLjE2OC4xNjUuMzIvbGVnYWwvJyk7cmV0dXJuIGZhbHNlO2RkAh8PDxYCHwQFRndpbmRvdy5vcGVuKCdodHRwOi8vMTkyLjE2OC4xNjUuMzIvc3lzdGVtLWVuaGFuY2VtZW50LycpO3JldHVybiBmYWxzZTtkZAIhDw8WAh8EBUZ3aW5kb3cub3BlbignaHR0cDovLzE5Mi4xNjguMTY1LjMyL3N5c3RlbS1lbmhhbmNlbWVudC8nKTtyZXR1cm4gZmFsc2U7ZGQCCQ9kFgICAQ9kFgICAg9kFgJmD2QWAgIBD2QWAgIdDw8WAh8EBfsBamF2YXNjcmlwdDpjdHJsQ3JlYXRlTmV3UGFzc3dvcmRfQ3JlYXRlTmV3UGFzc3dvcmRQdXNoQnV0dG9uLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJzsgY3RybENyZWF0ZU5ld1Bhc3N3b3JkX0NyZWF0ZU5ld1Bhc3N3b3JkUHVzaEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOyBjdHJsQ3JlYXRlTmV3UGFzc3dvcmRfQ3JlYXRlTmV3UGFzc3dvcmRQdXNoQnV0dG9uRGlzYWJsZWQuc3R5bGUudmlzaWJpbGl0eSA9ICd2aXNpYmxlJztkZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAQUMaWJ0bk1vcmVJbmZvdZmFXkMbPfVWPQYtreXvFt8Bck8%3d&__PREVIOUSPAGE=1aYW5DqTKrT4ieGPkHcnrQLIq8lEcSIVkql1EugwSQNV_5102t5D7QDmOnuQFA4Tz9Mh5-CEYpkRngMROFFeeAG12Ss1&__EVENTVALIDATION=%2fwEWCQKKr%2bXcBgKvruq2CALSxeCRDwL%2bjNCfDwKH8YSKBgKN6O7XCwKz9P38DALl3I74DwLWxI74D6Nz%2f2bCBFC%2bM9glZmEyM%2byOCTZg&UserName=user01&Password=password99&LoginButton=Log+in
Response:
HTTP/1.1 302 Found
Connection: close
Date: Mon, 04 Feb 2013 16:36:55 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Location: /Default.aspx?locale=en
Set-Cookie: .EXTASPXAUTH=65BB5BFDD274F730E26CAEAAEB417792A764E7B8E8C6C9AC8C47FA97EF35DFACF551A53EAA6EA67D868C8A9BF55EBA758A5E724C58269028EE48F56268A204CBED19B60FC1AF58892989D9546202C037E97BF0EEE6A6281FF5EEA461BC30C5C7A71DFD64027AEB796D3FD21AE97ECFB16FF0F95C; path=/; HttpOnly
Cache-Control: private, no-cache="Set-Cookie"
Content-Type: text/html; charset=utf-8
Content-Length: 140
<html><head><title>Object moved</title></head><body>
<h2>Object moved to here.</h2>
</body></html>
Note that the above response includes an authenication cookie.
Now we run the following line of code with the intention of getting that cookie:
HttpWebResponse httpResponse = request2.GetResponse() as HttpWebResponse;
But instead the following request/response is generated in fiddler:
Request:
GET http://withtheld/Default.aspx?locale=en HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: withheld
Response:
HTTP/1.1 302 Found
Connection: close
Date: Mon, 04 Feb 2013 16:37:38 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Location: /Login.aspx?ReturnUrl=%2fDefault.aspx%3flocale%3den&locale=en
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 182
<html><head><title>Object moved</title></head><body>
<h2>Object moved to here.</h2>
</body></html>
I believe this is the response that httpResponse now contains. How can I actually get the cookie to request up another protected page after the login is done?
Thanks!
Well it turns out I had two problems here. One is that I needed to call this:
request.AllowAutoRedirect = false
This keeps the framework from just skipping the response that had the authentication cookie in it, and actually gives back the response we're interested in.
The other issue was that you have to create a new instance of a CookieContainer and assign it to the request. Without having done that Response.Cookies contains no cookies. As soon as you've assigned your own container it's populated after the response is made. I don't know why.
When you login, the authentication token will be sent as a cookie from the server to your client. You will need to store this cookie, and then re-send it with every future request. Re-sending the cookie tells the server that you have been authenticated as a certain user.
To get the cookies that were sent in response after you logged in:
HttpCookieCollection loginResponseCookies = Response.Cookies;
This collection will include the auth cookie, any session cookies, etc.
Then, just re-send these cookies with every subsequent request, and the server will authenticate you as a result.
foreach(HttpCookie loginResponseCookie in loginResponseCookies)
{
Response.Cookies.Add(loginResponseCookie);
}
OK, now that I have investigated the code, there are no cookies to speak of when it comes to storing the cookie collection in a CookieContainer, so I would like to divert and use the headers. The only problem is I do not understand how to use them so that I may download the file form the website.
Could someone give me an example of how I would potentially use headers?
Also the code I used for the cookies is as follows, maybe there is a mistake:
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
CookieContainer newCookies = new CookieContainer();
newCookies.Add(response.Cookies);
All I get is this header Headers = {Content-Length: 6292
Cache-Control: private
Content-Type: text/html; charset=utf-8
Date: Sun, 22 Jul 2012 03:12:59 GMT
Set-Cookie: ASP.NET_SessionId=dpub2i550ynjfonuv0o0n4nb; domain=website.co.nz; path=/; HttpOnly
Server: Microsoft-IIS/6.0
X-AspNet-Vers...
The code does not throw an exception. Just as a side not I am using request.Method = "GET";.
That's the result of the .ToString() method which is called when viewing the variable in the debugger. You need to access the members of CookieContainer.
I followed the instruction at http://dev.twitter.com/pages/auth#request-token, and developed a c# class to do the OAuth authorization. I used the parameters on the page, and the output signature base string and signature match that on the page. So I think the algorithm part is correct. Then I replaced the parameters with the ones in my twitter application, but I failed to acquire the request token from Twitter service. And the response data is "Failed to validate oauth signature and token".
Here's the request I send (I used http, instead of https for debug):
POST http://api.twitter.com/oauth/request_token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: OAuth oauth_callback="http%3A%2F%2Flocalhost%3A3005%2Fthe_dance%2Fprocess_callback%3Fservice_provider_id%3D11", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_nonce="QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323042", oauth_version="1.0", oauth_signagure="IP%2FEEoc4tKdiobM%2FKH5cPK69cJM%3D"
Host: api.twitter.com
Proxy-Connection: Keep-Alive
And here's the response:
HTTP/1.1 401 Unauthorized
Connection: Keep-Alive
Connection: Proxy-Support
Content-Length: 44
Via: 1.1 APS-PRXY-09
Expires: Tue, 31 Mar 1981 05:00:00 GMT
Date: Fri, 08 Apr 2011 05:47:20 GMT
Content-Type: text/html; charset=utf-8
Server: hi
Proxy-Support: Session-Based-Authentication
Status: 401 Unauthorized
X-Transaction: 1302241640-40339-46793
Last-Modified: Fri, 08 Apr 2011 05:47:20 GMT
X-Runtime: 0.01519
Pragma: no-cache
X-Revision: DEV
Cache-Control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
Set-Cookie: k=207.46.55.29.1302241640766556; path=/; expires=Fri, 15-Apr-11 05:47:20 GMT; domain=.twitter.com
Set-Cookie: guest_id=13022416407746962; path=/; expires=Sun, 08 May 2011 05:47:20 GMT
Set-Cookie: _twitter_sess=BAh7CDoPY3JlYXRlZF9hdGwrCEiBpjMvAToHaWQiJWMzMTViOGZiNDkzMDRi%250ANjNhMmQwYmVkZDBhNTc2NTc4IgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVy%250AOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--177afd5c0f6fe30005ab9a9412e6f85ab03cbfa7; domain=.twitter.com; path=/; HttpOnly
Vary: Accept-Encoding
Failed to validate oauth signature and token
This is how I generate the normalized parameters:
string.Join("&", (from d in this.BuildParameterDict()
select string.Format("{0}={1}", OAuthEncoding.Encode(d.Key), OAuthEncoding.Encode(d.Value))))
The BuildParameterDict method will sorted build a list with: parameters from query string; parameters from body; parameters sepcific to 'oauth', except the 'oauth_signature'.
Then the signature base string is generated by:
StringBuilder sb = new StringBuilder();
sb.Append(OAuthEncoding.Encode(this._request.Method));
sb.Append('&');
sb.Append(OAuthEncoding.Encode(this.GetNormalUri()));
sb.Append('&');
sb.Append(OAuthEncoding.Encode(this.GetNormalParameters()));
This is the generated base string with parameters from the above page:
POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Flocalhost%253A3005%252Fthe_dance%252Fprocess_callback%253Fservice_provider_id%253D11%26oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3DQP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1272323042%26oauth_version%3D1.0
which is identical to the string on that page.
Your oauth signature is listed as "oauth_signagure" in your request.
oAuth parameters has to be sorted before sending, but signature has to be at the end of the authorization request.(9.1.1 in http://oauth.net/core/1.0/#anchor14)
You may also need to specify a realm="/oauth/request_token". It's optional, but as I remember correctly Twitter wants this one for a request token.
If you can add your code we might find what's going on, as you might not be building your request and key for signature hashing correctly.