Using Fiddler: Inject cookie into all subsequent requests from initial request - http

I have a batch of requests in Fiddler, the first is a login request and returns a valid cookie. The rest need to use this cookie, I know I can break and edit headers but is it possible to automatically script this behaviour? I'm pretty new to Fiddler but it looks powerful so I'm hoping this is possible, anyone know how or where to start?

To manually add a header, use the Filters tab and use the Request Headers section.
To automatically add a header, click Rules > Customize Rules. Scroll to OnBeforeResponse and write code that stores the target cookie in a global variable declared just inside the Handlers function, e.g.
static var m_MyCookie: String;
Then, inside the OnBeforeRequest function, use that variable, e.g.
if (!String.IsNullOrEmpty(m_MyCookie)) oSession.oRequest["Cookie"] = (m_MyCookie + ";" + oSession.oRequest["Cookie"] )
If you're only trying to add this header to specific requests, use, for instance, the oSession.uriContains function to determine whether the target URL is one that you want to have the cookie.

Related

How to reuse variables from previous request in the Paw rest client?

I need to reuse value which is generated for my previous request.
For example, at first request, I make a POST to the URL /api/products/{UUID} and get HTTP response with code 201 (Created) with an empty body.
And at second request I want to get that product by request GET /api/products/{UUID}, where UUID should be from the first request.
So, the question is how to store that UUID between requests and reuse it?
You can use the Request Sent Dynamic values https://paw.cloud/extensions?extension_type=dynamic_value&q=request+send these will get the value used last time you sent a requst for a given request.
In your case you will want to combine the URLSentValue with the RegExMatch (https://paw.cloud/extensions/RegExMatch) to first get the url as it was last sent for a request and then extract the UUID from the url.
e.g
REQUEST A)
REQUEST B)
The problem is in your first requests answer. Just dont return "[...] an empty body."
If you are talking about a REST design, you will return the UUID in the first request and the client will use it in his second call: GET /api/products/{UUID}
The basic idea behind REST is, that the server doesn't store any informations about previous requests and is "stateless".
I would also adjust your first query. In general the server should generate the UUID and return it (maybe you have reasons to break that, then please excuse me). Your server has (at least sometimes) a better random generator and you can avoid conflicts. So you would usually design it like this:
CLIENT: POST /api/products/ -> Server returns: 201 {product_id: UUID(1234...)}
Client: GET /api/products/{UUID} -> Server returns: 200 {product_detail1: ..., product_detail2: ...}
If your client "loses" the informations and you want him to be later able to get his products, you would usually implement an API endpoint like this:
Client: GET /api/products/ -> Server returns: 200 [{id:UUID(1234...), title:...}, {id:UUID(5678...),, title:...}]
Given something like this, presuming the {UUID} is your replacement "variable":
It is probably so simple it escaped you. All you need to do is create a text file, say UUID.txt:
(with sample data say "12345678U910" as text in the file)
Then all you need to do is replace the {UUID} in the URL with a dynamic token for a file. Delete the {UUID} portion, then right click in the URL line where it was and select
Add Dynamic Value -> File -> File Content :
You will get a drag-n-drop reception widget:
Either press the "Choose File..." or drop the file into the receiver widget:
Don't worry that the dynamic variable token (blue thing in URL) doesn't change yet... Then click elsewhere to let the drop receiver go away and you will have exactly what you want, a variable you can use across URLs or anywhere else for that matter (header fields, form fields, body, etc):
Paw is a great tool that goes asymptotic to awesome when you explore the dynamic value capability. The most powerful yet I have found is the regular expression parsing that can parse raw reply HTML and capture anything you want for the next request... For example, if you UUID came from some user input and was ingested into the server, then returned in a html reply, you could capture that from the reply HTML and re-inject it to the URL, or any field or even add it to the cookies using the Dynamic Value capabilities of Paw.
#chickahoona's answer touches on the more normal way of doing it, with the first request posting to an endpoint without a UUID and the server returning it. With that in place then you can use the RegExpMatch extension to extract the value from the servers's response and use it in subsequent requests.
Alternately, if you must generate the UUID on the client side, then again the RegExpMatch extension can help, simply choose the create request's url for the source and provide a regexp that will strip the UUID off the end of it, such as /([^/]+)$.
A third option I'll throw out to you, put the UUID in an environment variable and just have all of your requests reference it from there.

javascript extension error: Cannot perform modifications

