Android-Django user authentication-1 - android

I am trying to refer user as foreign key in my django model AddRec(Having android at frontend)
at django side I have this code ,
this is django model,
class AddRec(models.Model):
user=models.ForeignKey(User)
about=models.CharField(User)
created = models.DateTimeField(auto_now_add=True)
class AddRecForm(ModelForm):
class Meta:
model=AddRec
#login_required
def add_record(request):
if request.method=='POST':
if not request.user.is_authenticated(): # if user is not logged in
response_data=[{"success": "0"}]
return HttpResponse(simplejson.dumps(response_data),mimetype='application/json')
current_user=request.User
description=request.POST['about']
new_rec = AddRec(user=current_user,about=description)
new_rec.save()
response_data=[{"success": "1"}]
return HttpResponse(simplejson.dumps(response_data), mimetype='application/json')
else:
response_data=[{"success": "0"}]
return HttpResponse(simplejson.dumps(response_data),mimetype='application/json')
When I execute the code above with Android as backend it gives me error "fatal exception".
The main thing is that I am not able to access the request the user sent from Android in django.
From the Android side I just send data with
nameValuePairs.add(new BasicNameValuePair("about", "123"));
and with httppost I am sending data.
Is it necessary to send user name from the Android side even if the user is logged in?

The authentication you are using stores session key in a cookie on the client side (android). Are you using HttpClient? if so you must use cookies.
Additionally, api's should be stateless. You should not be keeping a user logged in using cookies for an api. http://en.wikipedia.org/wiki/Representational_state_transfer There are a couple popular api authentication schemes that address this.
Are you sending csrf token with the request? If not you can explicitly disable csrf protection for your view using a decorator. https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#django.views.decorators.csrf.csrf_exempt (not recommended)
When posting a question please post error logs, tracebacks, basically everything you see when something doesn't go right.

Related

How to implement server side sessions in node.js with express for an android app?

