I have been experimenting with authentication on APIs and was looking to pass a token with the request that uniquely identifies the user.
I want to know why there would only be an encode function create_signed_value and no decode_signed_value or verify_signed_value.
Are you expected to set it in a cookie and use the get_secure_cookie although I'm struggling with actually setting it too?
UPDATE:
To decode a signed value created using create_signed_value, you can pass the signed value to the get_secure_cookie method (see docs):
signed_value = self.create_signed_value(name='auth', value='John Doe')
decoded_value = self.get_secure_cookie(name='auth', value=signed_value)
When I wrote the original answer, I was unaware of the API which I've mentioned above.
Related
I'm using Python with the Django Rest framework and am trying to receive webhook events correctly from stripe.
However I constantly get this error:
stripe.error.SignatureVerificationError: No signatures found matching the expected signature for payload
This is the code:
WEBHOOK_SECRET = settings.STRIPE_WEBHOOK_SK
#csrf_exempt
def webhook(request):
sig_header = request.headers.get('Stripe-Signature', None)
payload = request.body
try:
event = stripe.Webhook.construct_event(
payload=payload,
sig_header=sig_header,
secret=WEBHOOK_SECRET
)
except ValueError as e:
raise e
except stripe.error.SignatureVerificationError as e:
raise e
return HttpResponse(status=200)
I have also tried modifying the request body format like so:
payload = request.body.decode('utf-8')
# and also
payload = json.loads(request.body)
And yet no luck.
The error is coming from the verify_header() class method inside the WebhookSignature class.
This is the part of the method where it fails:
if not any(util.secure_compare(expected_sig, s) for s in signatures):
raise error.SignatureVerificationError(
"No signatures found matching the expected signature for payload",
header,
payload,
)
So I printed out exptected_sig and signatures before this line and found that regardless of what format request.body is in, signatures is always there (which is good), but they never match the signature from the header.
Why is this?
When Stripe calculates the signature for the Event it sends you, it uses a specific "payload" representing the entire Event's content. The signature is done on that exact payload and any change to it such as adding a new line, removing a space or changing the order of the properties will change the payload and the corresponding signature.
When you verify the signature, you need to make sure that you pass the exact raw payload that Stripe sent you, otherwise the signature you calculate won't match the Stripe one.
Frameworks can sometimes try to be helpful when receiving a request and they detect JSON and automatically parse it for you. This means that you think you are getting the "raw payload/body" but really you get an alternate version. It has the same content but it doesn't match what Stripe sent you.
This is fairly common with Express in Node.js for example. So, as the developer, you have to explicitly request the exact raw/original payload Stripe sent you. And how to do this can differ based on a variety of factors. There are 2 issues on the stripe-node github with numerous potential fixes here and here.
With Django, the same can happen and you need to make sure that your code requests the raw payload. You seem to use request.body as expected but that's one thing you want to dig into further.
Additionally, another common mistake is using the wrong Webhook secret. If you use the Stripe CLI for example, it creates a new secret for you that is different from the one you see in the Dashboard for this Webhook Endpoint. You need to make sure you use the correct secret based on the environment you're in.
Using the HTTPretty library for Python, I can create mock HTTP responses for my unit tests. When the code I am testing runs, instead of my request reaching the third party, the request is intercepted and my code receives the response I configured.
I then use last_request() and can check the url my code requested, any parameters, etc.
What I would like is to know how can I access not just the last request but also any other requests my code sent before the last one.
This seems to be possible. In the documentation it uses a list called latest_requests. For example here
But that doesn't seem to work for me. I get an AttributeError AttributeError: module 'httpretty' has no attribute 'latest_requests'
Here is some code that illustrates what I am trying to do and where I get AttributeError
import httpretty
import requests
httpretty.enable()
httpretty.register_uri(
method=httpretty.GET,
uri='http://www.firsturl.com',
status=200,
body='First Body'
)
httpretty.enable()
httpretty.register_uri(
method=httpretty.GET,
uri='http://www.secondurl.com',
status=200,
body='secondBody'
)
firstresponse = requests.get('http://www.firsturl.com')
secondresponse = requests.get('http://www.secondurl.com')
print(httpretty.latest_requests[-1].url)
# clean up
httpretty.disable()
httpretty.reset()
Thanks!!
Unfortunately, after reading the docs and attempting to get your code working, I can only describe the documentation as blatantly incorrect. There appear to be three | separate | pull requests from several years ago that claim to make httpretty.latest_requests a real attribute but none of them have merged in for whatever reason.
With all of that said, I managed to get the list of all previous requests by calling
httpretty.HTTPretty.latest_requests
This returns a list of HTTPrettyRequest objects. Seeing as httpretty.last_request() returns an HTTPrettyRequest object, that attribute is probably what you're looking for.
Unfortunately, .url is not defined on that class (but it is defined on the blank request object which doesn't make any sense). If you want to check that the request URL is what you're expecting, you pretty much have to try reconstructing it yourself:
req = httpretty.HTTPretty.latest_requests[-1]
url = req.headers.get('Host', '') + req.path
If you're passing anything in the query string, you'll have to reconstruct that from req.querystring although that's not ordered so you probably don't want to turn that into a string for matching purposes. Also, if all of your requests are going to the same domain, you can leave off the host part and just compare req.path.
I am using QuickFix with Python. On the back of this question, I've explored the SessionID class a bit, but I am mystified by the behavior.
The SessionID class is described here. It is formed of a BeginString, SenderCompID and TargetCompID.
Say my SessionID in string form looks like this: FIX.4.2:LMXTS->TS68.
fix.SessionID().fromString() returns :->
Which if you look, are the three filler characters separating the BeginString, SenderCompID and TargetCompID.
fix.SessionID().getBeginString returns 8=☺ (i.e. the BeginString is nowhere). And the same thing applies to getSenderCompID and getTargetCompID, they return 49=☺ and 56=☺ respectively.
fix.SessionID().getTargetCompID().getValue() returns the empty string ''.
Trying another way, fix.SessionID().fromString('FIX.4.2:LMXTS->TS68') returns None.
I am trying to get these values after the session is created (which I can explicitly see happening when I pass fix.ScreenLogFactory(settings) to the initiator. So I am confused.
The method void onLogon( const SessionID& ) {} in Application.h is fired when the session is logged on, and gives you a reference to a SessionID. You could inspect the SessionID object inside onLogon to see how it behaves.
you can do it any of the quickfix methods after your session is created as the sesionId is one of the parameters.
The first method fired is onCreate so you can potentially store the sesionId in your class var and then reuse if if and when required to retrieve your settings. You can also use the onLogon method as suggested in one of the other answers.
Example below
def onCreate(self, sessionID):
self.session_id = sessionID
target = sessionID.getTargetCompID().getString()
sender = sessionID.getSenderCompID().getString()
It sounds like you're looking at the session directly after creating it, before logging on etc. So that means you're not using a breakpoint in, say, FromApp or ToApp to look at the session properties there. If you do, you get the properties directly i.e. SenderCompID, or TargetCompID.
I cannot find the method SessionID in the objects I use. How do you define your 'fix' object?
class ...
self.response.headers.add_header('Set-Cookie','user_id = %s'% id_and_hash)
self.redirect("/app/login")
class ThanksHandler(webapp2.RequestHandler):
def get(self):
if 'user_id' in self.request.cookies:
self.response.out.write('user_id')
else:
self.response.out.write("wrong") // what i am getting
and i have this cookie (I saw in a manager of cookies)
name: user_id
content: 30|a9bdc98e952c0e787aaf0e5466809eea71635d38446d30a9f71f2d15e99fa701
well, basically the problem is that i can't retrieve the cookie that has been initialized. Any reason for that?
When setting the cookie directly using the "Set-Cookie" HTTP-header you have to also take care of the cookie-attributes (depending on how you want to use the cookie).
In this case you set the cookie for example in the path /app/auth and then redirect to /app/login. If you don't explicit specify the cookie-path the browser assumes /app/auth and therefore the cookie is not sent when requesting /app/login. This behaviour is specified in the RFC 6265 (this is more recent than the one I cited in my comment but now the exact algorithm is included in section 5.1.4).
To set the path (or any other cookie-attribute) you can append a list of semicolon-delimited name=value pairs. In this case you want to set the path to / (it could be something different like /app):
self.response.headers.add_header('Set-Cookie','user_id=%s; Path=/'% id_and_hash)
Of course most libraries/frameworks already provide a wrapper for the "Set-Cookie" header. In the case of "webapp2" you can set the cookie with response.set_cookie:
self.response.set_cookie('user_id', id_and_hash)
It's automatically setting the path to / so you don't have to worry about it (it does escape the values properly too).
I used this library to make API requests and got the access tokens successfully.
But the documentation does not explain how _access_token and _access_token_secret should be used afterwards future. I suppose that there should be a method like:
set_access_token(_access_token, _access_token_secret)
but I could't find a method like that in this code or documentation.
Please help me to solve this problem.
I have not used this particular library or API, but a common pattern in these cases is that you pass the token as an argument to subsequent calls. Looking at the source, I can see a function called get_user_profile in __init__.py:
def get_user_profile(self, access_token, selectors=None, headers=None, **kwargs):
"""
Get a user profile. If keyword argument "id" is not supplied, this
returns the current user's profile, else it will return the profile of
the user whose id is specificed. The "selectors" keyword argument takes
a list of LinkedIn compatible field selectors.
"""
So I'd guess you just want to pass the token as the first argument (in this instance).