flask-security ajax logout causes session errors - javascript

When I post to a flask endpoint:
#app.route('/api/v1/logout', methods=['POST','GET'])
def logout():
logout_user()
return jsonify(status=200, message='User has been successfully logged out.')
I get an error when I try to log in the next time
InvalidRequestError: Object '<User at 0x7f09b4831c90>' is already attached to session '1' (this is '4')
I was wondering how to logout and in safely using ajax.
Edit- angularjs login controller:
LoginController: function ($scope, $http, authService, $location) {
$scope.submit = function() {
console.log('in logincontroller')
$http.defaults.headers.post['X-CSRFToken'] = csrf_token;
$http.defaults.headers.common['Content-Type'] = 'application/json'
//debugger;
$http.post(
'/login',
JSON.stringify({ email: $scope.email, password: $scope.password })
).success(
function(data) {
if (data.meta){
var status_code = data.meta.code;
}
else{
var status_code = data.status;
}
if (status_code == 200){
$.cookie('email', $scope.email, { expires: 7 });
$.cookie('auth_token', data.authentication_token, { expires: 7 });
$http.defaults.headers.common['Authentication-Token'] = data.authentication_token;
authService.loginConfirmed();
$location.path("/dashboard");
}
else{
//form stuff
}
}
).error(
function(data) {
alert('LoginController submit error');
$scope.errorMsg = data.reason;
//debugger;
}
);
};
}

I guess You have to redirect at the end to get out of the existing session
#app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))

You are doing it very wrong.
Since you didn't provide your login method, I guess from the error log that you were storing a User model in the session. This is totally wrong.
My suggestion is that you store your user's id in the session. e.g.
def login_user(user):
session['user_id'] = user.id
If you need to know the current user:
def get_current_user():
return User.get(session['user_id'])
Ask the right question, so that people can help you.

Related

Not able to figure out the way to call a function at the correct place in django website

I am working on a django website and have come across an error which I am not able to solve and Its been a couple of days but I wasnt able to solve the error. I am trying to integrate a payment gateway to my site. I have a payment button which on click is supposed to post the data to the database as well as go to the payment site. But it is storing the data but not going to payment site.
Here is the javascript for my button:
document.getElementById('payment-info').addEventListener('click', function (e) {
submitFormData()
})
function submitFormData() {
console.log('Payment Button Clicked')
var userFormData = {
'name': null,
}
var shippingInfo = {
'address': null,
}
shippingInfo.address = form.address.value
userFormData.name=form.name.value
var url = "/process_order/"
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body:JSON.stringify({'form': userFormData, 'shipping': shippingInfo }),
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
alert('Transaction Completed')
window.location.href = "{% url 'index' %}"
})
}
</script>
This is my views.py:
def processOrder(request):
transaction_id = datetime.datetime.now().timestamp()
data = json.loads(request.body)
if request.user.is_authenticated:
customer=request.user.customer
order, created=Order.objects.get_or_create(customer=customer, complete=False)
total=float(data['form']['total'])
order.transaction_id=transaction_id
if total == order.get_cart_total:
order.complete = True
order.save()
ShippingAddress.objects.create(
customer=customer,
order=order,
address=data['shipping']['address'],
name=data['form']['name'],
)
//Code for integration below
param_dict = {
'MID': 'DIY12386817555501617',
'ORDER_ID': str(order.id),
'TXN_AMOUNT': '4',
'CUST_ID': 'j',
'INDUSTRY_TYPE_ID': 'Retail',
'WEBSITE': 'WEBSTAGING',
'CHANNEL_ID': 'WEB',
'CALLBACK_URL':'http://127.0.0.1:8000/handlerequest/',
}
param_dict['CHECKSUMHASH'] = Checksum.generate_checksum(param_dict, MERCHANT_KEY)
return render(request, 'paytm.html', {'param_dict': param_dict})
return JsonResponse('Done',safe=False)
#csrf_exempt
def handlerequest(request):
# paytm will send you post request here
form = request.POST
response_dict = {}
for i in form.keys():
response_dict[i] = form[i]
if i == 'CHECKSUMHASH':
checksum = form[i]
verify = Checksum.verify_checksum(response_dict, MERCHANT_KEY, checksum)
if verify:
if response_dict['RESPCODE'] == '01':
print('order successful')
else:
print('order was not successful because' + response_dict['RESPMSG'])
return HttpResponse('doneee')
And this is my urls.py:
path("process_order/",views.processOrder,name="process_order"),
path("handlerequest/",views.handlerequest,name="handlerequest"),
This code is not working . After clicking the payment button I am getting this error:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
This error is referring to the submitformdata() in my javascript code.
I want to workout a way so that once a person clicks on the payment button and his transaction is completed then his data is submitted to the database otherwise not for which I have written the code in handlerequest.
Please help me out.