I'm building a custom dynamicValue extension for paw. However i'm not able to set header in the evaluate method. See the sample code below:
evaluate(context) {
const request = context.getCurrentRequest();
request.setHeader('Content-Type', this.contentType); // <-- this gives warning
return this.createSignable(request); // This returns a base64 string.
}
I get the warning saying Javascript extension error: Cannot perform modifications and the header is not set. ( when i comment out request.setHeader call, i get no warnings)
Can anyone please help me resolve this issue?
This is correct, you cannot use setters (set any value) in a dynamic value. In fact, the way Paw evaluates dynamic values is asynchronous and as multiple evaluations can take place simultaneously it would be impossible to record the modifications. For this reason, Paw is simply denying changes and no change is persisted during evaluation.
In the documentation, it's specified that these methods (like setHeaders) is only available for importer extensions. Sorry for the inconvenience!
I think to achieve what you're trying to do, you would need two dynamic values one set in the Authorization header and one set in the Content-Type header.
Alternatively, in the future we're going to add request post-processors, so you'll be able to mutate the computed request ready to be sent to the server for additional modifications.

Using Datazen in an iframe with external authentication

I was able to successfully use external authentication with datazen via HTTPWEBREQUEST from code-behind with VB.NET, but I am unclear how to use this with an iframe or even a div. I'm thinking maybe the authorization cookies/token isn't following the iframe around? The datazen starts to load correctly, but then it redirects back to the login page as if it's not being authenticated. Not sure how to do that part, this stuff is pretty new to me and any help would be greatly appreciated!!
Web page errors include:
-OPTIONS url send # jquery.min.js:19b.extend.ajax # jquery.min.js:19Viewer.Controls.List.ajax # Scripts?page=list:35Viewer.Controls.List.load # Scripts?page=list:35h.callback # Scripts?page=list:35
VM11664 about:srcdoc:1
XMLHttpRequest cannot load http://datazenserver.com/viewer/jsondata. Response for preflight has invalid HTTP status code 405Scripts?page=list:35
load(): Failed to load JSON data. V…r.C…s.List {version: "2.0", description: "KPI & dashboard list loader & controller", url: "/viewer/jsondata", index: "/viewer/", json: null…}(anonymous function) # Scripts?page=list:35c # jquery.min.js:4p.fireWith # jquery.min.js:4k # jquery.min.js:19r # jquery.min.js:19
Scripts?page=list:35
GET http://datazenserver.com/viewer/login 403 (Forbidden)(anonymous function) # Scripts?page=list:35c # jquery.min.js:4p.fireWith # jquery.min.js:4k # jquery.min.js:19r # jquery.min.js:19
' ''//////////////////////////////////
Dim myHttpWebRequest As HttpWebRequest = CType(WebRequest.Create("http://datazenserver.com/"), HttpWebRequest)
myHttpWebRequest.CookieContainer = New System.Net.CookieContainer()
Dim authInfo As String = Session("Email")
myHttpWebRequest.AllowAutoRedirect = False
myHttpWebRequest.Headers.Add("headerkey", authInfo)
myHttpWebRequest.Headers.Add("Access-Control-Allow-Origin", "*")
myHttpWebRequest.Headers.Add("Access-Control-Allow-Headers", "Accept, Content-Type, Origin")
myHttpWebRequest.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
Dim myHttpWebResponse As HttpWebResponse = CType(myHttpWebRequest.GetResponse(), HttpWebResponse)
Response.AppendHeader("Access-Control-Allow-Origin", "*")
' Create a new 'HttpWebRequest' Object to the mentioned URL.
' Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
Dim streamResponse As Stream = myHttpWebResponse.GetResponseStream()
Dim streamRead As New StreamReader(streamResponse)
frame1.Page.Response.AppendHeader("Access-Control-Allow-Origin", "*")
frame1.Page.Response.AppendHeader("headerkey", authInfo)
frame1.Attributes("srcdoc") = "<head><base href='http://datazenserver.com/viewer/' target='_blank'/></head>" & streamRead.ReadToEnd()
You might have to do more of this client-side, and I don't know whether you'll be able to because of security concerns.
External authentication in Datazen looks something like this:
User-Agent | Proxy | Server
-------------------|----------------------|------------------------------------
1. /viewer/home --> 2. Append header --> 3. Check cookie (not present)
<-- 5. Forward <-- 4. Redirect to /viewer/login
6. /viewer/login --> 7. Append header --> 8. Append cookie
<-- 10. Forward <-- 9. Redirect to /viewer/home
11. /viewer/home --> 12. Append header --> 13. Check cookie (valid)
<-- 15. Forward <-- 14. Give content
16. .................. Whatever the user wanted ..........................
So even though you're working off a proxy with a header, you're still getting a cookie back that it uses.
Now, that's just context.
My guess, from your description of the symptoms, is that myHttpWebResponse should have a cookie set (DATAZEN_AUTH_TOKEN, I believe), but it's essentially getting thrown out--you aren't using it anywhere.
You would need to tell your browser client to append that cookie to any subsequent (iframe-based) requests to the domain of your Datazen server, but I don't believe that's possible due to security restrictions. I don't know a whole lot about CORS, though, so there might be a way to permit it.
I don't know whether there's any good way to do what you're looking to do here. At best, I can maybe think of a start to a hack that would work, but I can't even find a good way to make that work, and you really wouldn't want to go there.
Essentially, if you're looking to embed Datazen in an iframe, I would shy away from external authentication. I'd shy away from it regardless, but especially there.
But, if you're absolutely sure you need it over something like ADFS, you'll need some way to get that cookie into your iframe requests.
The only way I can think to make this work would be to put everything on the same domain:
www.example.com
datazen.example.com (which is probably your proxy)
You could then set a cookie from your response that stores some encrypted (and likely expiring) form of Session("Email"), and passes it back down in your html.
That makes your iframe relatively simple, because you can just tell it to load the viewer home. Something to the effect of:
<iframe src="//datazen.example.com/viewer/home"></iframe>
In your proxy, you'll detect the cookie set by your web server, decrypt the email token, ensure it isn't expired, then set a header on the subsequent request onto the Datazen server.
This could be simplified at a couple places, but this should hold as true as possible to your original implementation, as long as you can mess with DNS settings.
I suppose another version of this could involve passing a parameter to your proxy, and sharing some common encryption key. That would get you past having to be on the same domain.
So if you had something like:
var emailEncrypted = encrypt(Session("Email") + ":somesalt:" + DateTime.UtcNow.ToString("O"));
Then used whatever templating language you want to set your iframe up with:
<iframe src="//{{ customDomain }}/viewer/home?emailkey={{ emailEncrypted }}"></iframe>
Then your proxy detected that emailkey parameter, decrypted it, and checked for expiration, that could work.
Now you'd have a choice to make on how to handle this, because Datazen will give you a 302 to /viewer/login to get a cookie, and you need to make sure to pass the correct emailkey on through that.
What I would do, you could accept that emailkey parameter in your proxy, set a completely new cookie yourself, then watch for that cookie on subsequent requests.
Although at that point, it would probably be reasonable to switch your external authentication mode to just use cookies. That's probably a better version of this anyway, assuming this is the only place you use Datazen, and you'd be safe to change something so fundamental. That would substantially reduce your business logic.
But, you wouldn't have to. If you didn't want to change that, you could just check for the cookie, and turn it into a header.
You should do (1), but just for good measure, one thing I'm not sure on, is whether you can pass users directly to /viewer/login to get a cookie from Datazen. Normally you wouldn't, but it seems like you should be able to.
Assuming it works as expected, you could just swap that URL out for that. As far as I know (although I'd have to double-check this), the header is actually only necessary once, to set up the cookie. So if you did that, you should get the cookie, then not need the URL parameter anymore, so the forced navigation would be no concern.
You'll, of course, want to make sure you've got a good form of encryption there, and the expiration pattern is important. But you should be able to secure that if you do it right.
I ended up just grabbing the username and password fields and entering them in with javascript. But this piece helped me a ton. You have to make sure you set the
document.domain ='basedomain.com';
in javascript on both sites in order to access the iframe contents else you'll run into the cross-domain issues.

How can I add common header to every request in Paw?

I need to add a header (or set of headers) for many existing requests (all in workspace except two) and I would like this header to be added as default to new request or be able to add them without rewriting or copying it all.
All I can think of is to use environment variables for the header name and value but if I have multiple headers I would need to add them to every request but it is difficult to maintain.
Is there better way to do this? Is there anything like inheritance for the requests?
you could try adding it as environment variable and use it for every request.
visit https://paw.cloud/docs/environments/environments-reusable-presets

Cancel an HTTP GET request from Firefox Extension

I have a firefox extension that listens to "http-on-modify-request" and inspects all GET requests coming from firefox. I'd like to be able to cancel the request (say return a fail code to the page) or modify the URI of the request but can't seem to do it. the nsiHttpChannel object just doesn't allow it - for instance
delete httpChannel;
or reseting to an empty request
httpChannel = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
don't work (and you can't modify the URI).
So how do you both intercept and modify http GET requests in a firefox extension.
delete httpChannel; just deletes the variable, sort of like saying httpChannel = undefined;. The request itself is unchanged. Similarly, your second idea just sets the variable to point at a new nsIHttpChannel instance, but the old request is still unchanged.
To modify the request, use its properties and methods. See nsIHttpChannel or nsIChannel or nsIRequest. As you say, you can't modify the URI so you might want to cancel it (see below) and replace it with a new one. I'm not sure exactly how to do that but I imagine one of those three pages has the answer.
To cancel it, use nsIRequest.cancel()

Resources