django 2 custom jwt_get_username_from_payload_handler - django

To validate the jwt token of auth0 in django, I use the following code in settings.py
def jwt_get_username_from_payload_handler(payload):
return 'authuser'
JWT_AUTH = {
'JWT_PAYLOAD_GET_USERNAME_HANDLER': jwt_get_username_from_payload_handler,
'JWT_PUBLIC_KEY': PUBLIC_KEY,
'JWT_ALGORITHM': 'RS256',
'JWT_AUDIENCE': API_IDENTIFIER,
'JWT_ISSUER': JWT_ISSUER,
'JWT_AUTH_HEADER_PREFIX': 'Bearer',
}
where authuser is the username. So Instead of writing it directly I want to receive it in request header and pass it. Please help me in customising this function - jwt_get_username_from_payload_handler in such a way. TIA

def jwt_get_username_from_payload_handler(user):
return {
'username': user.username,
'email': user.email,
'is_superuser': user.is_superuser,
}
you can use this function

Related

Creating a Apache superset user through API

I want to create user through apache superset API if user already exist it should show message.
import requests
payload = { 'username': 'My user name',
'password': 'my Password',
'provider': 'db'
}
base_url="http://0.0.0.0:8088"
login_url =f"{base_url}/api/v1/security/login"
login_response =requests.post(login_url,json=payload)
access_token = login_response.json()
print(access_token)
# header
header = {"Authorization":f"Bearer {access_token.get('access_token')}"}
base_url="http://0.0.0.0:8088" # apache superset is running in my local system on port 8088
user_payload={
'first_name': "Cp",
'last_name': "user",
'username':"A",
'email': "user.#gmail.com",
'active': True,
'conf_password': "user#1",
'password': "user#1",
"roles":["Dashboard View"]
}
users_url = f"{base_url}/users/add"
user_response= requests.get(users_url, headers=header)
print(user_response)
print(user_response.text)
user_response = user_response.json()
print(user_response)
I tried to create user through mentioned API, some time it gives 200 success message, but after checking in apache superset website i can not see created user details.
If i am using the wrong API endpoint or wrong methods to create user please suggest me.

How to create an account/login using google api client in django for android

I want to implement the same scenario for use in Android Kotlin which is given in this url.
For Web Application
I have created login with google for web application by follow this link. Here is my Google Login View in views.py for access token (as one user have explained here )
class GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
And It's working for me as I expected.
For Android Application
Now, Somehow I have managed a code for this google scenario.
Here is my Google Client login View.view.py code
class GoogleClientView(APIView):
def post(self, request):
token = {'id_token': request.data.get('id_token')}
print(token)
try:
# Specify the CLIENT_ID of the app that accesses the backend:
idinfo = id_token.verify_oauth2_token(token['id_token'], requests.Request(), CLIENT_ID)
print(idinfo)
if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
raise ValueError('Wrong issuer.')
return Response(idinfo)
except ValueError as err:
# Invalid token
print(err)
content = {'message': 'Invalid token'}
return Response(content)
When I am requesting POST method with IdToken then this is providing below information and ofcourse we need this.
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}
Till here, everything is working good for me.But here I want to create account/login for a the user using above info and when account/login is created then need a key in return response.
below What I had tried
class GoogleClientView(APIView):
permission_classes = [AllowAny]
adapter_class = GoogleOAuth2Adapter
callback_url = 'https://example.com/user/accounts/google/login/callback/'
client_class = OAuth2Client
def post(self, request):
token = {'id_token': request.data.get('id_token')}
print(token)
try:
# Specify the CLIENT_ID of the app that accesses the backend:
idinfo = id_token.verify_oauth2_token(token['id_token'], requests.Request(), CLIENT_ID)
print(idinfo)
if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
raise ValueError('Wrong issuer.')
return Response(idinfo)
except ValueError as err:
# Invalid token
print(err)
content = {'message': 'Invalid token'}
return Response(content)
Again It seems it's not creating any account/login for user and no key is getting in response.
So, for creating account/login, How can I implement the code?
Please ask for more information If I forgot to put any.

How to configure the JWT token in django-graphql-jwt to obtain the userId in the token instead of just the username?

