I was trying to extract Facebook user profile by GraphAPI. From the query:"https://graph.facebook.com/v2.4/search?q=vietnam&limit=1000&offset=0&type=user&format=json&access_token=....". I can get the list of id Facebook. But I want more information about user profile such as education, email. I used query:"https://graph.facebook.com/v2.4/{id_user}?fields= education,birthday&access_token=...."But I cant get them. Any suggestions for my problem? I will highly appreciated
In order to obtain more detailed infos such as 'education', 'birthday' and 'email', you need an access token with permissions that will grant you access to that info.
From the graph API explorer, with the token you get by default, using the following query:
me?fields=id,name,education,email,birthday
will not return education, email or birthday
{
"id": "...",
"name": "..."
}
Using the Graph API Explorer tool, you can try the same query with more priviledges.
Click the "Get Token" button, then on the prompt you get, check the following permissions:
user_birthday
user_education_history
email (located inside "extended permissions")
then try the request again. You should get:
{
"id": "...",
"name": "...",
"email": "...#....com",
"birthday": "../../...."
"education": ...
}
NOTE: You may not get all fields, depending on wether the target user has made these fields available to you.
Also if the user you're querying is 'yourself' (/me) then the user must have granted these permissions to your app. (a user may decline individual permissions. Your app must take that in consideration and handle cases where permissions were refused.)
Once you've confirmed this works, all you have to do is to add these permissions to your login or authorization flow inside your app.
Related
I've created a simple REST API to list and create users with Django REST Framework and I'm trying to integrate it with an Kivy app. I've used the django.contrib.auth.models.User as my user class, and passwords are being created as show below:
serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password')
def create(self, validated_data):
user = super(UserSerializer, self).create(validated_data)
user.set_password(validated_data['password'])
user.save()
return user
As I'm using the set_password function, my REST API gives me SHA256 hashed passwords when I list my users:
GET /list/
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
[
{
"username": "user1",
"first_name": "Katy",
"last_name": "Smith",
"email": "katysmith#domain.com",
"password": "pbkdf2_sha256$216000$rV8FoNw98RYu$0pdfnA4HO+15o4ov4GZVMXiq0tLNJopfLDV++iPvC5E="
},
{
"username": "user2",
"first_name": "John",
"last_name": "Smith",
"email": "johnsmith#domain.com",
"password": "pbkdf2_sha256$216000$q4wfz8tiFnnF$gmOuN7HJurbEqHykZ221UX8STcG9pAQ8WQTKF+qDtbw="
},
With that backend, I'm creating an app frontend with Kivy. I have a login screen that asks users to input their username and password. My thinking about how should I create a login system (as I'm just a student in programming) is:
Use urllib.request to get the user list;
Loop and check if the username provided is in the list;
Check if the password provided is the password store for that user in that list.
Concerning the logic of this operation, if passwords were stored in plain text, I could simple compare string with the password given by the user. But as they're hashed... how can I do it? How can I check if this hashed password 'match' with the one provided by the user on the login screen?
Also, I would consider a bonus if you can answer this: my login "strategy" is correct? There's a better way to create a login system using this tools I have? If so, how?
When you have a web service that you are using to handle login info then it should be the only one that does hashing and authenticating.
You should NEVER send a list of users and their hashed passwords to the client and then have the client authenticate there password against that list. This is a huge security issue.
Here's how a username and password authentication system works.
Client sends their username and un-hashed password to the server via https to a certain endpoint. eg. mywebsite.com/login
The server receives this request and and retrieves a user with that username if it exists from the database.
You then grab the hashed password for that user from the database as well and you then hash the password sent via https request the same way. And compare the two to see if they match.
If they match you need to send back an api key/authentication token to the client that they will use for all future requests. That api key/authentication token should be stored in the server's database to later be retrieved for requests.
From now on the client sends that api key/authentication token to the server for any requests it needs and the server checks to make sure the key/token is valid and then ignores or processes the request further.
This is a simplified version of the whole process cause there is also salt and peppering a password before hashing. There is expiration times that need to be added to key/tokens so that they dont last forever and other things.
Google around for how authentication systems work and the proper workflow for an authentication system. Hope this helps and #CyberSrikanth referenced a good article to use for getting started.
I am using rest-auth and I want to allow the users reactivate their accounts by their own.
I managed to allow the inactive user to log in by using AllowAllUsersModelBackend in settings.py
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.AllowAllUsersModelBackend",
]
And then I disallowed rest-auth to check respond with an error message by deleting these lines from the LoginSerializer:
if not user.is_active:
msg = _('User account is disabled.')
raise exceptions.ValidationError(msg)
I also customized the UserDetailSerializer to allow deactivation and activation by adding is_active field of the user model.
Now I can log in using a deactivated user and it sends me a JWT back, but when I try to use the /user/ endpoint it respond with that error:
{
"detail": "User account is disabled."
}
I want to allow them to use this endpoint to reactivate their account but without allowing them to use any other custom endpoint that requires authentication.
I am using python-social-auth to log users in to my we application. Everything works as expected to create user accounts, log them in, etc.
Now I am also requesting the publish_actions permission from the user. When I do this, I see the request step when I try to log in, so I know Facebook is being asked for this permission properly. However, I can't figure out how to discover from the response whether the user approved this permission. I want to store this so that I only expose the right parts of the UI based on the user's choice to allow or deny the permission.
Here's how I request the permission:
SOCIAL_AUTH_FACEBOOK_SCOPE = [ 'email', 'publish_actions' ]
And for extra params I have the following:
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id,name,email',
}
I needed to add email to the list to expose the email value returned from FB to my authentication pipeline.
If I try to add publish_actions to this field, the pipeline is interrupted and the authentication is cancelled:
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id,name,email,publish_actions', # <-- this causes a failure in auth pipeline
}
Without publish_actions noted as an extra param, I can't see any other data that indicates whether the user approved the permission. How do I discover this?
You can make a request for /me/permissions/ using the user access token, that will show you which permissions the user has granted to your app.
You can also make the login dialog return the granted scopes directly in the direct URL (see parameter return_scopes) – whether or not that can easily be added to the login dialog from within your framework, I don’t know.
We are working with Google Drive and Permissions API to get e-mail addresses of users with sharing permissions. The API might not return the e-mail address if user forbids this in Google+ profile.
The documentation to Google Drive Permissions API says:
The email address of the user this permission refers to. This is an output-only field which is populated when the permission type is user and the given user's Google+ profile privacy settings allow exposing their email address.
After few hours of searching, we cannot find this "profile privacy settings" in question. Google Account Settings shows no such field.
Anybody knows where it is?
With "profile privacy settings" they mean that the Google + profile have shared the email from the contact information with the profile you are authenticated for the request.
I've made some test with a couple of documents, both shared with "Anyone with the link can view", but the first is from a user that shares with me the email in contact information.
Using the Try It I get the following result:
{
"kind": "drive#permission",
"etag": "\"SQFIsIrlQ4j3H07nwR6GyVXbP4s/4mfL2lpQkyuoRKmfVUHuvQuo5DI\"",
"id": "yyyyyyyyyyyy",
"selfLink": "https://content.googleapis.com/drive/v2/files/1ypzfcjfxIusRz0rLoDYh49DqPUj9DdZJI3lCGLtCkn8/permissions/yyyyyyyyyyyyy",
"name": "NAME Surname",
"emailAddress": "KKKKK.XXXXX#gmail.com",
"domain": "gmail.com",
"role": "owner",
"type": "user",
"photoLink": "https://lh4.googleusercontent.com/-DRgxkD0Vigg/AAAAAAAAAAI/AAAAAAAAZ0g/dszVFwA6bUo/s64/photo.jpg"
}
The second file is from a test account that doesn't share the email with me.
And I get the following:
{
"kind": "drive#permission",
"etag": "\"SQFIsIrlQ4j3H07nwR6GyVXbP4s/eUBKpMiVeQhLf3_Rf4Us5qisOqU\"",
"id": "ooooooooookkkkkkk",
"selfLink": "https://content.googleapis.com/drive/v2/files/1IpGtyYgJ_K6b0Xp2TWuYrcCTfPrIGJoUrStMPCyWGgM/permissions/kkkkkkkkkk",
"name": "lkajdlkj oiuaoiuoi",
"domain": "gmail.com",
"role": "owner",
"type": "user",
"photoLink": "https://lh3.googleusercontent.com/-SUCY0jPNqsA/AAAAAAAAAAI/AAAAAAAAMEk/8Y7SD9VNhHE/s64/photo.jpg"
}
As you can see the emailAddress is not displayed in the second result
To change this setting in your Google+ profile follow this steps (or the official help page):
Go to your account on https://plus.google.com
When the page is loaded in the top left corner, hover to the Home Menu
Click on Profile
Open the About tab of your profile (top center)
Scroll down to the Contact Information and click edit
Home and Work contacts can be shared to different circles or remove all the circles to make the contacts fully private
I have started using https://github.com/omab/django-social-auth and been successfully able to login via twitter, google and facebook.
Needed
I need to query about the logged in user in order to do more things, which Model I shall be using for that?
I don't see any examples for that
Thank you
Update
#Omab, I did not understand how this would work, can you please help. When I login with twitter, the callback goes to following code
#login_required
def done(request):
"""Login complete view, displays user data"""
ctx = {
'version': version,
'last_login': request.session.get('social_auth_last_login_backend')
}
logging.warn('context - ' + str(ctx))
logging.warn('request - ' + str(request))
return render_to_response('home.html', ctx, RequestContext(request))
Can you tell me how can I access to user instance here?
Thank you
The app stores the social account details using the UserSocialAuth model, to retrieve any instance just do:
user.social_auth.filter(provider="...")
Where:
user is a User instance (request.user for current logged in user)
provider is a string with the provider name (facebook, twitter, etc)
The UserSocialAuth instance stores the needed tokens to call the needed API:
print user_social_auth.tokens
{...}
As suggested by K-man, you can try this (Identifying the backend provider of a logged in user):
request.user.social_auth.values_list('provider')
Other values that you can find in the values_list include: id, uid (for ex. facebook user id), user, extra_data (which contains the access_token)