I am trying to redirect the user to next url, if login not successful.
I patched the code to this:
class OAuth2CallbackView(OAuth2View):
def dispatch(self, request):
if 'error' in request.GET or 'code' not in request.GET:
# Distinguish cancel from error
auth_error = request.GET.get('error', None)
if auth_error == self.adapter.login_cancelled_error:
error = AuthError.CANCELLED
else:
error = AuthError.UNKNOWN
return render_authentication_error(
request,
self.adapter.provider_id,
error=error)
app = self.adapter.get_provider().get_app(self.request)
client = self.get_client(request, app)
try:
access_token = client.get_access_token(request.GET['code'])
token = self.adapter.parse_token(access_token)
token.app = app
login = self.adapter.complete_login(request,
app,
token,
response=access_token)
login.token = token
if self.adapter.supports_state:
login.state = SocialLogin \
.verify_and_unstash_state(
request,
request.REQUEST.get('state'))
else:
login.state = SocialLogin.unstash_state(request)
return complete_social_login(request, login)
except (PermissionDenied, OAuth2Error, requests.RequestException) as e:
try:
next_url = SocialLogin.unstash_state(request).get('next', '') # <---- here state is not available anymore, why?
if next_url:
redir_url = '%s&loginerr=y' % next_url.split('&loginerr=y')[0]
else:
raise PermissionDenied()
except PermissionDenied: # <--- thats why, this part gets executed
next_url = request.META.get('HTTP_REFERER', '/')
redir_url = '%s?loginerr=y' % next_url
return redirect(redir_url)
Related
I am new to Django and a small detail has been bothering me.I have an api endpoint that returns the details of one patient. I have made a successful get request and tested on postman. It returns data for a particular patient with id = 996(I have hard coded the id). But I need to set it so it can pick the id from params in postman instead of the hard coded one here. How can I set params and append them on the url so that I use the id fed in postman instead of hard coding? Kindly assist
views.py
class PatientDetailsView(GenericAPIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
#classmethod
#encryption_check
def get(self, request, *args, **kwargs):
try:
result = {}
auth = cc_authenticate()
res = getPatientDetails(auth["key"], id)
result = res
return Response(result, status=status.HTTP_200_OK)
except Exception as e:
error = getattr(e, "message", repr(e))
result["errors"] = error
result["status"] = "error"
return Response(result, status=status.HTTP_400_BAD_REQUEST)
api_service.py
def getPatientDetails(auth, id):
print("getting patientdetails from Callcenter")
try:
print(auth)
# print(url)
id= 996
headers = {
"Authorization": f'Token {auth}'
}
url = f'{CC_URL}/patients/v1/details/?id={id}'
print(url)
res = requests.get(url, headers=headers)
print("returning patientdetails response", res.status_code)
return res.json()
except ConnectionError as err:
print("connection exception occurred")
print(err)
return err
urls.py
path("details/", views.PatientDetailsView.as_view(), name="patient_info"),
This is the code I needed
id = request.GET.get('<id>')
I created the userdefined decorator to check the session is active or not. Following is the function defination
def session_required(func):
"""
Decorator to check the session is active or not for logged in user
:param func: Name of function for which you have to check the session is active or not
:return:
"""
def wrap(request, *args, **kwargs):
"""
Wrapper function for the decorator
:param request: request parameter for called URL
:return:
"""
if not request.session.get("admin_id"):
return redirect("/")
func_return = func(request, *args, **kwargs)
return func_return
return wrap
I am using this decorator on the respective function based view. At some places it works absolutely fine but when I do some POST or PUT operation then it gives me error
Forbidden (CSRF token missing or incorrect.):
My function based view is like
#csrf_exempt
#session_required
def mover_profile_handler(request):
"""
mover profile handler function for viewing and editing the details
:param request:
:return:
"""
try:
if request.method == "GET":
login_id = request.session.get("admin_id")
login_info_obj = Login.objects.get(id=login_id)
mover_info_obj = Mover.objects.get(fk_login=login_info_obj)
country_obj = Country.objects.all()
currency_obj = CurrencyType.objects.all()
subscription_detail = SubscriptionMoverDetail.objects.filter(fk_mover=mover_info_obj).order_by("-id")
# Extracting data for showing the subscription package details
current_subscription_detail = {}
subscription_detail_history = []
for index, item in enumerate(subscription_detail):
subscription_master_detail = SubscriptionMaster.objects.get(id=item.fk_subscription_master_id)
subscription_detail_json = {
"plan_name": subscription_master_detail.subscription_plan_name,
"subscription_start_date": item.subscription_date,
"subscription_end_date": item.subscription_end_date,
"amount_paid": item.amount_paid,
"users": subscription_master_detail.customer_permitted_count
}
if index == 0:
current_subscription_detail = subscription_detail_json
else:
subscription_detail_history.append(subscription_detail_json)
return render(request, "mover_profile.html", {
"mover_info_obj": mover_info_obj,
"country_obj": country_obj,
"currency_obj": currency_obj,
"login_info_obj": login_info_obj,
"current_subscription_detail": current_subscription_detail,
"subscription_detail_history": subscription_detail_history
})
elif request.method == "PUT":
request = convert_method_put_to_post(request)
mover_id = request.POST.get("id")
if Mover.objects.filter(id=mover_id).exists():
mover_info_obj = Mover.objects.get(id=mover_id)
mover_info_obj.mover_name = request.POST.get("name")
mover_info_obj.address = request.POST.get("address")
mover_info_obj.phone_no = request.POST.get("phone")
mover_info_obj.mover_size = request.POST.get("size")
mover_info_obj.reg_no = request.POST.get("reg_no")
mover_info_obj.website = request.POST.get("website")
mover_info_obj.fk_country_id = request.POST.get("country")
mover_info_obj.fk_currency_id = request.POST.get("currency")
operational_countries = request.POST.getlist("operational_countries[]")
mover_info_obj.countries_in_operation.set(operational_countries)
mover_info_obj.save()
return HttpResponse("success")
except Exception as e:
error_save(str(traceback.format_exc()))
return redirect('error_handler_500')
I tried with
#csrf_protect #csrf_exempt
in view and also tried {% csrf_token %} in html file
without using #session_required code is working absolutely fine.
So please tell me what is wrong with this stuff!!
I'm trying to authorize from my djano-app on vk.com. I'm using requests and client authorization. I'm trying to authorize by this way and getting an error:
{"error":"invalid_request","error_description":"Security Error"}
Internet suggests to re-login on VK in browser, but there isn't any solution for authorization from code.
My code:
class VkApiSingleton(object):
api_version = '5.95'
def __init__(self,
app_id=config.APP_ID,
login=config.ACCOUNT_LOGIN,
pswd=config.ACCOUNT_PASSWORD,
permissions='video,offline,groups'
):
# type: (int, str, str, str) -> None
self.app_id = app_id
self.app_user_login = login
self.app_user_pass = pswd
self.access_token = None
self.user_id = None
self.session = requests.Session()
self.form_parser = FormParser()
self.permissions = permissions
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = super(VkApiSingleton, cls).__new__(cls, *args, **kwargs)
return cls.instance
#property
def get_session(self):
return self.session
def _parse_form(self, response):
# type: (requests.models.Response) -> None
self.form_parser = FormParser()
try:
self.form_parser.feed(str(response.content))
except Exception as err:
logger.exception(
'Error checking HTML form',
extra={'Error body': str(err)}
)
def _submit_form(self, **kwargs):
# type: (dict) -> requests.models.Response
if self.form_parser.method == 'post':
payload = copy.deepcopy(self.form_parser.params)
if kwargs.get('is_login', False):
payload.update({
'email': self.app_user_login,
'pass': self.app_user_pass
})
with self.get_session as session:
try:
return session.post(self.form_parser.url, data=payload)
except Exception as err:
logger.exception(
'Error submitting auth form',
extra={'Error body': str(err)}
)
raise VkApiError('Error submitting auth form: %s' % str(err))
def _log_in(self):
# type: () -> requests.models.Response
response = self._submit_form(is_login=True)
self._parse_form(response)
if response.status_code != 200:
raise VkApiError('Auth error: cant parse HTML form')
if 'pass' in response.text:
logger.error(
'Wrong login or password'
)
raise VkApiError('Wrong login or password')
return response
def _submit_permissions(self, url=None):
# type: () -> requests.models.Response
if 'submit_allow_access' in self.form_parser.params and 'grant_access' in self.form_parser.url:
return self._submit_form(token_url=url)
else:
logger.warning(
'Cant submit permissions for application'
)
def _get_token(self, response):
# type: (requests.models.Response) -> None
try:
params = response.url.split('#')[1].split('&')
self.access_token = params[0].split('=')[1]
self.user_id = params[2].split('=')[1]
except IndexError as err:
logger.error(
'Cant get access_token',
extra={'Error body': str(err)}
)
def auth(self):
auth_url = 'https://oauth.vk.com/authorize?revoke=1'
redirect_uri = 'https://oauth.vk.com/blank.html'
display = 'wap'
request_params = {
'client_id': self.app_id,
'scope': self.permissions,
'redirect_uri': redirect_uri,
'display': display,
'response_type': 'token',
'v': self.api_version
}
with self.get_session as session:
response = session.get(
auth_url,
params=request_params
)
self._parse_form(response)
if not self.form_parser.form_parsed:
raise VkApiError('Invalid HTML form. Check auth_url or params')
else:
login_response = self._log_in()
permissions_response = self._submit_permissions()
self._get_token(login_response)
If someone has a similar problem - I found some reasons of this.
1) Invalid type of authorization - try to use another type of authorization (it describes in official documentation)
2) Too many authorizations.
I solved problem like this:
1) Get token with "offline" permission by "Client Application Authorization"
2) Every time I need to use vk.api method - I am checking my token for expiring with secure method "secure.checkToken" (you need to get Service token to use this method. There are a lot of information in official documentation)
3) If my token expires - i am getting the new one.
I am using Vimeo's API for the users of my app to upload videos, or replace their existing video with a new one. I am using a Vimeo Client to help me make the calls in my Django Application. Uploading works without any issues, but when I try to replace an existing video with a new one, the thumbnail stays as the old video. If you play the video, it will play the new one, but the thumbnail never changes.
Model Method that Uploads/Replaces
def vimeo_upload(self):
media_file = self.video_file
if media_file and os.path.exists(media_file.path):
v = vimeo.VimeoClient(token=settings.VIMEO_ACCESS_TOKEN, key=settings.VIMEO_API_KEY,
secret=settings.VIMEO_API_SECRET)
if self.video_url is None:
try:
video_uri = v.upload(media_file.path)
except AssertionError as exc:
logging.error('Vimeo Error: %s Video: %s' % (exc, media_file.path))
else:
self.video_url = video_uri
else:
try:
v.replace(video_uri=self.video_url, filename=media_file.path)
except Exception as exc:
self.video_url = None
logging.error('Vimeo Replace Error: %s Video: %s' % (exc, media_file.path))
# set the video title, description, etc.
if self.video_url:
try:
# convert locale from en-us form to en
v.patch(self.video_url, data={'description': self.customer.full_name, })
except Exception as exc:
logging.error('Vimeo Patch Error: %s Video: %s' % (exc, media_file.path))
Vimeo Client Model, and UploadVideoMixin
class UploadVideoMixin(object):
"""Handle uploading a new video to the Vimeo API."""
UPLOAD_ENDPOINT = '/me/videos'
REPLACE_ENDPOINT = '{video_uri}/files'
def upload(self, filename, upgrade_to_1080=False):
"""Upload the named file to Vimeo."""
ticket = self.post(
self.UPLOAD_ENDPOINT,
data={'type': 'streaming',
'upgrade_to_1080': 'true' if upgrade_to_1080 else 'false'},
params={'fields': 'upload_link,complete_uri'})
return self._perform_upload(filename, ticket)
def replace(self, video_uri, filename, upgrade_to_1080=False):
"""Replace the video at the given uri with the named source file."""
uri = self.REPLACE_ENDPOINT.format(video_uri=video_uri)
ticket = self.put(
uri,
data={'type': 'streaming',
'upgrade_to_1080': 'true' if upgrade_to_1080 else 'false'},
params={'fields': 'upload_link,complete_uri'})
return self._perform_upload(filename, ticket)
def _perform_upload(self, filename, ticket):
"""Take an upload ticket and perform the actual upload."""
if ticket.status_code != 201:
raise UploadTicketCreationFailure(ticket, "Failed to create an upload ticket")
ticket = ticket.json()
# Perform the actual upload.
target = ticket['upload_link']
last_byte = 0
# Try to get size of obj by path. If provided obj is not a file path
# find the size of file-like object.
try:
size = os.path.getsize(filename)
with io.open(filename, 'rb') as f:
while last_byte < size:
try:
self._make_pass(target, f, size, last_byte)
except requests.exceptions.Timeout:
# If there is a timeout here, we are okay with it, since
# we'll check and resume.
pass
last_byte = self._get_progress(target, size)
except TypeError:
size = len(filename.read())
f = filename
while last_byte < size:
try:
self._make_pass(target, f, size, last_byte)
except requests.exceptions.Timeout:
# If there is a timeout here, we are okay with it, since
# we'll check and resume.
pass
last_byte = self._get_progress(target, size)
# Perform the finalization and get the location.
finalized_resp = self.delete(ticket['complete_uri'])
if finalized_resp.status_code != 201:
raise VideoCreationFailure(finalized_resp, "Failed to create the video")
return finalized_resp.headers.get('Location', None)
def _get_progress(self, upload_target, filesize):
"""Test the completeness of the upload."""
progress_response = self.put(
upload_target,
headers={'Content-Range': 'bytes */*'})
range_recv = progress_response.headers.get('Range', None)
_, last_byte = range_recv.split('-')
return int(last_byte)
def _make_pass(self, upload_target, f, size, last_byte):
"""Make a pass at uploading.
This particular function may do many things. If this is a large upload
it may terminate without having completed the upload. This can also
occur if there are network issues or any other interruptions. These
can be recovered from by checking with the server to see how much it
has and resuming the connection.
"""
response = self.put(
upload_target,
timeout=None,
headers={
'Content-Length': str(size),
'Content-Range': 'bytes: %d-%d/%d' % (last_byte, size, size)
}, data=f)
if response.status_code != 200:
raise VideoUploadFailure(response, "Unexpected status code on upload")
class VimeoClient(ClientCredentialsMixin, AuthorizationCodeMixin, UploadMixin):
"""Client handle for the Vimeo API."""
API_ROOT = "https://api.vimeo.com"
HTTP_METHODS = set(('head', 'get', 'post', 'put', 'patch', 'options', 'delete'))
ACCEPT_HEADER = "application/vnd.vimeo.*;version=3.2"
USER_AGENT = "pyvimeo 0.3.10; (http://developer.vimeo.com/api/docs)"
def __init__(self, token=None, key=None, secret=None, *args, **kwargs):
"""Prep the handle with the authentication information."""
self.token = token
self.app_info = (key, secret)
self._requests_methods = dict()
# Make sure we have enough info to be useful.
assert token is not None or (key is not None and secret is not None)
# Internally we back this with an auth mechanism for Requests.
#property
def token(self):
return self._token.token
#token.setter
def token(self, value):
self._token = _BearerToken(value) if value else None
def __getattr__(self, name):
"""This is where we get the function for the verb that was just
requested.
From here we can apply the authentication information we have.
"""
if name not in self.HTTP_METHODS:
raise AttributeError("%r is not an HTTP method" % name)
# Get the Requests based function to use to preserve their defaults.
request_func = getattr(requests, name, None)
if request_func is None:
raise AttributeError(
"%r could not be found in the backing lib" % name
)
#wraps(request_func)
def caller(url, jsonify=True, **kwargs):
"""Hand off the call to Requests."""
headers = kwargs.get('headers', dict())
headers['Accept'] = self.ACCEPT_HEADER
headers['User-Agent'] = self.USER_AGENT
if jsonify \
and 'data' in kwargs \
and isinstance(kwargs['data'], (dict, list)):
kwargs['data'] = json.dumps(kwargs['data'])
headers['Content-Type'] = 'application/json'
kwargs['timeout'] = kwargs.get('timeout', (1, 30))
kwargs['auth'] = kwargs.get('auth', self._token)
kwargs['headers'] = headers
if not url[:4] == "http":
url = self.API_ROOT + url
response = request_func(url, **kwargs)
if response.status_code == 429:
raise APIRateLimitExceededFailure(
response, 'Too many API requests'
)
return response
return caller
class _BearerToken(requests.auth.AuthBase):
"""Model the bearer token and apply it to the request."""
def __init__(self, token):
self.token = token
def __call__(self, request):
request.headers['Authorization'] = 'Bearer ' + self.token
return request
I am trying to implement a Twitter sign in using Django Social Auth. I have added a partial pipeline where I gather extra details from the user using a form (DOB, email, etc).
My problem is that I want to skip this pipeline if the user already exists. However, when I try to do this I get an AuthTokenError "Token error: Missing unauthorized token" and I cannot figure out why.
Here is code that is causing a problem:
def gather_extra_data(backend, details, uid, request, user=None, *args, **kwargs):
social_user = UserSocialAuth.get_social_auth(backend.name, uid)
if social_user:
return redirect('socialauth_complete', backend.name)
if not details.get('email'):
if not request.session.get('saved_email'):
return redirect(request_extra, backend=backend.name)
else:
details['email'] = request.session['saved_email']
details['password'] = request.session['password']
details['first_name'] = request.session['first_name']
details['last_name'] = request.session['last_name']
details['dob'] = request.session['dob']
details['gender'] = request.session['gender']
details['avatar_url'] = request.session['avatar_url']
You should put your pipeline entry after the user is created and the social account is associated (after social_auth.backends.pipeline.social.associate_user entry), then you can try with this code:
def gather_extra_data(social_auth, user, details, request, is_new=False, *args, **kwargs):
if is_new:
if request.session.get('saved_email') is None:
return redirect(request_extra, backend=backend.name)
else:
details['email'] = request.session['saved_email']
details['password'] = request.session['password']
details['first_name'] = request.session['first_name']
details['last_name'] = request.session['last_name']
details['dob'] = request.session['dob']
details['gender'] = request.session['gender']
details['avatar_url'] = request.session['avatar_url']
Remember to put social_auth.backends.pipeline.misc.save_status_to_session before your entry.
Try this way:
def gather_extra_data(backend, details, uid, request, user=None, is_new=False, *args, **kwargs):
If not user is None and is_new: #is_new is your missing argument.
if not details.get('email'):
if not request.session.get('saved_email'):
return redirect(request_extra, backend=backend.name)
else:
details['email'] = request.session['saved_email']
details['password'] = request.session['password']
details['first_name'] = request.session['first_name']
details['last_name'] = request.session['last_name']
details['dob'] = request.session['dob']
details['gender'] = request.session['gender']
details['avatar_url'] = request.session['avatar_url']