Hello all i am making an android app in whiich i have multiple account login at a time now my question is that i for multiple logins i should use sessions to verify every account user that is logged in. Now i am using express on the server side i have read a lot of documentation on storing sessions in node.js
Express-session (Though it is only good for development but not for production but not for my app)
Cookie-session
connect-Redis
connect-mongo
I have also heard about json web tokens where i can generate unique tokens and then i can pass the tokens to the client using res.json({user_id:"user1", token: "generated_token here"})
I have also heard about passport but dont know how it is going to do this also as in passport i use express-session by default will it be good for production or not ??
Now my first question is i have read all of there docs and nowhere it is mentioned where i am creating unique tokens for every user that is signing up.
Second question as i am using my server for android app there will be no use of cookie i will be sending user token as in parameter req.body.token now how to cmpare this with current user_id.
Actually i dont get the flow of control i mean how everything is going on in session in node.js. Also what is this secret is this thing generating unique tokens or what. Also i mean about 100000 of users are registered for my app now please tell me accordingly which way should i use for my app.
I have asked this question previously but there i did not mention that as i am not making a website how to do this(As in my case there will be no use of tokens)
I know this question i am asking is very vague but please bear with me i just want to understand how sessions are used in node.js
Thanks Anways
I'll try to answer this, but it is vague (as you pointed out). I'm going to make an assumption that your Android app is a native Android app and is going to be connecting to some sort of NodeJS backend in the cloud that is based on ExpressJS. If that's not the case, please clarify your thoughts in an update to your question.
The best idea for this specific scenario is to look to the cloud provide. Azure App Service Mobile Apps, for example, allows you to implement authentication - it eventually returns a JSON Web Token (http://jwt.io) to authenticate each request.
If you don't want to be beholden to a cloud provider, but want to run it yourself, you are going to have to implement the token generation and checking yourself. This generally follows the form:
Set up a WebAPI endpoint (maybe /signin) which takes whatever token the identity provider gives you, verifies the information and returns a JWT - there is an NPM module (jsonwebtoken) for producing the JWT. Ensure the JWT includes the identity of your user. I tend to use email address for the identity.
Your Android application will do a WebAPI request to your backend with an Authorization header, the value of which is "Bearer "
Your NodeJS API will use JWT authorization to validate the JWT and extract the user identity so you can use it in your API logic.
The important thing to note in this specific scenario is that your backend code is implementing a WebAPI - there are no cookies nor sessions in the API. The only thing that is linking the user from the client code to the backend code is the JWT.
As a short piece of code, here is how you verify a JWT:
var express = require('express');
var app = express();
var jwt = require('express-jwt');
var jwtCheck = jwt({
secret: new Buffer('your-jwt-secret', 'base64'),
audience: 'your-jwt-audience'
});
app.get('/api/protected', jwtCheck, (req, res) => {
// Your code here
});
app.listen(process.env.PORT || 3000);

Foursquare Redirect uri mismatch on native Android OAuth login

I am trying to implement Foursquare Native OAuth on my Android app. I have followed the foursquare-oauth-library sample and have succesfully generated an access_token for the user.
However, following Foursquare's recommendation of my App's Secret not being stored anywhere in the app and instead performing a server side auth code/access_token exchange I am doing the call on my server but get a redirect_uri_mismatch error everytime I do it this way.
I am getting the auth code as specified in the sample app:
AuthCodeResponse codeResponse = FoursquareOAuth.getAuthCodeFromResult(resultCode, data);
Afterwards, I send that auth code from my Android app to my rails server. I assume the access_token should be obtained following Step 3 of https://developer.foursquare.com/overview/auth#code but I get the redirect_uri_mismatch response.
I am using Nestful on my rails server to send Foursquare my request for the access_token:
response = Nestful.post 'https://foursquare.com/oauth2/access_token',
client_id: ENV_CONFIG['foursquare_client_id'],
client_secret: ENV_CONFIG['foursquare_client_secret'],
grant_type: 'authorization_code',
redirect_uri: ENV_CONFIG['redirect_uri'],
code: params[:code]
#token = response['access_token']
The response is:
{"error":"redirect_uri_mismatch"}
I have already double checked the app's configuration on Foursquare, where I have also set my generated Android Hash Key, and even tried providing that as a redirect_uri parameter to generate the acess token, but to no avail.
Any idea of what I could be doing wrong?
It turns out that the given code checks upon the redirect_uri provided originally. Since one wasn't specified in the first place, no redirect_uri param should be passed to the code/access_token exchange call.

django, using session in web for the first time

Client access the login view,
//user is properly set here
user = auth.authenticate(username=email, password=password)
auth.login(request,user)
The same client which requested the login view, requests another view
// I expect the same user I logged in previously here. But I see anonymous user here.
user = request.user
I don't know how exactly web server recognizes two different http requests (because http is connectionless) are coming from the same user. But I know that session is the concept that makes it possible.
I have MIDDLEWARE_CLASSES = ('django.contrib.sessions.middleware.SessionMiddleware',...) in my settings.py
Is there something else I need to check to make this work?
-edit
I debugged a bit,
django/contrib/auth/init:login does request.session[SESSION_KEY] = user.id
django/contrib/auth/init:get_user tries looking up request.session[SESSION_KEY] on next run and fails.
I need to understand what request.session is.
I thought request is something a client sends per http-request.(so it's not persistent)
** Below is my understanding, please correct me if I'm wrong **
When a user logins, server assigns a unique id for a user and send it to the user.
Server also stores relevant data for the id in somewhere persistent.
The user sends the unique id for every subsequent http-request.(this is cookie)
Django looks up data stored in step 2(or in other cases) with the id given.
Django puts the data in request.session and give to view.
I followed Django, request.user is always Anonymous User
I suspect all this is due to my custom authentication backends copied from http://www.micahcarrick.com/django-email-authentication.html
My First View.
#csrf_exempt
def login(request):
# import pdb
# pdb.set_trace()
email = request.POST['email']
password = request.POST['password']
user = auth.authenticate(username=email, password=password)
# auth.logout(request)
if user is not None and user.is_active:
auth.login(request, user)
profile = user.get_profile()
user_dict = profile.to_dict()
jsonUser = json.dumps(user_dict, ensure_ascii=False, cls=DjangoJSONEncoder)
return HttpResponse(jsonUser)
else:
raise Http404
My second view.
#csrf_exempt
def user_update(request):
import pdb
pdb.set_trace()
user = request.user
=> if not user.is_authenticated():
raise Http404 // always ends up here
print 'in user_update'
.......
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware', )
my Backends
from django.contrib.auth.models import User, check_password
class EmailAuthBackend(object):
"""
Email Authentication Backend
Allows a user to sign in using an email/password pair rather than
a username/password pair.
"""
supports_inactive_user = False
def authenticate(self, username=None, password=None):
""" Authenticate a user based on email address as the user name. """
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
""" Get a User object from the user_id. """
print 'getting an user for user_id: ', user_id
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
You are right about http being stateless. However using cookie can help you maintain state of the request. When you call login function Django will save the user ID (encrypted value) in the cookie named sessionid. So the next time you get a request from the user, the browser will also send this cookie in the request header.
If you look at the table named *django_session* you should see an entry where session_key has the same value as cookie sessionid.
AuthenticationMiddleware keeps track of a user authentication and assigns user object to request.user
SessionMiddleware tracks session data for a user
That's how Django will track a user and its session.
If you really want to look into details you could have a look at authentication middleware code (django.contrib.auth.middleware), especially process_request to check how a user is added in request object.
Perhaps this is useful in debugging your issue?
EDIT:
Based on what helped Eugene from the comments.
When it's session related issue (login or session data) it's a good idea to check if the cookie is set properly on the client side. If it's a desktop browser, a tool like Firebug can be helpful by reading the http headers in "Net" tab of Firebug.
In Eugene's case it's an Android client, so one option is to debug Django middleware to check the values for request.COOKIE. If you are not receiving right cookies on Django end then the cookie is not set properly on the client side. One of the reasons for this on a browser is cookies could be disabled.
So it's a good idea to check client side settings to make sure cookies are stored and sent correctly.

Implementation an authentication scheme for mobile apps using Tastypie

I would like to create a REST service with authentication for mobile devices. This is the first time I will be doing something like this, so I would like to receive some advise on how I would implement things.
For this I would need to create a signup form which let's the user signup for the services.
I see no issue here I can just post the form data to the server and let it return a response.
If the form is valid a new user object will be created and immediately be logged in. Also a API KEY will be generated using:
from django.contrib.auth.models import User
from django.db import models
from tastypie.models import create_api_key
models.signals.post_save.connect(create_api_key, sender=User)
The request, will return a 301 HTTP status and contain a redirect URI to fetch the API KEY.
After this step the app will request another URI (the URI received in the 301 response of the signup request) to access the API KEY (I will be using Tastypie's ApiKeyAuthentication scheme). The request will contain the session cookie received in the previous request response, this way to view will be secured and I will be able to user the login_required decorator.
The response will be plain JSON with username and api key.
These values will be stored somewhere in the app.
Any requests now made will add the username and API KEY stored in the app so further requests will be more secure.
Does this look like a good scheme to follow ? Are there holes in the design ?

Handling Sessions on Google App Engine with Android/IPhone

I'm starting to write an app whereby a mobile app (Android/IPhone) will communicate with the GAE backend (Python) through a series of Web API calls using JSON.
I can't use Google Accounts for authentication so I need to implement my own auth. I have an idea of how to do this, but I'm not sure if there is a better way.
Can anyone help with some code examples/suggestions of how to achieve the below please?
Method
Mobile app calls a Login method on the server which authenticates and creates a session key in the store and returns this to the app - not sure how to generate the key/session or where on the request/response it should be.
On every call, the app passes this key for the server to authenticate and allows the action if it passes.
User should not have to login on mobile again unless they explicitly logout or lose the key.
Login Method - without key generation
class Login(webapp.RequestHandler):
def post(self):
args = json.loads(self.request.body)
email = args['e']
pwd = args['p']
ret = {}
user = User.gql('WHERE email = :1', email).get()
if user and helpers.check_password(pwd, user.password):
ret['ret_code'] = 0
ret['dn'] = user.display_name
else:
ret['ret_code'] = 1
self.response.headers['Content-Type'] = 'application/json'
self.response.out.write(json.dumps(ret))
I think you should use features webapp2 providing to implement your custom registration.
from webapp2_extras import auth
from google.appengine.api import users
class RegisterHandler(webapp2.RequestHandler):
def post(self):
email=self.request.POST['email']
password=self.request.POST['password']
#Let webapp2 handle register and manage session
user = auth.get_auth().store.user_model.create_user('own:'+str(email), password_raw=password,email=email)
#user (True, User(key=Key('User', 80001), auth_ids=[u'own:useremail#mail.com'],email='useremail#mail.com',password=u'hashed_password',...))
if not user[0]: #user is a tuple
self.response.write(user[1]) # Error message
else:
#You can extend your User Model e.g UserProfile(User): or have a UserProperty in your profile model as the example.
profile=UserProfile(user=users.User(user[1].email)).put()
self.response.write(str(profile.key()))
class LoginHandler(webapp2.RequestHandler):
def post(self):
email = self.request.POST.get('email')
email = self.request.POST.get('password')
# Try to login user with password
# Raises InvalidAuthIdError if user is not found
# Raises InvalidPasswordError if provided password doesn't match with specified user
try:
auth.get_auth().get_user_by_password('own:'+email, password)
#Return user_session with User id,
except InvalidPasswordError, InvalidAuthIdError:
#Error
You can check user logged in by:
if auth.get_user_by_session():
#Logged in
else:
#Not logged in
On your client application(Android, IOS). You only have to store the response cookie and send it for every sub sequence requests.
Good luck :)
Have a look at webapp2 and webapp2 extras with sessions, auth and JSON
I cannot see why you would need a session?
Sessions on App Engine are persisted in the data store, so if you can keep your requests stateless, I encourage you to do so.
As you will have your own user service which will authenticate the users, I suggest you use Digest authentication, as the secret is never included in the request.
There are libraries implementing Digest for most client and server platforms.
If you dont explicitly want to use Sessions etc. you can simply use the Datastore. Try following this:
Get a unique deviceID/email to identify each unique user.
On request from a specific user, generate a random authentication key, and store it attached to the user's email/deviceID and probably the current timestamp and a loggedIn flag.
SO you have:
User email/id: someone#example.com
password: xxxxxxxxxx
Key : 2131231312313123123213
Timestamp: 20:00 12-02-2013
loggedIn : boolean value
This can be database model. Now whenever the user logs in:
Check email, password combination.
If valid, generate random key, and update the datastore with the new key
update timestamp with current time, and set loggedIn to True
Now return the key back to the client (Android/iPhone) in a JSON object.
Now on every request, Check the received key against the one in your datastore, and if loggedIn flag is set to true. If both OK, process the request.
Also, on Logout:
Just set the loggedIn flag in the datastore to False.
Hope this helps :)
Try gae-sessions for session management. It creates secure cookies for you and allows you to easily associate data with each user. Just provide your own logic for the initial authentication.
It was built specifically for App Engine and is pretty popular and super fast/scalable.
https://github.com/dound/gae-sessions
There are many ways to do this.
1) When you check the users login details if it checks out you can then create a random UUID or string and store the User object in memcache with the random string as the Key and the User Object as the value. Then return the random string along with your response headers. On the mobile when you are parsing the response, get this header and store it in the local cache. On all further requests keep sending this key back in the request header and in your controller get the User object from memcache using this key and proceed. If the object is not in memcache you can send back a response which prompts the user to log in.
2) If you dont want to use memcache you can store the User object in the session and on the client side while parsing the response get the session id from the response. Its usually JSESSIONID. Then store that and resend it with further requests. In the controller you can check if the current session has the user object else force login.
1) Another way to go would be to return the appengine key for the user along with the response and resend it.
Just google get response header from response. Then get the SESSIONID/JSESSIONID header, store and add the field with the same name and value to all further request headers. Thats the easiest way.
My first answer on stackoverflow and no code exapmles, dangit if only i knew python.

Categories

Resources