TLDR - But by default the JWT token sent from the backend only includes the username. I want the userId as well.This is what it contains currently:-
HEADER:ALGORITHM & TOKEN TYPE
{
"typ": "JWT",
"alg": "HS256"
}
PAYLOAD:DATA
{
"username": "admin", <---- I have the username already. Need the userId as well!
"exp": 1621845856,
"origIat": 1621845556
}
VERIFY SIGNATURE
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
) secret base64 encoded
I have a Django GraphQL API (using Graphene, django-graphql-auth, django-graphql-jwt) and an Angular frontend. I have authentication setup fully. Now the issue I'm facing is that I'm storing the token in the localstorage and so when the user opens the browser again, I want to verify that token and use just the information in there to obtain the user's id and then use that userId to fetch their user profile information, which is an essential step to complete the login process.
I am not sure how to customize the payload to include the userId as well. So that when the user opens the browser after shutting down, I can simply use just the information in the token to fully log them in. I'm very new to both Python and Django. I couldn't find the process detailed anywhere online, maybe I wasn't looking for the right thing or in the right place. Detailed instructions would be very helpful.
The following is a more thorough reproduction of solution found here.
We basically need to override the jwt_payload method that comes as part of the graphql_jwt package.
Add this to project's settings.py
GRAPHQL_JWT = {
'JWT_PAYLOAD_HANDLER': 'common.utils.jwt_payload',
}
Create the following files in a folder common in the same directory where you have the manage.py file.
Inside, create the following two files:-
Here's where we're adding the user_id in the sub attribute.
utils.py
from calendar import timegm
from datetime import datetime
from .settings import jwt_settings
def jwt_payload(user, context=None):
username = user.get_username()
user_id = str(user.id)
if hasattr(username, 'pk'):
username = username.pk
payload = {
user.USERNAME_FIELD: username,
'sub': user_id,
'exp': datetime.utcnow() + jwt_settings.JWT_EXPIRATION_DELTA,
}
if jwt_settings.JWT_ALLOW_REFRESH:
payload['origIat'] = timegm(datetime.utcnow().utctimetuple())
if jwt_settings.JWT_AUDIENCE is not None:
payload['aud'] = jwt_settings.JWT_AUDIENCE
if jwt_settings.JWT_ISSUER is not None:
payload['iss'] = jwt_settings.JWT_ISSUER
return payload
This settings.py file inside the common folder is just a dependency. for the utils.py.
settings.py
from datetime import timedelta
from importlib import import_module
from django.conf import settings
from django.contrib.auth import get_user_model
from django.test.signals import setting_changed
DEFAULTS = {
'JWT_ALGORITHM': 'HS256',
'JWT_AUDIENCE': None,
'JWT_ISSUER': None,
'JWT_LEEWAY': 0,
'JWT_SECRET_KEY': settings.SECRET_KEY,
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': False,
'JWT_EXPIRATION_DELTA': timedelta(seconds=60 * 5),
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=7),
'JWT_LONG_RUNNING_REFRESH_TOKEN': False,
'JWT_REFRESH_TOKEN_MODEL': 'refresh_token.RefreshToken',
'JWT_REFRESH_TOKEN_N_BYTES': 20,
'JWT_AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_ALLOW_ARGUMENT': False,
'JWT_ARGUMENT_NAME': 'token',
'JWT_ENCODE_HANDLER': 'graphql_jwt.utils.jwt_encode',
'JWT_DECODE_HANDLER': 'graphql_jwt.utils.jwt_decode',
'JWT_PAYLOAD_HANDLER': 'graphql_jwt.utils.jwt_payload',
'JWT_PAYLOAD_GET_USERNAME_HANDLER': (
lambda payload: payload.get(get_user_model().USERNAME_FIELD)
),
'JWT_GET_USER_BY_NATURAL_KEY_HANDLER':
'graphql_jwt.utils.get_user_by_natural_key',
'JWT_REFRESH_EXPIRED_HANDLER': 'graphql_jwt.utils.refresh_has_expired',
'JWT_GET_REFRESH_TOKEN_HANDLER':
'graphql_jwt.refresh_token.utils.get_refresh_token_by_model',
'JWT_ALLOW_ANY_HANDLER': 'graphql_jwt.middleware.allow_any',
'JWT_ALLOW_ANY_CLASSES': (),
'JWT_COOKIE_NAME': 'JWT',
'JWT_REFRESH_TOKEN_COOKIE_NAME': 'JWT-refresh-token',
'JWT_COOKIE_SECURE': False,
}
IMPORT_STRINGS = (
'JWT_ENCODE_HANDLER',
'JWT_DECODE_HANDLER',
'JWT_PAYLOAD_HANDLER',
'JWT_PAYLOAD_GET_USERNAME_HANDLER',
'JWT_GET_USER_BY_NATURAL_KEY_HANDLER',
'JWT_REFRESH_EXPIRED_HANDLER',
'JWT_GET_REFRESH_TOKEN_HANDLER',
'JWT_ALLOW_ANY_HANDLER',
'JWT_ALLOW_ANY_CLASSES',
)
def perform_import(value, setting_name):
if isinstance(value, str):
return import_from_string(value, setting_name)
if isinstance(value, (list, tuple)):
return [import_from_string(item, setting_name) for item in value]
return value
def import_from_string(value, setting_name):
try:
module_path, class_name = value.rsplit('.', 1)
module = import_module(module_path)
return getattr(module, class_name)
except (ImportError, AttributeError) as e:
msg = 'Could not import `{}` for JWT setting `{}`. {}: {}.'.format(
value, setting_name, e.__class__.__name__, e,
)
raise ImportError(msg)
class JWTSettings:
def __init__(self, defaults, import_strings):
self.defaults = defaults
self.import_strings = import_strings
self._cached_attrs = set()
def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError('Invalid setting: `{}`'.format(attr))
value = self.user_settings.get(attr, self.defaults[attr])
if attr == 'JWT_ALLOW_ANY_CLASSES':
value = list(value) + [
'graphql_jwt.mixins.JSONWebTokenMixin',
'graphql_jwt.mixins.VerifyMixin',
'graphql_jwt.refresh_token.mixins.RevokeMixin',
]
if attr in self.import_strings:
value = perform_import(value, attr)
self._cached_attrs.add(attr)
setattr(self, attr, value)
return value
#property
def user_settings(self):
if not hasattr(self, '_user_settings'):
self._user_settings = getattr(settings, 'GRAPHQL_JWT', {})
return self._user_settings
def reload(self):
for attr in self._cached_attrs:
delattr(self, attr)
self._cached_attrs.clear()
if hasattr(self, '_user_settings'):
delattr(self, '_user_settings')
def reload_settings(*args, **kwargs):
setting = kwargs['setting']
if setting == 'GRAPHQL_JWT':
jwt_settings.reload()
setting_changed.connect(reload_settings)
jwt_settings = JWTSettings(DEFAULTS, IMPORT_STRINGS)