Angular js Web Application failed to Return Expected Message

I am consuming WCF Rest Service into Angular js web application. First I am checking username in database . If the username name is exist then i want to display message in angular js web application is username name is exist please choose other username .If username is not exist then i want to insert the record into database .But the problem is its not displaying message username is not displaying expected message and i got following error .
The server encountered an error processing the request. The exception message is 'Non-static method requires a target.'. See server logs for more details. The exception stack trace is:
Here is the Method.
public bool RegisterUserEncryptPassword(tblUser user)
{
using (HalifaxDatabaseEntities context = new HalifaxDatabaseEntities())
{
var query = (from x in context.tblUsers
where x.Username == user.Username
select x).SingleOrDefault();
if (query != null)
{
return true;
}
else
{
tblUser createUser = new tblUser();
createUser.Username = user.Username;
createUser.Password = Utility.Encrypt(user.Password);
createUser.Email = user.Email;
ctx.tblUsers.Add(createUser);
ctx.SaveChanges();
}
}
return false;
}
Here is my script code..
var app = angular.module("WebClientModule", [])
.controller('Web_Client_Controller', ["$scope", 'myService', function ($scope, myService) {
$scope.OperType = 1;
$scope.createuser = function () {
var User = {
Username: $scope.Username,
Password: $scope.Password,
Email: $scope.Email
};
if ($scope.OperType === 1) {
var promisePost = myService.post(User);
promisePost.then(function (pl) {
$scope.Id = pl.data.Id;
window.location.href = "/Login/Index";
ClearModels();
}, function (err) {
$scope.msg = "Password Incorrect or username is exit !";**//Always Hit on This line**
console.log("Some error Occured" + err);
});
}
}]);
app.service("myService", function ($http) {
//Create new record
this.post = function (User) {
var request = $http({
method: "post",
url: "http://localhost:52098/HalifaxIISService.svc/RegisterUserEncryptPassword",
data: JSON.stringify(User)
});
return request;
};
})
Here is the Screen shot when i run the application.When i try to insert new record i i want to display
here is error message in network tab.
You need to bind the #scope.msg into an html element like label or span. This html element must be loaded inside the DOM with hidden status. You have to just show it with ng-show.

Angularjs : How to always show modal login dialog if any REST API fails due to authentication

My angular JS application is for an e-commerce usecase. There would be several pages, where some data would be fetched from some REST APIs which would be authenticated (and some not requiring authentication). If authentication fails (user not logged in), the APIs would all respond with a special error_code (say 'AUTH_FAIL').
My requirement is if any API fails due to authentication, then a login modal form dialog should appear in that page. This modal form contains the Username and password field. If the login succeeds, the modal window should close, and the current route should be re-freshed.
I understand how to do this for a particular route/controller. However, since there would be a lot of such pages where this would be needed, I'm unable to think of a way in which same piece of code could be easily utilized, since in my opinion, this does seem like a common requirement. How can it be done, or if not, what's the best way around it?
You can use interceptors for this purpose. Inteceptors can be used for global error handling, authentication, or any kind of synchronous or asynchronous pre-processing of request or postprocessing of responses.
For example I use the following code to redirect user to login when authentication fails.
.factory('myInterceptor', ['$q', '$location', '$injector', function ($q, $location, $injector) {
return {
response: function (response) {
return response || $q.when(response);
},
responseError: function (rejection) {
if (rejection.status === 401) {
var stateService = $injector.get('$state');
stateService.go('login');
}
return $q.reject(rejection);
}
}
}])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
}]);
Using interceptors sounds like the most obvious and elegant solution, however I was never satisfied with it, mostly because of running into the circular dependency problems.
Here are some bits and pieces of logic from one of my apps using angular 1.6 and ui-router.
Some explanation about the business logic before you deep dive into the code.
I use JWT authentication and my server expects JWT to be passed as a header, hence the specifics of the authService implementation. The authService checks if the header is expired, and tries to send a JWT refresh request before actually showing a login dialog. Feel free to adjust it to your security implementation (e.g. session cookie/based or some other storage).
authService.js
This service is responsible for storing security token in the client. It returns a promise, which is resolved with the JWT token (if present or if it was refreshed). The promise is rejected when the token is expired and the service failed to obtain new token from the server.
app.factory('authService', function($http, $q, $window, jwtHelper, API_HOST) {
var storage = $window.localStorage;
var cacheToken = {};
var targetUrl = null;
function saveToken(data) {
var tokenPayload = jwtHelper.decodeToken(data.auth_token);
storage.setItem('auth_token', data.auth_token);
storage.setItem('refresh_token', data.refresh_token);
storage.setItem('exp', tokenPayload.exp);
storage.setItem('user_identifier', tokenPayload.user_identifier);
cacheToken.auth_token = storage.getItem('auth_token');
cacheToken.refresh_token = storage.getItem('refresh_token');
cacheToken.exp = storage.getItem('exp');
cacheToken.user_identifier = storage.getItem('user_identifier');
}
function setCacheToken() {
cacheToken.auth_token = storage.getItem('auth_token');
cacheToken.refresh_token = storage.getItem('refresh_token');
cacheToken.exp = storage.getItem('exp');
cacheToken.user_identifier = storage.getItem('user_identifier');
}
function isAuthenticated() {
return cacheToken.auth_token && cacheToken.exp > moment(new Date().getTime()).unix()
}
setCacheToken();
return {
saveToken: function(data) {
saveToken(data);
return cacheToken;
},
getToken: function() {
return cacheToken;
},
isAuthenticated: isAuthenticated,
targetUrl: targetUrl,
getAuthorizationHeader: function() {
if (isAuthenticated()) {
return $q.when({
'Authorization': 'Bearer ' + cacheToken.auth_token
});
} else {
cacheToken.auth_token = storage.getItem('auth_token');
cacheToken.refresh_token = storage.getItem('refresh_token');
cacheToken.exp = storage.getItem('exp');
if (isAuthenticated()) {
return $q.when({
'Authorization': 'Bearer ' + cacheToken.auth_token
});
} else {
if (!cacheToken.refresh_token) return $q.reject(null);
return $http.post(API_HOST + '/tokens/refresh', {
'refresh_token': cacheToken.refresh_token
}).then(function(response) {
saveToken(response.data);
return {
'Authorization': 'Bearer ' + cacheToken.auth_token
};
}).catch(function() {
cacheToken = {};
$window.localStorage.clear();
return $q.reject(null);
})
}
}
}
}
});
app.run block
This piece of logic is responsible for memorising the target url in case user tried to access protected resource, or when user token/session is expired. Please 2 things here: authService.targetUrl stores the URL and authenticate property on the ui-router state is used to check if the state is protected (e.g. if the authentication logic should be applied).
$transitions.onBefore({
to: function(state) {
return state.self.authenticate;
}
}, function(trans) {
return authService.getAuthorizationHeader().then(function() {
return null;
}).catch(function() {
authService.targetUrl = $window.location.href;
$('#login-modal').modal();
return trans.router.stateService.target('homepage');
});
});
login modal directive
This piece of code stores the user token after login and also checks if the targetUrl is present in the authService, e.g. if a user tried to access protected resource some time before.
scope.loginCallback = function(response) {
authService.saveToken(response.data);
jasprApi.User.me().then(function(response) {
$rootScope.user = response.data;
$(element).modal('hide');
if (authService.targetUrl) {
$window.location.href = authService.targetUrl;
authService.targetUrl = null;
}
});
};
routes.js
Here is the ui-router states config which specified if the state should be protected
.state('admin', {
url: '/admin',
//other configuration
//...
//...
authenticate: true
})
api.js
A bonus — this is the sample from the file with the methods for accessing the API. Please note how authService is used here.
updatePageAction: function() {
return authService.getAuthorizationHeader().then(function(authHeader) {
return $http({
method: 'PUT',
url: '/admin/page/update',
headers: authHeader
});
});
},
I hope it helps!
Cheers

