I have the following code:
app.js:
var passport = require('passport')
, FacebookStrategy = require('passport-facebook').Strategy
, ...
passport.serializeUser(function(user, done) {
console.log('serializing user')
done(null, user);
})
passport.deserializeUser(function(obj, done) {
console.log('deserializeUser')
done(null, obj)
})
passport.use(new FacebookStrategy({
clientID: FBAPP.id,
clientSecret: FBAPP.secret,
callbackURL:
"http://www.mylocal.com:3000/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
return done(null, profile)
})
}
))
app.get('/auth/facebook', passport.authenticate('facebook',
{ scope: ['email, user_likes, user_photos, publish_actions'] }))
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
successRedirect: '/loginsuccess', failureRedirect : '/loginfail' }))
app.get('loginsuccess', function(req, res) {
console.log('Login success')
res.send(200, 'ok')
})
app.get('/loginfail', function(req, res) {
console.log('Login error')
res.send(401, 'error')
})
The angular part:
factory('FacebookFactory', ['$http', '$q', function($http, $q) {
var get = function() {
var deferred = $q.defer();
$http({method: 'GET', url: '/auth/facebook'}).
success(function(data, status, headers, config) {
deferred.resolve(data);
}).
error(function(data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
return {
get: get
};
}])
I get always this error and did several attempts but no success.
XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?
response_type=code&redirect_uri=http%…
user_likes%2C%20user_photos%2C%20publish_actions&client_id=xxxxxxxxxxx.
No 'Access-Control-Allow-Origin' header
is present on the requested resource. Origin '[basic
links]http://www.mylocal.com:3000' is therefore
not allowed access.
Anyone any idea? I did try it solely in angular but then it does not work in Safari but in Chrome and FF it works perfectly.
www.mylocal.com:3000 = localhost:3000
You will not find a solution with client side languages as this constitutes a cross-origin request which could be used as a malicious attack. So basically the Facebook endpoint would need to have a Access-Control-Allow-Origin header block set and I don't think they will do that anytime soon. I use APIs alot and frequently have to have theses headers set in my endpoint so my clients can connect from localhost or dev urls:
if (isset($_SERVER['HTTP_ORIGIN'])):
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');
endif;
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS'):
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])):
header('Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE, PUT');
endif;
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])):
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
endif;
exit(0);
endif;
You could also try this in your $http broker:
var promise = $http({
method: 'POST',
url: 'url_to_api',
data: params,
headers: {
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json'
}
}).success(function (data, status, headers, config) {
return data;
});
I have an Angular app with express on the backend. When I clicked on a button with this HTML:
<input type="button" ng-click="socialLogIn('facebook')" class="modal-input" value="Sign in with Facebook">
It gave me a CORS error:
$scope.socialLogIn = function (social) {
return $http.get ('/auth/'+social).success (function (data) {
auth.saveToken (data.token); // write data to local storage
});
Problem is, I wanted to get the token back so I could save it in localStorage. I did solve it, but the solution is round-about. In the socialLogIn function, I opened a new window:
$scope.socialLogIn = function (social) {
var url = 'http://' + $window.location.host + '/auth/' + social;
$window.open(url);
};
In the express backend, after I got my 'stuff' from Facebook or Google and I created the token, I sent back some code that saved the token, reloaded the parent window and closed itself:
function loginReturn (res, token) {
var returnString = '' +
'<!DOCTYPE html>\n' +
'<html>\n' +
'<head>\n' +
'<meta charset="UTF-8">\n' +
'<title>Login</title>\n' +
'</head>\n' +
'<body>\n' +
'<script type="text/javascript">\n' +
'window.localStorage[\'token\'] = \''+token+'\';\n' +
'window.opener.location.reload(false);\n' +
'window.close();\n' +
'</script>\n' +
'</body>\n' +
'</html>';
res.send(returnString);
};
Related
This is my angular configuration for appending keycloak token with every HTTP request.
module.factory('authInterceptor', function($q, Auth) {
return {
request: function (config) {
var deferred = $q.defer();
if (Auth.authz.token) {
Auth.authz.updateToken(5).success(function() {
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + Auth.authz.token;
deferred.resolve(config);
}).error(function() {
deferred.reject('Failed to refresh token');
});
}
return deferred.promise;
}
};
});
module.config(["$httpProvider", function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
}]);
This is the request I sending to the backend. It seems the request not adding keycloak token, so I'm getting 403 forbidden error.
var formData = new FormData(file);
formData.append('file', file);
return $http({
method: 'POST',
url: API_BASE + '/uploadEmployeeDetails/excelUpload',
headers: {
'Content-Type': undefined
},
data: formData,
transformRequest: function(data, headersGetterFunction) {
return data;
}
});
Backend security config
Since you are able to send the token to the back-end as you can see from the network tab of the browser.
The issue is in the api side on handling the csrf token
If the csrf token is enabled by default you should disable it.
Here is the code with your help, to disable it
http.csrf().disable();
http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class)
.authorizeRequests().antMatchers("/**")
.hasAnyRole("ORG_ADMIN", "EMPLOYEE", "PARENT", "STUDENT")
.anyRequest().permitAll();
I want to get access token for authentication. My post result like
POST https://staj-io-goldenilkay92-1.c9.io/api/v1/oauth/token 401 (Unauthorized)
but when I try to post with postman it works.
Server Side Headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.header('Content-Type', 'application/json');
Angular Code
Service
function signIn(data) {
var deferred = $q.defer();
$http.post('https://staj-io-goldenilkay92-1.c9.io/api/v1/oauth/token', data,
{headers: {'Content-Type': 'application/x-www-form-urlencoded'}}
)
.success(function (response, status, headers, config) {
deferred.resolve(response);
}).error(function () {
deferred.reject("Failed to login");
});
return deferred.promise;
}
controller
vm.loginData = {
'client_id': 'client',
'client_secret': 'client',
'grant_type': 'password',
'username': '',
'password': ''
};
vm.login = function login() {
loginService.signIn(vm.loginData).then(function (result) {
vm.signInResult = result;
},
function (data) {
});
}
POST https://staj-io-goldenilkay92-1.c9.io/api/v1/oauth/token 401 (Unauthorized)
Here is suggestions to solve your problem;
Use cors module (not required);
Server Side
I assume that your passport code working properly.
var cors= require('cors');
//init first.
app.options(cors({origin'*'})); //Use your origins.
app.use(cors({origin'*'})); //Use your origins.
Client Side
Just delete headers options
//...
$http.post('https://staj-io-goldenilkay92-1.c9.io/api/v1/oauth/token', data)
.success(function (response, status, headers, config) {
deferred.resolve(response);
}).error(function () {
deferred.reject("Failed to login");
});
//...
If one POST works and the other doesn't, then your angularjs $http request is making the request with the wrong parameters.
I'd suggest you to get an http analyser (like Fiddler) and compare the actual request done by Postman vs the request done by you angular app.
Following is the code I use, I get the Authentication Success Alert if the basic auth succeeds but the else alert "Authentication failed" is never displayed when the credentials are wrong. I do not use any routes and I don't have a need to use interceptors. Is there a way to get the 401 errors without using interceptors?
this.authorize = function(request, callbackFunc) {
var encodedString = btoa(request.userName + ":" + request.password);
var basicAuthString = 'Basic ' + encodedString;
var requestObject = {
location: '40005'
};
var req = {
method: this.method,
crossDomain: true,
url: this.loginURL,
data: requestObject,
headers: {
'Authorization': basicAuthString,
'Content-Type': 'application/json',
'Accept': '*/*',
'apiKey': ''
}
};
$http(req)
.success(function(response) {
callbackFunc(response, "success");
})
.error(function(response) {
console.log("Error Received");
callbackFunc(response, "error");
});
};
In Controller:
$scope.Login = function() {
AuthenticationService.authorize($scope.LoginRequest, function(response, responseCode) {
if (responseCode === "success") {
alert("Authentication Success");
} else {
alert("Authentication Failed");
}
});
};
As described in the AngularJS documentation for $http, the $http call returns a promise with an error method, which has the code(number) of the status as one of it's parameters. You can check for a 401 status in there:
error(function(data, status, headers, config) {
if(status === 401){
// Add your code here
}
});
I have website where I'm trying to login over https with an AngularJS controller. Every time I try to log in I get a message like this
Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example.com/'. This request has been blocked; the content must be served over HTTPS."
The site is running on nginx configured to redirect everything to https.
Here is my controller code.
app.controller("LoginCtrl", function ($scope, $http, $window) {
$scope.formData = {};
$scope.remember_me = false;
$scope.doLogin = function(){
var xsrf = $scope.formData;
$http({
url: "/login",
method: "POST",
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
transformRequest: function(obj) {
var str = [];
for(var p in obj)
if (obj.hasOwnProperty(p)){
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
data: xsrf
}).success(function(data) {
if( $window.location.pathname == '/login') {
$window.location.href = '/';
}
else{
$window.location.reload();
}
});
}
$scope.doJsonLogin = function(){
var xsrf = $scope.formData;
$http.post('/', { 'u': $scope.formData.username, 'p': $scope.formData.password, 'c': $scope.remember_me }).success(function(data) {
if( $window.location.pathname == '/login') {
$window.location.href = '/';
}
else{
$window.location.reload();
}
}).error(function (data, status, headers, config) {
console.log(data);
console.log(status);
console.log(headers);
console.log(config);
alert("failed!");
});
}
});
My backend is running on Flask, and everything seems to be working properly on that part.
Currently it will stall like it failed, but when I reload the homepage it has me successfully logged in.
Why is AngularJS pushing XMLHttpRequest to http when everything was loaded through https, and how do I fix it so it works properly?
I just figured out my problem. In my backend Flask was previously setup to do the redirects itself upon success, which meant it wasn't properly returning a response to angularjs $http.post() that the login was successful. Once I rewrote my returns inside python to respond with json
return jsonify({'success': False, 'msg': "Username or Password is invalid"}) or
return jsonify({'success': True, 'msg': "Logged in successfully"}) the angularjs requests worked properly.
I am building my website with Angularjs and I am testing it with Node js and express. So, I am able to send a json item with information from the contact page form. But, I do not know How to return a success or fail code from Node.js to Angularjs to redirect to a thank you page. Also, I need to know how to send the information to my email and save it to a db and how to add a token for the form. I know that I'm using the MEAN stack. I learn better watch.
Here is my Node js:
var express = require('express');
var app = express();
var formidable = require('formidable');
app.use(express.static(__dirname + '/public')); // navigate to where the app reside
app.get('/', function (request, response) {
response.redirect('Index.html');
});
app.post('/Contact', function (request, response) {
var frm = new formidable.IncomingForm();
frm.parse(request, function(err, formData){
var Name = formData.Name,
Email= formData.Email,
Message = formData.Message;
response.writeHead(200, { "Content-Type": "application/json" });
response.end("{'status:' 200}");
});
});
var port = 8080;
app.listen(port);
console.log('Listening on port: ' + port);
and here is my Angularjs:
$scope.submit = function () {
console.log('Im in the controller');
console.log($scope.formData);
$http({
method : 'POST',
url : '/Contact',
data : $.param($scope.formData),
headers : { 'Content-Type': 'application/json' }
}).success(function(result, status, headers, config) {
console.log(result);
if(result.status == "???"){
redirectTo: '/Thnkyu';
}
}).error(function(result, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log(result);
});
}
When I submit the form; the console showed: TypeError: Cannot read property 'protocol' of undefined Before it showed: ERR_CONNECTION_REFUSED because I had the url portion before I setted the headers and data.
The problem was I use the angularJs $http dependence as shown above; but, it did not work. So, I use the $http dependence like so:
$scope.submit = function () {
console.log($scope.formData);
$http.post("/contact", $scope.formData)
.success(function(reponse){
if(reponse.status == 200)
console.log('im in')
$location.path('/thnkyu');
});
and the response from the server is like this:
...
if(!eor){
console.log(eor);
response.json({status: 200});
}