AnonymousUser with django.test.client.login()

I'm testing login function.
def setUpClass(cls):
super(BasePage_loggedin, cls).setUpClass()
cls.selenium = WebDriver()
cls.client = Client()
cls.user_1 = MyUser.objects.create_user(username='myself',password='12345')
cls.client.login(username=cls.user_1.username, password=cls.user_1.password)
# create session cookie:
session = SessionStore()
session[SESSION_KEY] = cls.user_1.pk
session[BACKEND_SESSION_KEY] = settings.AUTHENTICATION_BACKENDS[0]
session[HASH_SESSION_KEY] = cls.user_1.get_session_auth_hash()
session.save()
# Finally, create the cookie dictionary
cookie = {
'name': settings.SESSION_COOKIE_NAME,
'value': session.session_key,
'secure': False,
'path': '/',
}
# add the session cookie
cls.selenium.get('{}'.format(cls.live_server_url))
cls.selenium.add_cookie(cookie)
cls.selenium.refresh()
cls.selenium.get('{}'.format(cls.live_server_url))
So I can pass the login page, but then, when I do request.user to check the data for this user, it's an AnonymousUser
When you're creating the user that way - I believe it has to do with the password. Setting the password to a string like that doesn't do what you think it would do.
You could create the user like that - then add this after the user creation but before the login:
cls.user_1.set_password('12345')
cls.user_1.save()
Then login the user with something like this:
cls.client.login(username=cls.user_1.username, password='12345')
I believe it has something to do with the hashing of the password or something along those lines - it's been a while since I stumbled around with it, but I remember having the exact same issue as you.
Something like this should work:
cls.selenium = WebDriver()
cls.client = Client()
cls.user_1 = MyUser.objects.create_user(username='myself',password='12345')
cls.user_1.set_password('12345')
cls.user_1.save()
cls.client.login(username=cls.user_1.username, password='12345')
Please check your settings.py and try below codes.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication', # needed only up to the test env
'rest_framework.authentication.TokenAuthentication',
)
}

django test for upload image

i want to test user registration but i can't test image here is my test:
test.py
response = self.client.post('/api/v1/signup/',
content_type='application/json',
data=json.dumps({"username": "casino", "email": "casinoluxwin#gmail.com",
"password1": "android12", "password2": "android12", "photo": {
'real_filename': "u'banner3.jpg'",
'path': "u'C:/Users/Dima/Desktop'"}
}))
self.assertEqual(response.status_code, 200)
i get code 400(bad request), but without photo my test pass
service/users.py
#validate_input({
'username': {'min_length': 3, 'max_length': 50},
'email': {'validation_type': "email", 'max_length': 50},
'password1': {'min_length': 8, 'max_length': 50},
'password2': {'min_length': 8, 'equal_to': 'password1',
'messages': {'equal_to': _(u"Пароли не совпадают")}},
'photo': {'required': True}
})
#transaction.atomic
def signup(self, data):
user_data = {
'username': data['username'],
'email': data['email'],
'password': data['password1'],
'coins_amount': 0
}
user = self._create_user(user_data)
if data.get("photo"):
self._attach_photo(user, data["photo"])
obj, created = VerificationCode.objects.get_or_create(user=user, code_type="registration")
obj.create_expiration_date()
obj.create_code()
obj.save()
return user.id
So i want to test user photo anything else works fine. Thanks for any help
Problem probably resides in either Users._attach_photo() or your user model. Not enough information here to decipher it entirely. There are a couple of things to try.
I'd write a normal unittest that does not use the client. It'll give you a more helpful traceback than just the HTTP status code from the running server. Something like:
def test_user_add_method(self):
x = Users.signup(json.dumps({"username": "casino", "email": "casinoluxwin#gmail.com",
"password1": "android12", "password2": "android12", "photo": {
'real_filename': "u'banner3.jpg'",
'path': "u'C:/Users/Dima/Desktop'"})
Users.get(pk=x) #will fail if user was not created.
Second, try commenting out your validator. 400 bad request could easily be kicked off by that. It is possible that your validator isn't playing nice with the image and you'll have to mess around with that.