trouble on using lb-services (Loopback - Angular JS SDK)

I'm using lb-services from Angular JS SDK to create my default service, and currently, I have some trouble in logout & rememberMe function.
I'm following this tutorial : Angular Javascript SDK & Loopback getting started intermediate , and the way I create my authentication is as same as the example, with some adjustment to apply them in my application.
I'm not sure how to describe it, but here's some of the code for my logout & remember function
in my stateProvider, I have this kind of state as my root application
.state('app', {
url:'/',
abstract: true,
views:{
'bodyLogin': {templateUrl : 'views/login/body.html',
controller : 'BodyController'},
'bodyMain': {templateUrl : 'views/main/body.html',
controller : 'BodyController'}}
})
.state('app.mainUnreg', {
url:'home',
views: {
'content#app': {
templateUrl : 'views/login/home.html'
}}})
.state('app.mainReg', {
url:'mainMenu',
views: {
'header#app': {
templateUrl : 'views/main/header.html'
},
'sidebar#app': {
templateUrl : 'views/main/sidebar.html'
},
'middle#app': {
templateUrl : 'views/main/home.html'
},
'footer#app': {
templateUrl : 'views/main/footer.html'
}},
controller: 'HomeController'})
index.html
<div ng-if="!loggedIn" ui-view="bodyLogin" class="site-wrapper" ui-sref-active="app.mainUnreg"></div>
<div ng-if="loggedIn" ui-view="bodyMain" ui-sref-active="app.mainReg"></div>
so, if I haven't not logged in, I will enter to bodyLogin, which means I will show my login template, and otherwise, if I have logged in, I will enter to bodyMain
I have succeed to logged in and enter to my main page, but on here, and it should be have been authenticated, because in my bodyController,
.controller('BodyController', [..., function(...){
//this line is to check whether the user has been authenticated or not
if(Account.isAuthenticated() === false) {
$scope.loggedIn = false;}
// ------------
if($scope.loggedIn === false){
$scope.layout = 'login';
$state.go('app.mainUnreg');
}
else{$scope.loggedIn = true;
$scope.layout = 'styles';
$state.go('app.mainReg');
}}])
.controller('LoginController', [..., function (...) { $currentUserId = Account.getCurrentId();
$scope.$stateParams = $stateParams; $scope.loginData = {}; $scope.doLogin = function() { AuthService.login($scope.loginData)
.then(function() {
$scope.loggedIn = true;
location.reload(); }); };}])
.controller('LogoutController', [..., function(...) {
AuthService.logout()
.then(function() {
console.log("Logging out . . .");
$scope.loggedIn = false;
$state.go('app'); }); }]);
And some additional service beside lb-services.js to handle my authentication,
function login(loginData) {
var params = { rememberMe: loginData.rememberMe };
var credentials = {
email: loginData.email,
password : loginData.password
};
return User
.login(params, credentials)
.$promise.then(function(response){ $rootScope.currentUser = {...};
console.log($rootScope.currentUser);
},
function(response) {
console.log(response);
});
}
function logout(){
return User
.logout()
.$promise.then(function(){
$rootScope.currentUser = null;
});
};
I think, with this kind of code, especially I have checked with
if(Account.isAuthenticated() === false){...}
and succeed to enter my main page, I have successfully logged in and authenticated, haven't I?
But, if I tried to put ng-show="Account.isAuthenticated()" in the top div of my main page app.mainReg , my page can't be show, yet it means that my account haven't authenticated, even the loopback have successfully save my token, user id, and rememberMe boolean in local storage, like this
$LoopBack$accessTokenId = ....
$LoopBack$currentUserId = ...
$LoopBack$rememberMe = true // automatically become true?
So, do anyone know how to solve this problem? I think the problem is on the authentication.
I'm quite confused with this one, I have tried to search for solution, yet I could find any.
I just realized why I couldn't use rememberMe function, that's just because I made a silly mistake, by putting " ; " after my logout function in my additional services
And after several testing, It seems that my problem was inside my state provider. I tweaked my controller and my state provider and finally it has been work successfully.

