I never built a REST API, so,
My idea is: I have an SQL database that has a table with name and description (for this example it is car name and its description is somewhat simple) I want to create a REST API, and thus be able to consume it in any future application. I thought I would do it in php, now my question is for me to be able to access this rest api I must access using url and this will return the results in json form. But as it is done so that only my website can use it (in this example I am developing it in reactjs) and not any other that does not have authorization. I know something about JWT, but I do not know if it is indicated, this web page has no users, it only serves for you to see these "products", I read something about oauth 2.0, I do not know if this is what I am thinking of.
https://blog.restcase.com/4-most-used-rest-api-authentication-methods/
Basic Authentication is probably the easiest. Just google PHP Basic Authentication REST API implementation
There's a very basic old example on php.net in the comments https://www.php.net/manual/en/features.http-auth.php
<?php
$valid_passwords = array ("mario" => "carbonell");
$valid_users = array_keys($valid_passwords);
$user = $_SERVER['PHP_AUTH_USER'];
$pass = $_SERVER['PHP_AUTH_PW'];
$validated = (in_array($user, $valid_users)) && ($pass == $valid_passwords[$user]);
if (!$validated) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
die ("Not authorized");
}
// If arrives here, is a valid user.
echo "<p>Welcome $user.</p>";
echo "<p>Congratulation, you are into the system.</p>";
?>
But the above is not using a database to store user login/hashed password, it's just storing it in an array. But it would be very quick to prototype your authentication before making something a bit more complicated
Here's another basic example along the same lines
https://gist.github.com/rchrd2/c94eb4701da57ce9a0ad4d2b00794131
So with this setup, if you're sending a GET request to your REST API endpoints to get the json, you would also need to include the username/pass in the Http request headers otherwise you would get the 401 not authorized response instead of the JSON.
See the answer here for how you would code the GET request from your PHP to call the REST endpoint
How do I make a request using HTTP basic authentication with PHP curl? or here also has a good example PHP: how to make a GET request with HTTP-Basic authentication
Related
Not sure if the title summarises my question well.
Basically, I am trying to authenticate routes such as checking if user exists etc. I only want to allow
requests coming from my frontend application to be approved, but, since no user is signed in there is no token to send.
Api request -
mywebiste/checkUser/email
This route is unprotected on my backend because no user is logged in.
BUT I want to protect this route, in such a way that it's accessible only from the frontend.
Some ideas I came up with were adding specific headers tag from the frontend and check them on the backend, but that could be easily replicated, is there something more secure like using tokens etc.
I am using React and Node.js
Same origin policy is going to give you some basic protection, but basically if an API endpoint is exposed publicly, it's exposed publicly. If you don't want that route to be publicly accessible you need to add access control.
If you use that route to check if a user is already registered, you could, for example, merge it with the user registration route and send a different error code if the user already exists (which is not a great idea because it leaks which emails are registered on your system).
You can verify that a request was originated by a user (by authenticating him) but you cannot verify that a request comes from a particular client because of these two reasons :
If you include some API key in your client (web page or other), it's easily retrievable by everyone (the best thing you could do is offuscate it which makes things slightly harder but still possible)
If you send an API key over the network it's easily retrievable as well
The only thing you could do is prevent other web pages from calling your backend on behalf of the user, by using CORS (which is actually active by default if you dont specify an Access-Control-Allow-Origin header)
I ended up creating a kind of working solution, so basically, I create a new base64 string on my frontend and attach that to the header while making a request to the backend. The base64 string is different every minute, so even if the header is copied, it differs every minute and is combined with your secret key.
I have made a package so that people can use it if they want - https://github.com/dhiraj1site/ncrypter
You can use it like so
var ncrypter = require('ncrypter');
//use encode on your frontend with number of seconds and secret key
var encodedString = ncrypter.encrypt(2, 'mysecret1')
//use decode on your backend with same seconds and secret
var decodedString = ncrypter.decrypt(encodedString, 2, 'mysecret1');
console.log('permission granted -->', decodedString);
I have been trying to get refresh token from google api using javascript google client " code " that google return from client side. It returns me the code which i send to the server side. Now from server side i am sending the code to get the refresh token and access token using using google-api-php-client with this call :
https://www.googleapis.com/oauth2/v4/token
While i use the same code from google playground i get the response with refresh token as well but i do not get it from my own server..
This is the code
public function getRefreshToken($code)
{
$client = new Google_Client();
$client->setClientId(config('services.google.client_id'));
$client->setClientSecret(config('services.google.client_secret'));
$client->setRedirectUri('postmessage');
$client->setScopes(config('services.google.scopes'));
$client->setAccessType("offline");
$client->setApprovalPrompt("force");
dd($client->authenticate($code));
dd($client->getRefreshToken());
return ;
}
I have set access type to offline as mentioned in some answers but still i get the response with our refresh token.. this is the response
access_token :"xxxxxxxxxxxxxxxxxxxxxx"
created:1510242052
expires_in:3598
id_token:"xxxxxxxx"
token_type:"Bearer"
Your php code looks fine to me. I suspect your front end javascript, specifically the link to google that it builds, may be to blame. Whether the authorization_code produces a refresh token when redeemed is partially dependent on what parameters are included in the initial link to Google.
As detailed in this answer, the javascript client library uses "client side flow". Normally in a front end app you'd specify response_type=token, but if you specify response_type=code, instead, you'll get a code back. But when redeemed, that code will not produce a refresh token.
For example, a link built by a front end javascript library might look like this:
https://accounts.google.com/o/oauth2/v2/auth?client_id=7xxxxxxxxxxx-xxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=http://localhost:8080/oauth2callback.php&response_type=code&scope=profile
Your back end can redeem the code that comes back, but the response will not include a refresh token. This is by design.
One way to get a code that is eligible for refresh tokens, would be to use the back end PHP client library to build the link, rather than the javascript client library. $client->createAuthUrl() will build a link like this:
https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=offline&client_id=7xxxxxxxxxx-hxxxxxxxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Foauth2callback.php&state&scope=profile&approval_prompt=force
This toy example builds the link this way and does receive refresh tokens.
Note the addition of access_type=offine and approval_prompt=force. After successful authentication, the redirect in this case includes a code that does provide a refresh token when redeemed.
The OAuth 2.0 playground builds an initial link that contains access_type=offline and prompt=consent, which also creates a code that is redeemable for a refresh token.
If this isn't helpful, perhaps you could update the question with the link to google that your front end is building? (With client id redacted, of course)
All I found was with php and node.js (which is based on js, so it should be fine), but I got across this library:
<script type="text/javascript"
src="//media.twiliocdn.com/sdk/js/client/v1.4/twilio.min.js"></script>
What is the relavant JS code to make a "send sms" request?
This is the php I found:
<?php
require __DIR__ . '/twilio-php-master/Twilio/autoload.php';
use Twilio\Rest\Client;
$client = new Client($sid, $token);
$client->messages->create(
'+15558675309', // number to send to
array(
'from' => '+15017250604', // your Twilio number
'body' => "There’s something strange in my neighborhood. I don’t know who to call. Send help!"
)
);
Thanks.
Twilio developer evangelist here.
We don't recommend that you use the Twilio REST API for sending SMS messages within a public HTML page. If you do so, you will expose your account credentials publicly and a malicious attacker could steal them and send messages or phone calls on your behalf, using up your credit and potentially spamming people.
The JavaScript library you found there is for you to use to make phone calls from within the browser using WebRTC. This is built to not leak your credentials as you need to generate a token server side that can be used to authenticate users.
I recommend you check out the SMS quick start guides in a language of your choice to see how you can write server side code to send messages.
I am creating a SPA blog website with PHP/MySQL and a Javascript frameworks, still haven't decided which one yet.
The idea is that I am willing to create an API and consume it using Javascript, but I want to protect the API, so that no one can access /posts/ for example and get a list of all the posts.
I am not requiring any registration and I don't have a users system.
How would I go about it?
Thanks
You might be able to hard code whitelisted IP addresses, but as Steve pointed out in the comments: it's either public or it's not.
I'd go with some little registration functionality that generates API-keys that can be used to access your API.
It has been pointed out that a public API is public, however there are some steps that could take to make it more difficult for consumers other than your UI to access it.
The problem is akin (though not the same as) Cross Site Request Forgery, and you can use a variation of any of the prevention techniques listed to mitigate unauthorized access to your API.
The simplest implementation might be something like this:
index.html
<?php
$mytoken = uniqid();
$_SESSION['token'] = $mytoken;
?>
<input type='hidden' name='apitoken' value='<?= $mytoken;?>' >
some-api-endpoint.php
<?php
if($_GET['apitoken'] !== $_SESSION['token']) {
header("HTTP/1.0 403 Forbidden", true, 403);
}
If someone wants to access your public API, they will be able to, but they will have to put forth at least a little bit of effort to do so.
Using a JWT service will work just as well.
Have a look here: introduction to JWT
You can also use an api key and secret which will be passed on initial session auth for your service.
Here's a Stackoverflow answer that helps explain what you'll need to do: key and secret in php
If you're really lazy, you can just use basic authentication or digest auth to auth on the client side. (This is not advisable and has security risks as if you're not using ssl the passwords are passed as plain text in the request)
Another article for your information: PHP HTTP Authentication
I need to retrieve a facebook page's list of posts (feed) using their javascript SDK, just like they explain in their docs: https://developers.facebook.com/docs/graph-api/reference/v2.4/page/feed
/* make the API call */
FB.api(
"/{page-id}/posts",
function (response) {
if (response && !response.error) {
/* handle the result */
}
}
);
I need it to be my website's "news section", so users should see it even if they are not connected to facebook.
The problem
Cool, but there is a problem... It returns: An access token is required to request this resource.
Holy cow... I'd like to get some access token for you #facebook, but my app doesn't make use of your authentication tools/plugins.
ANYWAY, I tried with FB.getLoginStatus(); but doesn't work, because the only way it can return an access_token is if the user is actually connected to the application. My users may not even be logged to facebook!
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
I've already payed a look to this SO question, but it doesn't solves my problem, simply because there are no such "generic tokens".
I've also read https://developers.facebook.com/docs/facebook-login/access-tokens/ and that also relies on tokens generated through facebook login methods... So, can't I display a list of fb page's posts in my website, without being connected into facebook, hence an application?
ADD: My app is build with angularJS, I'm not dealing with server-side code. I shall rely purely on javascript methods.
You could either use an page or an app access token, but as you'd be using them on the client-side, neither of them are an option.
See
https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens
https://developers.facebook.com/docs/facebook-login/access-tokens#pagetokens
Note that because this request uses your app secret, it must never be made in client-side code or in an app binary that could be decompiled. It is important that your app secret is never shared with anyone. Therefore, this API call should only be made using server-side code.
I'd strongly recommend to build a simple server-side script (PHP for example) to proxy the request to the Graph API. You could then call this via AJAX for example and load the posts asynchronously (and alse get rid of the FB JS SDK!). There is NO way to handle this in a secure manner if you don't want to use FB Login for all of your users (which also doesn't make much sense IMHO).
I think it's straightforward :)
Since pages' posts are always public, it only needs a valid access token to retrieve page posts.
Quoting what you've written:
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
You only require an access token.
My suggestion would be;
- Generate an access token for yourself (no extra permission needed)
- request page-id/posts
This way you don't require other users to be connected to facebook, you can simply requests page-id/posts to retrieve posts with access token you generated for yourself.
I hope it solves your problem :D
TIP: As long as posts are public, you only require a valid access token, it doesn't need to be user or page specific.