I'm trying to create a simple method to restrict access to data based upon the domain from which an HTTP request originates (i.e. CORS basically).
To give some brief background: (I'm using latest Laravel 4) - In this app, data is used off-site by customers. I want to give the customers the ability to restrict HTTP requests to access that data based upon the origin. So that only requests from their website can access that data via the API.
i.e. for arguments sake: imagine a script on http://mycustomer.com makes an Ajax call to http://myapp.com/api/customers_data --- I want to only allow requests from http://mycustomer.com, and deny all others.
Relevant code I've currently got:
// i.e. 'http://mycustomer.com';
$allow_domain = User::settings->domain;
$headers = array(
'Access-Control-Allow-Origin' => $allow_domain,
);
return Response::make($JSON_data, 200, $headers);
But this doesn't seem to be working to deny requests originating from other domains.
Can anyone help me out?
Solved: To answer this question, after many hours of hair-pulling it was the classic "output before sending headers" issue". I was error logging one of my utility functions, which was outputting pre-header.
Also, as a note, if anyone has a similar issue: there is no suffix backslash on the allowed domain. i.e. 'http://allow.com/' fails, but 'http://allow.com' works.
Related
I made a node application based on storefront API of shopify. However there are rate limit per ip address imposed. Due to this I can execute certain Graphql queries a set amount of time. For example, password reset only works 2 times and after that it show Limit Exceeded error, after which I need to wait for 60 seconds.
The issue is I have deployed application as lambda function and the IP will always be the same. I found the solution on storefront API stating I need to use delegate token and user IP to as header while sending the request. But I did not quite understand.
Can someone please help me how should I use delegate token in my node application, so that the whenever a request is sent it uses the client browser IP instead of the AWS server!
Ok, believe I figured it out.
First thing you to do is create a delegate token using this endpoint (POST).
https://{{shopify_store_name}}.myshopify.com/admin/access_tokens/delegate.json
Your POST should look something like this:
{
"delegate_access_scope": ["unauthenticated_write_checkouts"]
}
I suggest you go into your shopify store front API and view which permissions the storefront API has and use something similar. Note that your admin API needs to at least have those permissions to grant them.
Also note that the customerRecover needs the "unauthenticated_write_checkouts" permission to be called.
After you created that token (And this was the problem I had) REMOVE the X-Shopify-Storefront-Access-Token from your header, and REPLACE it with Shopify-Storefront-Private-Token
Remove:
X-Shopify-Storefront-Access-Token : {{{Storefront Token}}}
and Replace with:
Shopify-Storefront-Private-Token : {{{Your delegate token}}}
You will also need to forward your customers API address in the header by grabbing it out of the context and putting into the header as well
Shopify-Storefront-Buyer-IP' : this.sourceIp
After I did this, I noticed my rate limiting on forgot password was IP based on the client hitting it and not the servers IP being throttled.
Hope this helps!
I want to retrieve data from a data warehouse that has a web-based API, I need to use an API key for authentication and use the GET / Customers command to retrieve the list of customers data, but when I am using that same thing in postman, it's returning the same documentation page of the data warehouse?
I am new to this any help will be really appreciated.
The URL doesn't look valid:
You need a base URL, endpoint, http method, authentication scheme, and credential or a token etc.
I don't know details about your system and API, so let's see an example:
base url is https://stackoverflow.com; your current base url is localhost:4444, is your server running on your machine? If so, it might be correct, but I assumer you're talking about a server running somewhere else, not on your computer
endpoint (path parameter) is /questions/69883697, in your case /customers
http method is GET and you find it here in Postman; it also means it will not go into query parameters where you put it:
authentication scheme - your docs mentions an api key that goes into a header called Authorization, so you have to set it in Headers, not as a query parameter:
Read carefully what's on your screen, Postman uses the same language as your API documentation, so if your doc speaks about headers, you need to go into Headers tab in Postman.
I am trying to write a python script that collects messages from Stocktwits.
I managed to successfully access the API, with
params = {
'client_id':'my_consumer_key_here',
'response_type':'code',
'redirect_uri':'https://api.stocktwits.com/api/2/oauth/authorize',
'scope':['read','watch_lists'],
'prompt':1,
}
r = requests.get('https://api.stocktwits.com/api/2/oauth/authorize',params)
r.status_code # 200
The messages should be accessed via a watchlist (which I created on my account), like this
r = requests.get('https://api.stocktwits.com/api/2/streams/watchlist/<watchlist_id>.json',params)
To get at the watchlist-id, which I couldn't find on my account, I tried:
r = requests.get('https://api.stocktwits.com/api/2/watchlists.json',params)
r.status_code # 401
This should list the watchlists and their IDs. The '401' indicates that authorization for some reason doesn't work here the same way as above.
I changed the redirect_uri to 'https://api.stocktwits.com/api/2/watchlists.json' as well, frankly I'm not sure what it's good for.
The problem is likely that the authorization process is geared towards having many possible users accessing my app and via my app the API. What I want to do is much simpler.
I have never worked with an API before and most of the documentation is pretty opaque to me. So my question is whether I'm doing something obviously wrong and how I should proceed to get the watchlist_id and retrieve the messages.
You should add access token to your requests for secured resources like
https://api.stocktwits.com/api/2/streams/watchlists.json?access_token=<access_token>
or instead of this you can add authorization header to each request to protected resources.
And access_token you should get from your authorize request
r = requests.get('https://api.stocktwits.com/api/2/oauth/authorize',params)
I'm kind of surprised that, after searching for this for a while, I didn't find as many answers as I thought would be out there (well I found none), so maybe by asking it here we can help improve search results.
I'm building a REST api which has JWT-based authentication. There is an /auth/login route which returns the token after login/password verification, and the token is subsequently sent in every route in a Authorization http header.
Not, suppose that someone queries another route (say, /cars), without sending the token (that is, before logging in). If I return a 401 unauthorized, I can make the frontend query /auth/login to get the token.
But, strictly speaking, this does not conform to the REST specification, because every resource should be discoverable from the initial one, and a client accessing /cars and receiving a 401 will not know about /auth/login.
So another option would be a redirection like 302. But this semantics means that the resource was temporarily moved, and this is not the case (the resource is still /cars, you just need to authenticate first).
So, what is the correct way to do this procedure in a "true" rest api?
I 100% agree, and that's why I proposed this standard:
https://datatracker.ietf.org/doc/html/draft-pot-authentication-link-01
The idea is that for cases like this, you should be able to return a Link header with an authentication rel, so the client can discover how to proceed.
I know there is enough content for this question on the Stack Overflow but my subject is not the same as the others. ( Kinda the same but not equal )
I want to hear the community thoughts of what I doing and to see if I can improve somewhere or not.
I'm currently using BASIC Authorization for my login EndPoint as it doesn't require complexity and its over https so its fine the way it is.
Example:
GET - /api/login
Authorization : Basic BASE64String(username:password)
Some of my EndPoints require Tokens to be granted access to the resource. These Tokens I'm sending trough Headers and Https-Secured.
The thing is I'm not using a conventional method of doing these Authorizations. Some examples below:
Example 1:
GET - /api/hardware/{PUBLIC_TOKEN}/getMe
Authorization-Hardware : PRIVATE_TOKEN
This EndPoint doesn't require the Authorization-Hardware Header, but if included more things are done by the API. ( Not relevant here )
Example 2:
GET - /api/login/{id}
Authorization-Person : USER_TOKEN
This EndPoint otherwise is necessary including the Authorization-Person Header with the User Token to access the resource. ( Note that how the Token is generated is irrelevant here )
To access the API EndPoints an HTTPS request is necessary.
I gave arbitrary names to the Custom Headers and EndPoints above just to give a picture of what my Authorization Schema is, the names doesn't match the original ones. So don't bother the names just foccus on the schema.
My question is: Not following the convetional way is such a bad thing ? Creating Custom Authorization Headers is bad somehow ( if it is why ? ).
I find this way simpler to give Authorization and a secure way of passing tokens, all these Tokens can be re-generated in the platform again.
Lots of devices and a Mobile Application is already using this Schema, but its all under Development Environment and its not in Production yet. My fear is that this non-conventional way of doing this can affect users of the API in the future. Hope the community thoughts can help me to improve this.
EDIT: 26/03/2017
I would like to know if it would be better and why implementing in the way that is described in the protocol, as its harder to fetch from the Headers when multiple Authorizations is required than when you have a Custom Header and wants to retrieve its value.
Following the Protocol you should use Authorization Header like this:
Authorization: <type> <value>
Example:
GET - /api/login/{id}
Authorization : User USER_TOKEN
But I just can't see what I gain following this, because when fetching its value would come a String or in the example case it would return User Token.
Using an Custom Header its way easier validating the Token. Multiple Authorizations can give a headache too following the protocol way.
TL;DR Some header names such as Authorization have special rules about caching as well as proxy & client handling; your custom header names would not get the special behavior unless you modified every single proxy & client.
The point of using the common Authorization: <type> <value> header as defined in RFC7234 is mostly to ensure that clients & HTTP proxies that natively implement handling of those headers behave CORRECTLY.
Section 4.2 of RFC7234 says:
A proxy forwarding a request MUST NOT modify any Authorization fields
in that request. See Section 3.2 of [RFC7234] for details of and
requirements pertaining to handling of the Authorization field by
HTTP caches.
The Proxy may modify, omit, log or cache your other Authorization-* headers.
RFC7234, section 3.2 says that requests/responses Authorization header MUST not be cached (except in specific circumstances).
RFC7235, section 5.1.2, point 7 furthermore has this say to about NEW authentication schemes that use headers other than Authorization:
Therefore, new authentication schemes that choose not to carry credentials in the Authorization header field (e.g., using a newly defined header field) will need to explicitly disallow caching, by mandating the use of either Cache-Control request directives (e.g., "no-store", Section 5.2.1.5 of [RFC7234]) or response directives (e.g., "private").
So what should you do...? If you controller both ends of the system entirely, it's not unreasonable to define a new type value that might have multiple parameters to cover any combination of one or more token types, just avoiding the , character:
Authorization: MyAuth User=USER_TOKEN/Hardware=HWTOKEN/Person=PERSONTOKEN/Basic=...
The alternative depends on server & client implementations more, and would be using a , as the alternate version list form of multiple headers:
Authorization: User USER_TOKEN, Hardware=HWTOKEN, Person=PERSONTOKEN, Basic=...
Which depending on the server & client, may be treated the same as:
Authorization: User USER_TOKEN
Authorization: Hardware HWTOKEN
Authorization: Person PERSONTOKEN
Authorization: Basic ...
The problem here is "MAY" (lots of added emphasis) be treated the same. There's discussions suggestion that various versions of Apache & NGINX don't treat this consistently, and that the older HTTP RFCs are very unclear about the intended behavior.