I'm developing a web application that uses the Twitter API REST. I have a page with Twitter accounts and a button for adding a new account. When the button is pressed, the function in the Angular controller is executed:
// Calls token to add a new Twitter user
$scope.callToken = function () {
$http.get('/token')
.then(function (response) {
console.log(response);
});
};
This is the code in the backend to serve de request. It simply redirects to Twitter to add a new user.
// routes.js
var token = express.Router();
token.route('/token')
.get(cuentasCtrl.getToken);
// Account file
exports.getToken = function(req, res) {
twitter.getRequestToken(function(err, requestToken, requestSecret) {
if (err)
res.status(500).send(err);
else {
_requestSecret = requestSecret;
res.setHeader('Access-Control-Allow-Origin', '*');
res.redirect("https://api.twitter.com/oauth/authenticate?oauth_token=" + requestToken);
}
});
};
But I get the next error:
Origin 'http://localhost:3000' is therefore not allowed access Twitter API
My server is running on localhost:3000 and If I put localhost:3000/token in my browser there is no problem. I have read the solutions for using CORS and tested other browsers but it hasn't worked for me. What have i done wrong?
The redirect you are sending in your express response is caught by the http client you use in the frontend and the redirect happens there. You are in a classical CORS situation and of course this is not how you can interact with the Twitter rest APIs.
You have to make http calls to Twitter on the node side (server to server) or use a client side client library for Twitter (https://dev.twitter.com/web/javascript)
Related
I'm trying to create a gallery in React with life previews of many websites (like a portfolio) all the linked websites belong to me as well.
I already try to use iFrame and embed but I didn't have the result I would like, I'm trying to get a miniature website like in here https://codesandbox.io/explore.
Even tho the website show the thumbnails as images if you update your sandbox it will the images will update too.
I try use iFrame and embed but it does not show a small version of the website but the website as a mobile and just the frame size.
Any ideas in how I could generate such images or solve this problem in some other way?
You cant do this on the front end in a webpage. You need to execute something like puppeteer on your backend to screenshot the pages. An example can be found on
https://bitsofco.de/using-a-headless-browser-to-capture-page-screenshots/
As of the the same-origin policy, browsers do not allow you to make request to a different domain, you cannot request a different domain from your web app.
The Cross-Origin Resource Sharing standard works by adding new HTTP headers that let servers describe which origins are permitted to read that information from a web browser.
As of an alternative solution you can setup an express server and use cors package to add permission for sending request to your other site.
If you control both sites, then config Cross-Origin Resource Sharing (CORS) from server settings by adding new HTTP headers like Access-Control-Allow-Origin to be accept requests from your other servers
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
const whitelist = ['http://example1.com', 'http://example2.com']
const corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
}
app.listen(4000, function () {
console.log('CORS-enabled web server listening on port 4000')
})
There is also a library that captures screenshot of the given url and save it to the given outputFilePath, capture-website, you can use.
I'm using ExpressJs for backend and ReactJS for frontend. The server is running on localhost:3000, the client is runnning on localhost:8080. I want to redirect user to Chat page after they have successfully logged in. So I have the code in server:
(req, res) => {
//doing some authenticate actions up here
if (/*successful*/) {
//some actions here
res.redirect("/chat");
}
//actions on failure down here
};
But after logging in to the account, I get this error
GET http://localhost:8080/chat 404 (Not Found)
The http://localhost:8080/chat is exists and it is handled by client-side, if I type it in address bar and go, I still can access the Chat page.
I also have the code that handles any request not matching server routes, so that request can be sent to client for handling:
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client/dist/index.html"));
});
What is wrong with my code? Did I miss something?
You should redirect the user after a successful response from the API. It is not better handled by the back-end because you have a single page application, which technically has no additional pages that the server is aware of, which is why you are getting the 404 error when trying to redirect to http://localhost:8080/chat. It is only aware of your index.html file which serves your bundles react code. The reason you are able to type in /chat into the address bar is because your UI is set up to handle requests from the router you are using. It is not the server directing you there.
It should be simple, here's an example:
logUserIn = async (userData) => {
const isAuthed = await authenticateUser(userData)
if (isAuthed) {
this.props.history.push('/chat');
} else {
console.log('User not found!');
}
}
I'm using the adal-angular library (but not with Angular) in my SPA to try to acquire an access token that I can use to call the SharePoint APIs (https://<my-tenant>.sharepoint.com/_api/).
I've registered an application in Azure AD and enabled the implicit flow in the manifest, and I'm now running my SPA locally, which is why there's a localhost redirect URI. The code below is being executed on startup:
const context = new AuthenticationContext({
clientId: '<my-client-id>',
redirectUri: 'http://localhost:3000/signin',
popUp: true,
loginResource: 'https://<my-tenant>.sharepoint.com',
callback: () => window.location.reload()
});
const user = context.getCachedUser();
if (!user) {
context.login();
} else {
context.acquireToken('https://<my-tenant>.sharepoint.com', (error, token) => {
console.log(error, token);
});
}
I'm already logged into the SharePoint site, so with this config everything happens automatically and I see a JWT access token logged to the console. However, when I inspect the token, I see that the audience is <my-client-id>. When making a call to https://<my-tenant>.sharepoint.com/_api/v1.0/me using the access token, I then get a 401 response with the following error message:
{"error_description": "Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}
I'm pretty sure this all boils down to me not understanding the OAuth2 flow properly, but... how can I acquire a token that SharePoint can actually be used with SharePoint? Am I thinking about this the wrong way? It kinda defeats the purpose if the token retrieved by my app can only be used to authenticate against my own app.
Getting an access token to SharePoint is well described here:
OneDrive for Business authentication and sign in
You should consider first getting a token to the Discovery Endpoint:
Using an access token received for resource
https://api.office.com/discovery/ you can make a request to the
discovery API to learn which services are available
If the call is successful, the response body contains JSON data with
information about the services available for the user and your app.
{
"#odata.context": "https:\/\/api.office.com\/discovery\/v1.0\/me\/$metadata#allServices",
"value": [
{
"#odata.type": "#Microsoft.DiscoveryServices.ServiceInfo",
"capability": "MyFiles",
"serviceApiVersion": "v2.0",
"serviceEndpointUri": "https:\/\/contoso-my.sharepoint.com\/_api\/v2.0",
"serviceResourceId": "https:\/\/contoso-my.sharepoint.com\/"
}
]
}
There you should get your valid Resource ID... but the issue here may just be that you did not include a forwardslash (/) at the end of the Resource URL in your sample code.
I am trying to integrate facebook login for my app in nodejs, angularjs using passport-facebook module.
I can intergrate facebook authentication without angularjs, but when i use angular http.get('/auth/facebook')
i am getting below error
XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%…%2Flocalhost%3A1439%2Fauth%2Ffacebook%2Fcallback&client_id=xxxxxxxx. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:1439' is therefore not allowed access.
app.js:153 err
Below is my angular code
var headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Content-Type': 'text/html'
};
$scope.fblogin=function(){
// $window.location.href='/auth/facebook';
$http({
url:'/auth/facebook',
method:'GET',
headers: headers
}).success(function(data){
console.log(data);
}).error(function(){
console.log('err');
});
};
pp.config(['$routeProvider','$httpProvider',
function($routeProvider,$httpProvider) {
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.common = 'Content-Type: application/json';
delete $httpProvider.defaults.headers.common['X-Requested-With'];
NodeJs
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
**Note:**I have tried changing multiple header changes for $http.get()
Solution:
The link https://www.facebook.com/dialog/oauth?... is not designed for calling it as ajax because it must REDIRECT user to facebook login page (so when you call it by ajax then redirect is impossible).
Instead of make ajax request just prepare in html proper element:
<a href="https://www.facebook.com/dialog/oauth?..." > ... </>
This works :)
This is what I have done to avoid Angular to call facebook auth dialogue API as AJAX request.
Use 'window.location="http://localhost:3000/auth/facebook"'; in your Angular Controller Function from where you send the request to your Express Server which contains passport.authenticate stuff.
Example:
$scope.authFacebook = function() { window.location="http://localhost:3000/facebook" }
You are attempting to make an ajax call to a URL and the browser is rejecting that ajax request because of cross origin security.
There are several possible reasons for this:
The domain of that URL doesn't allow cross origin requests.
You aren't making the request in a proper way for the cross origin request to succeed.
Your request is not formed properly (either targeted at the right URL or sent with the right options).
FYI, your node.js code where you set the allow-origin headers has absolutely nothing to do with the browser code attempting to send an ajax call to Facebook. That code would allow other people's web sites to make cross origin requests to your node.js server.
One thing that is a bit confusing about what you posted is that the URL of the $http() call you show is not the same URL as you are getting in the error message so I'm wondering if you're looking at the wrong code for the error.
This solution works for me, adding to cors to express app
var cors = require('cors')
var app = express()
app.use(cors())
I have a web app that allows people to generate a list of songs by artists that are related to a particular artist. I want to be able to connect to the user's Spotify account and create a playlist for them from that list of songs, but I need to get an access token. I have a developer account and client ID and am trying to work through the Authorization Flow, but it's not working for me. Instead, I get this error: XMLHttpRequest cannot load https://accounts.spotify.com/authorize/?client_id=d137fe25b31c4f3ba9e29d85f…:3000/callback&scope=user-read-private%20user-read-email&state=34fFs29kd09. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
This is a portion of my scripts.js file (i'm using the spotify-web-api-js node module):
$('#spotify').on('click', function() {
$.support.cors = true;
$.getJSON("https://accounts.spotify.com/authorize/?client_id=d137fe25b31c4f3ba9e29d85f4e47c66&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&scope=user-read-private%20user-read-email&state=34fFs29kd09", function(json2){
$.getJSON("https://accounts.spotify.com/api/token/?grant_type=authorization_code&code=" + json2.code + "&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&client_id=d137fe25b31c4f3ba9e29d85f4e47c66&client_secret={...}", function(json3) {
s.setAccessToken(json3.access_token);
});
});
});
});
According to my research, it's a CORS-related issue. I'm making edits to my ExpressJS server to remedy this cross-origin problem and installed the cors node module, but I'm still getting the same error.
index.js server:
var express = require('express');
var cors = require('cors');
var app = express();
var port = 3000;
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(express.static(__dirname + '/public')); // looks in public directory, not root directory (protects files)
app.get('/', function(req, res) {
res.send(__dirname + '\\index.html')
});
app.listen(port, function() {
console.log('CORS-enabled web server listening on port ' + port);
});
When I go to the URL in question directly through my browser, it gives me the expected "Do you authorize this app to use your Spotify information" form.
Should I require 'cors' in 'scripts.js' for it to work? Does anyone have any other suggestions?
I believe the issue here is that you're attempting to retrieve JSON data from the endpoint where you should direct your users. So instead of making a request to it, you should supply a button on your page that links to your https://accounts.spotify.com/authorize/{...} URL. The user will proceed to give your application the permissions you've requested as specified in the scope parameter, and will be directed back to the URL you've specified in the redirect_uri parameter. This is where you get the authorization code, which you can use in the https://accounts.spotify.com/api/token/{...} endpoint. Read more about the Authorization Code flow in the Authorization Guide.
Spotify Web API support three different oAuth flows, and you might be interested in Implicit Grant. Examples of all of these flows written in Javascript using Node is available at https://github.com/spotify/web-api-auth-examples.