I am building a mobile app that connects to my grails app that uses spring security core.
Im building the app in titanium studio.
How do i check it the user has an open session on the mobile app.
I log in using the with the following code:
var xhr = Ti.Network.createHTTPClient();
var url = "http://localhost:8080/FYP/j_spring_security_check";
var postData = "";
postData += 'j_username=' + usernameField.value;
postData += '&j_password=' + passwordField.value;
postData += '&_spring_security_remember_me=on';
Ti.API.debug(url);
xhr.open("POST", url);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
xhr.onload = function() {
var response = JSON.parse(xhr.responseText);
win.close({animate:true});
slidingMenu.open({animate:true});
if( response.error ){
alert( response.error );
} else {
//logged in now do something
}
};
xhr.onerror = function(){
Ti.API.error( "Error Logging in" );
};
xhr.send(postData);
But how would i check if the user has already logged in?
Make a custom method in grails using
springsecurityservice.isLoggedIn()
and do a GET request :)
I simply use an application level variable. It situations when I need to protect data, I always pass the username and password I stored to the server so it has to authenticate every time.
Related
I'm trying to make real time application with node.js and socket.io. As I can see the server can see when new user connects but can't return information to client side or something. This is what I've on client side:
<script src="<?= base_url('assets/js/socket.io.js') ?>"></script>
<script>
var socket;
socket = io('http://***.***.***.***:3030', {query: "key=key"});
socket.on('connect', function (data) {
console.log('Client side successfully connected with APP.');
});
socket.on('error', function (err) {
console.log('Error: ' + err);
});
</script>
and this is the server side:
var app = require("express")();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
http.listen(3030, function () {
globals.debug('Server is running on port: 3030', 'success');
});
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('www.****.com' == domain) {
globals.debug('New user connected', 'warning');
} else {
globals.debug('Bad site authentication data, chat will be disabled.', 'danger');
return accept('Bad site authentication data, chat will be disabled.', false);
}
});
io.use(function (sock, next) {
var handshakeData = sock.request;
var userToken = handshakeData._query.key;
console.log('The user ' + sock.id + ' has connected');
next(null, true);
});
and when someone comes to website I'm expecting to see in console output "New user connected" and I see it: screen shot and the user should see on the browser console output: "Client side successfully connected with APP." but I doesn't show. Also I tried to emit data to user but it doesn't work too. I can't see any errors or something. This is not the first time I'm working with sockets but the first time facing such as problem. Maybe there is any error reporting methods to handle errors or something? Also I can't see output on io.use(....) method
The solution is to pass "OK" sign just after authenticating to do the next method:
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('www.****.com' == domain) {
globals.debug('New user connected', 'warning');
accept(null, true);
} else {
globals.debug('Bad site authentication data, chat will be disabled.', 'danger');
return accept('Bad site authentication data, chat will be disabled.', false);
}
});
I am having a website which contains login page. When user tries to log in using username and password. Data is being passed in Form Data. Please have a look as following image to get idea.
Now I want to use the same api in my Titanium application and get all details or logged in user which i am performing using below mentioned code.
var url= "http://www.randomwebsite.com/login/";
var jsonData = {
username: "admin",
password: "password1"
};
var xhr = Ti.Network.createHTTPClient();
xhr.onload = function(e) {
var obj = JSON.parse(this.responseText);
alert("DATA IS " + JSON.stringify(obj));
};
xhr.onerror = function(e) {
Ti.API.info("ERROR " + e.error);
};
xhr.onsendstream = function(e){
Ti.API.info("onsendstream");
};
xhr.ondatastream = function(e){
Ti.API.info("ondatastream");
};
xhr.open('POST',url);
xhr.send(JSON.stringify(jsonData));
I am getting HTTP error. I even tried setting xhr.setHeader('Content-Type','application/json') as well as verified url its same as that is being used by website. Can any one help me out with this ? Or is there any way in order to make sure that titanium code passes data in form-data ? Or any suggestion regarding this would be of great help.
Its working fine now. Mistake that I was doing is that i was stringifying text when data was being send. So changing xhr.send(JSON.stringify(jsonData)) to xhr.send(jsonData) works for me. Hope so this would help some one.
I am currently trying to login to my app that is built on Ionic Framework using Venmo's Oauth API. I am attempting to use the Server Side Flow so that I can have a longer term access token. I am able to receive a code and set it to a requestToken variable.
However, when I attempt to post to "https://api.venmo.com/v1/oauth/access_token" with my Client Id, Client Secret, and Request Token, I get the following error alert: "ERROR: [object Object]".
In checking my console, I see that the error is a 400 Bad Request error coming on my post request, although it does appear that I have a valid request token. The error message is as follows: "Failed to load resource: the server responded with a status of 400 (Bad Request)".
Below is the code of the login function I am using to login via Venmo's Oauth API:
//VENMO SERVER SIDE API FUNCTION
var requestToken = "";
var accessToken = "";
var clientId = "CLIENT_ID_HERE";
var clientSecret = "CLIENT_SECRET_HERE";
$scope.login = function() {
var ref = window.open('https://api.venmo.com/v1/oauth/authorize?client_id=' + clientId + '&scope=make_payments%20access_profile%20access_friends&response_type=code');
ref.addEventListener('loadstart', function(event) {
if ((event.url).startsWith("http://localhost/callback")) {
requestToken = (event.url).split("?code=")[1];
console.log("Request Token = " + requestToken);
$http({
method: "post",
url: "https://api.venmo.com/v1/oauth/access_token",
data: "client_id=" + clientId + "&client_secret=" + clientSecret + "&code=" + requestToken
})
.success(function(data) {
accessToken = data.access_token;
$location.path("/make-bet");
})
.error(function(data, status) {
alert("ERROR: " + data);
});
ref.close();
}
});
}
if (typeof String.prototype.startsWith != 'function') {
String.prototype.startsWith = function(str) {
return this.indexOf(str) == 0;
};
}
This function is from this helpful walkthrough article by Nic Raboy (https://blog.nraboy.com/2014/07/using-oauth-2-0-service-ionicframework/). I think that the problem may be in how I am presenting the data array, so if anyone has any experience in successfully implementing a Venmo API in Ionic, your help would be much appreciated!
I was actually able to solve this issue with the method described above. In my original code, I omitted the line used to set the content type to URL encoded (which was included in Nic's example). Once I added this line, the request functioned as expected. The line was as follows:
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
Suppose I logged into my device's Facebook authentication, like system Facebook on iOS. I obtain an access token.
How can I use the access token to login to Meteor's Facebook Oauth provider?
To login with Facebook using an access token obtained by another means, like iOS Facebook SDK, define a method on the server that calls the appropriate Accounts method:
$FB = function () {
if (Meteor.isClient) {
throw new Meteor.Error(500, "Cannot run on client.");
}
var args = Array.prototype.slice.call(arguments);
if (args.length === 0) {
return;
}
var path = args[0];
var i = 1;
// Concatenate strings together in args
while (_.isString(args[i])) {
path = path + "/" + args[i];
i++;
}
if (_.isUndefined(path)) {
throw new Meteor.Error(500, 'No Facebook API path provided.');
}
var FB = Meteor.npmRequire('fb');
var fbResponse = Meteor.sync(function (done) {
FB.napi.apply(FB, [path].concat(args.splice(i)).concat([done]));
});
if (fbResponse.error !== null) {
console.error(fbResponse.error.stack);
throw new Meteor.Error(500, "Facebook API error.", {error: fbResponse.error, request: args});
}
return fbResponse.result;
};
Meteor.methods({
/**
* Login to Meteor with a Facebook access token
* #param accessToken Your Facebook access token
* #returns {*}
*/
facebookLoginWithAccessToken: function (accessToken) {
check(accessToken, String);
var serviceData = {
accessToken: accessToken
};
// Confirm that your accessToken is you
try {
var tokenInfo = $FB('debug_token', {
input_token: accessToken,
access_token: Meteor.settings.facebook.appId + '|' + Meteor.settings.facebook.secret
});
} catch (e) {
throw new Meteor.Error(500, 'Facebook login failed. An API error occurred.');
}
if (!tokenInfo.data.is_valid) {
throw new Meteor.Error(503, 'This access token is not valid.');
}
if (tokenInfo.data.app_id !== Meteor.settings.facebook.appId) {
throw new Meteor.Error(503, 'This token is not for this app.');
}
// Force the user id to be the access token's user id
serviceData.id = tokenInfo.data.user_id;
// Returns a token you can use to login
var loginResult = Accounts.updateOrCreateUserFromExternalService('facebook', serviceData, {});
// Login the user
this.setUserId(loginResult.userId);
// Return the token and the user id
return loginResult;
}
}
This code depends on the meteorhacks:npm package. You should call meteor add meteorhacks:npm and have a package.json file with the Facebook node API: { "fb": "0.7.0" }.
If you use demeteorizer to deploy your app, you will have to edit the output package.json and set the scrumptious dependency from "0.0.1" to "0.0.0".
On the client, call the method with the appropriate parameters, and you're logged in!
In Meteor 0.8+, the result of Accounts.updateOrCreateUserFromExternalService has changed to an object containing {userId: ...} and furthermore, no longer has the stamped token.
You can get the accessToken in the Meteor.user() data at Meteor.user().services.facebook.accessToken (be aware this can only be accessed on the server side as the services field is not exposed to the client.
So when a user logs in with facebook on your meteor site these fields would be populated with the user's facebook data. If you check your meteor user's database with mongo or some other gui tool you could see all the fields which you have access to.
Building on DrPangloss' most excellent answer above, combining it with this awesome post: http://meteorhacks.com/extending-meteor-accounts.html
You'll run into some issues using ObjectiveDDP in trying to get the client persist the login. Include the header:
#import "MeteorClient+Private.h"
And manually set the required internals. Soon I'll make a meteorite package and an extension to MyMeteor (https://github.com/premosystems/MyMeteor) but for now it's manual.
loginRequest: {"accessToken":"XXXXXb3Qh6sBADEKeEkzWL2ItDon4bMl5B8WLHZCb3qfL11NR4HKo4TXZAgfXcySav5Y8mavDqZAhZCZCnDDzVbdNmaBAlVZAGENayvuyStkTYHQ554fLadKNz32Dym4wbILisPNLZBjDyZAlfSSgksZCsQFxGPlovaiOjrAFXwBYGFFZAMypT9D4qcZC6kdGH2Xb9V1yHm4h6ugXXXXXX","fbData":{"link":"https://www.facebook.com/app_scoped_user_id/10152179306019999/","id":"10152179306019999","first_name":"users' first name","name":"user's Full Name","gender":"male","last_name":"user's last name","email":"users#email.com","locale":"en_US","timezone":-5,"updated_time":"2014-01-11T23:41:29+0000","verified":true}}
Meteor.startup(
function(){
Accounts.registerLoginHandler(function(loginRequest) {
//there are multiple login handlers in meteor.
//a login request go through all these handlers to find it's login hander
//so in our login handler, we only consider login requests which has admin field
console.log('loginRequest: ' + JSON.stringify(loginRequest));
if(loginRequest.fbData == undefined) {
return undefined;
}
//our authentication logic :)
if(loginRequest.accessToken == undefined) {
return null;
} else {
// TODO: Verfiy that the token from facebook is valid...
// https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.0#checktoken
// graph.facebook.com/debug_token? input_token={token-to-inspect}&access_token={app-token-or-admin-token}
}
//we create a user if not exists, and get the userId
var email = loginRequest.fbData.email || "-" + id + "#facebook.com";
var serviceData = {
id: loginRequest.fbData.id,
accessToken: loginRequest.accessToken,
email: email
};
var options = {
profile: {
name: loginRequest.fbData.name
}
};
var user = Accounts.updateOrCreateUserFromExternalService('facebook', serviceData, options);
console.log('Logged in from facebook: ' + user.userId);
//send loggedin user's user id
return {
userId: user.userId
}
});
}
);
This answer could be improved further as we can now directly debug the token from a REST http request using futures. Credit still goes to #DoctorPangloss for the principal steps necessary.
//Roughly like this - I removed it from a try/catch
var future = new Future();
var serviceData = {
accessToken: accessToken,
email: email
};
var input = Meteor.settings.private.facebook.id + '|' + Meteor.settings.private.facebook.secret
var url = "https://graph.facebook.com/debug_token?input_token=" + accessToken + "&access_token=" + input
HTTP.call( 'GET', url, function( error, response ) {
if (error) {
future.throw(new Meteor.Error(503, 'A error validating your login has occured.'));
}
var info = response.data.data
if (!info.is_valid) {
future.throw(new Meteor.Error(503, 'This access token is not valid.'));
}
if (info.app_id !== Meteor.settings.private.facebook.id) {
future.throw(new Meteor.Error(503, 'This token is not for this app.'));
}
// Force the user id to be the access token's user id
serviceData.id = info.user_id;
// Returns a token you can use to login
var user = Accounts.updateOrCreateUserFromExternalService('facebook', serviceData, {});
if(!user.userId){
future.throw(new Meteor.Error(500, "Failed to create user"));
}
//Add email & user details if necessary
Meteor.users.update(user.userId, { $set : { fname : fname, lname : lname }})
Accounts.addEmail(user.userId, email)
//Generate your own access token!
var token = Accounts._generateStampedLoginToken()
Accounts._insertLoginToken(user.userId, token);
// Return the token and the user id
future.return({
'x-user-id' : user.userId,
'x-auth-token' : token.token
})
});
return future.wait();
Use this instead of the JS lib suggested by #DoctorPangloss. Follow the same principles he suggested but this avoids the need to integrate an additional library
Hello guys I need help in auto login to youtube.com to upload videos "browser-based" (and later get them data to show in a site by api). So basicly I downloaded extension from here http://framework.zend.com/downloads/latest Zend Gdata. And make it work.
It works fine (demos/.../YouTubeVideoApp). But how can i do auto login to youtube without confirmation page ("grant access" \ "deny access")? Currently I use developer key to work with youtube api.
The message of confirmation is
An anonymous application is requesting access to your Google Account for the product(s) listed below.
YouTube
If you grant access, you can revoke access at any time under 'My Account'. The anonymous application will not have access to your password or any other personal information from your Google Account. Learn more
This website has not registered with Google to establish a secure connection for authorization requests. We recommend that you continue the process only if you trust the following destination:
http://somedomain/operations.php
In general I need create connection to youtube (by api) and upload there (using my own account) video without any popups and confirmation pages.
i think all you need is to get a access token and set it to a session value "$_SESSION['sessionToken']". Combination of javascript and PHP will need to do this. previously i always have to grant access or deny it while using Picasa web API but after changes that i described below, grant or access page is no longer needed.
I have not integrated youtube with zend Gdata but have integrated Picasa web Albums using it
make a login using javascript popup and get a token for a needed scope. below is a javascript code. change your scope to youtube data as in this scope for picasa is used.. click function "picasa" on your button onclick.
var OAUTHURL = 'https://accounts.google.com/o/oauth2/auth?';
var VALIDURL = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=';
var SCOPE = 'https://picasaweb.google.com/data';
var CLIENTID = YOUR_CLIENT_ID;
var REDIRECT = 'http://localhost/YOUR_REDIRECT_URL'
var LOGOUT = 'http://accounts.google.com/Logout';
var TYPE = 'token';
var _url = OAUTHURL + 'scope=' + SCOPE + '&client_id=' + CLIENTID + '&redirect_uri=' + REDIRECT + '&response_type=' + TYPE;
var acToken;
var tokenType;
var expiresIn;
var user;
var loggedIn = false;
function picasa() {
var win = window.open(_url, "windowname1", 'width=800, height=600');
var pollTimer = window.setInterval(function() {
console.log(win);
console.log(win.document);
console.log(win.document.URL);
if (win.document.URL.indexOf(REDIRECT) != -1) {
window.clearInterval(pollTimer);
var url = win.document.URL;
acToken = gup(url, 'access_token');
tokenType = gup(url, 'token_type');
expiresIn = gup(url, 'expires_in');
win.close();
validateToken(acToken);
}
}, 500);
}
function validateToken(token) {
$.ajax({
url: VALIDURL + token,
data: null,
success: function(responseText){
//alert(responseText.toSource());
getPicasaAlbums(token);
loggedIn = true;
},
dataType: "jsonp"
});
}
function getPicasaAlbums(token) {
$.ajax({
url: site_url+"ajaxs/getAlbums/picasa/"+token,
data: null,
success: function(response) {
alert("success");
}
});
}
//credits: http://www.netlobo.com/url_query_string_javascript.html
function gup(url, name) {
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\#&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( url );
if( results == null )
return "";
else
return results[1];
}
Here i am making a ajax call in function "getPicasaAlbums" and setting token to a $_session there and after it i am able to get a album listing using zend queries. here is a some code of php file that i am calling using ajax in function "getPicasaAlbums".
function getAlbums($imported_from = '',$token = '') {
//echo $imported_from; //picasa
//echo $token;
$_SESSION['sessionToken'] = $token;// set sessionToken
$client = getAuthSubHttpClient();
$user = "default";
$photos = new Zend_Gdata_Photos($client);
$query = new Zend_Gdata_Photos_UserQuery();
$query->setUser($user);
$userFeed = $photos->getUserFeed(null, $query);
echo "<pre>";print_r($userFeed);echo "</pre>";exit;
}
i think this will help you a little in your task. relpace above "getAlbums" function's code with your youtube zend data code to retrieve data.
good example & referene of a login popup is here
http://www.gethugames.in/blog/2012/04/authentication-and-authorization-for-google-apis-in-javascript-popup-window-tutorial.html