Emberjs authentication session not working

I have followed Authentication Tutorial, but running into some issues.
I have a php backend api which resides in another domain, http://rest.api {local development}
The ember js application uses ember-app-kit and connects to the rest api.
When the user submits the login form it sends the username/email with password to one of the route defined in the rest api Session Controller
import AuthManager from 'lms/config/auth_manager';
var SessionNewController = Ember.ObjectController.extend({
attemptedTransition : null,
loginText : 'Log In',
actions: {
loginUser : function() {
var self = this;
var router = this.get('target');
var data = this.getProperties('identity', 'password');
var attemptedTrans = this.get('attemptedTransition');
$.post('http://rest.api/login',
data,
function(results) {
console.log(results.session);
console.log(results.user_id);
AuthManager.authenticate(results.session, results.user_id);
if(attemptedTrans) {
attemptedTrans.retry();
self.set('attemptedTransition', null);
} else {
router.transitionTo('index');
}
}
)
}
}
});
export default SessionNewController;
After receiving the api result in the results variable which looks like this :
Object {success: "user login success", session: "2OmwKLPclC.YhYAT3745467my7t0m2uo", user_id: "1"}
But as soon as I capture the data and send it to the AuthManager which resides in Auth Manager Code
import User from 'lms/models/user';
import Application from 'lms/adapters/application';
var AuthManager = Ember.Object.extend({
init: function() {
this._super();
var accessToken = $.cookie('access_token');
var authUserId = $.cookie('auth_user');
if(!Ember.isEmpty(accessToken) || !Ember.isEmpty(authUserId)) {
this.authenticate(accessToken, authUserId);
}
},
isAuthenticated: function() {
return !Ember.isEmpty(this.get('ApiKey.accessToken')) && !Ember.isEmpty(this.get('ApiKey.user'));
},
authenticate: function(accessToken, userId) {
$.ajaxSetup({
headers: { 'Authorization': 'Bearer ' + accessToken }
});
var user = User.store.find(userId);
console.log(user);
this.set('ApiKey', ApiKey.create({
accessToken: accessToken,
user: user
}));
},
reset: function() {
this.set('ApiKey', null);
$.ajaxSetup({
headers: { 'Authorization': 'Bearer None' }
});
},
apiKeyObserver: function() {
Application.accessToken = this.get('apikey.accessToken');
if (Ember.isEmpty(this.get('ApiKey'))) {
$.removeCookie('access_token');
$.removeCookie('auth_user');
} else {
$.cookie('access_token', this.get('ApiKey.accessToken'));
$.cookie('auth_user', this.get('ApiKey.user.id'));
}
}.observes('ApiKey')
});
export default AuthManager;
I got an error in the console saying
Uncaught TypeError: Object function () {
if (!wasApplied) {
Class.proto(); // prepare prototype...
}
o_defineProperty(this, GUID_KEY, undefinedDescriptor);
o_defineProperty(this, '_super', undefinedDescriptor);
var m = met...<omitted>...e' new.js:23
(anonymous function) new.js:23
jQuery.Callbacks.fire jquery.js:1037
jQuery.Callbacks.self.fireWith jquery.js:1148
done jquery.js:8074
jQuery.ajaxTransport.send.callback jquery.js:8598
It is not able to pass the variables to the imported function.
Finally got this working. The error that was I doing is after extending the Ember.Object.extend() on auth_manager.js, I didn't create the object anywhere. Thats why it couldnt set create a cookie and throwing that error message.
All I had to do was, .create() after extending the object.
Don't know whether it is the right method or not. But it certainly works.

Categories

Resources