How do you authenticate a websocket connection with Knox token authentication on django channels? - authentication

I understand you can write custom authentication middleware to use in django channels 2.
This works fine with Django's built-in token authentication but using django-rest-knox tokens is a different story.
Knox stores its tokens in an encrypted form so it is not as easy as simply retrieving the user from the database by looking up the token.
Please help.

Figured it out!
from knox.auth import TokenAuthentication
...
knoxAuth = TokenAuthentication();
user, auth_token = knoxAuth.authenticate_credentials(tokenString.encode(HTTP_HEADER_ENCODING))
scope['user'] = user
Integrate the above code with: https://gist.github.com/rluts/22e05ed8f53f97bdd02eafdf38f3d60a

In order to be able to authenticate a user using token authentication, you must use cookies, The headers you can send using WS are limited, you must also implement your own "TokenAuthMiddleware" to handle the cookie. for channels 2, you also have to handle access to the database correctly, below is how to do that:
from channels.auth import AuthMiddlewareStack
from channels.db import database_sync_to_async
from knox.auth import TokenAuthentication
from django.contrib.auth.models import AnonymousUser
from django.db import close_old_connections
from rest_framework.exceptions import AuthenticationFailed
import re
class TokenAuthMiddlewareInstance :
def __init__ (
#
self ,
scope ,
middleware ,
):
self.middleware = middleware
self.scope = dict(scope)
self.inner = self.middleware.inner
async def __call__ (
#
self ,
receive ,
send ,
):
self.scope['user'] = AnonymousUser()
cookie = dict(self.scope.get('headers',{})).get(b'cookie')
if cookie :
token = re.findall(r'X-Authorization=(\w*)', cookie.decode('ascii'))
if len(token) :
self.scope['user'] = await self._g_user(token)
inner = self.inner(self.scope)
return await inner(receive, send)
#database_sync_to_async
def _g_user (
#
self ,
token ,
):
try :
token_key = token[0]
user, token = TokenAuthentication().authenticate_credentials(token_key.encode('ascii'))
close_old_connections()
return user
except AuthenticationFailed as e :
return AnonymousUser()
class TokenAuthMiddleware :
def __init__ (
#
self ,
inner ,
):
self.inner = inner
def __call__ (
#
self ,
scope ,
):
return TokenAuthMiddlewareInstance(scope, self)
TokenAuthMiddlewareStack = lambda inner: TokenAuthMiddleware(AuthMiddlewareStack(inner))

Related

Getting error in a python script when using QuickSight API calls to retrieve the value of user parameter selection

I am working on a python script which will use QS APIs to retrieve the user parameter selections but keep getting the below error:
parameters = response['Dashboard']['Parameters'] KeyError: 'Parameters'
If I try a different code to retrieve the datasets in my QS account, it works but the Parameters code doesn't. I think I am missing some configuration.
#Code to retrieve the parameters from a QS dashboard (which fails):
import boto3
quicksight = boto3.client('quicksight')
response = quicksight.describe_dashboard(
AwsAccountId='99999999999',
DashboardId='zzz-zzzz-zzzz'
)
parameters = response['Dashboard']['Parameters']
for parameter in parameters:
print(parameter['Name'], ':', parameter['Value'])
#Code to display the datasets in the QS account (which works):
import boto3
import json
account_id = '99999999999'
session = boto3.Session(profile_name='default')
qs_client = session.client('quicksight')
response = qs_client.list_data_sets(AwsAccountId = account_id,MaxResults = 100)
results = response['DataSetSummaries']
while "NextToken" in response.keys():
response = qs_client.list_data_sets(AwsAccountId = account_id,MaxResults = 100,NextToken=response["NextToken"])
results.extend(response["DataSetSummaries"])
for i in results:
x = i['DataSetId']
try:
response = qs_client.describe_data_set(AwsAccountId=account_id,DataSetId=x)
print("succeeded loading: {} for data set {} ".format(x, response['DataSet']['Name']))
except:
print("failed loading: {} ".format(x))

Encrypted access token request to google api failed with 400 code

Recently I come up a scenario where I need to encrypt a WEB API request and response using PyCryptodome inside Synapse notebook activity. I am trying to make a call to Google API, but the request should be encrypted and similarly response should be encrypted. After making the call with encrypted data, I am getting below error.
Error:
error code: 400, message: Invalid JSON Payload received. Unexpected Token, Status: Invalid argument.
I have written below code:-
import os
import requests
import json
import base64
from Crypto import Random
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.padding import pad,unpad
import secrets
key= os.urandom(16)
iv = Random.new().read(AES.block_size)
def encrypt_data(key, data):
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted_data = base64.b64encode(cipher.encrypt(pad(data)))
return encrypted_data
url = "https://accounts.google.com/o/oauth2/token"
client_Id = "XXXXX"
client_secret = "YYYYY"
grant_type = "refresh_token"
refresh_token = "ZZZZZZ"
access_type="offline"
data = {"grant_type":grant_type,
"client_id":client_Id,
"client_secret":client_secret,
"refresh_token":refresh_token,
"access_type":access_type
}
encode_data = json.dumps(data).encode("utf-8")
encrypt_data = encrypt_data(key,encode_data)
response = requests.post(url, data = encrypt_data)
print(response.content)
It would be really helpful if someone can give me idea or guide me on how I can achieve this.
Thank You!

Google people API returning empty / no results in Python

I'm trying to read contacts from my person gmail account and the instructions provided by Google from the People API is returning an empty list. I'm not sure why. I've tried another solution from a few years ago, but that doens't seem to work. I've pasted my code below. Any help troubleshooting this is appreciated!
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/contacts.readonly']
from google.oauth2 import service_account
SERVICE_ACCOUNT_FILE = '<path name hidden>.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
def main():
#Shows basic usage of the People API.
#Prints the name of the first 10 connections.
creds = None
service = build('people', 'v1', credentials=credentials)
# Call the People API
print('List 10 connection names')
results = service.people().connections().list(
resourceName='people/me',
pageSize=10,
personFields='names,emailAddresses').execute()
connections = results.get('connections', [])
request = service.people().searchContacts(pageSize=10, query="A", readMask="names")
results = service.people().connections().list(resourceName='people/me',personFields='names,emailAddresses',fields='connections,totalItems,nextSyncToken').execute()
for i in results:
print ('result', i)
for person in connections:
names = person.get('names', [])
if names:
name = names[0].get('displayName')
print(name)
if __name__ == '__main__':
main()

how to get channel's members count with telegram api

I want to get a channel's members' count but I don't know which method should I use?
I am not admin in that channel, I just want to get the count number.
EDIT:I am using main telegram api, not telegram Bot api
You can use getChatMembersCount method.
Use this method to get the number of members in a chat.
It worked for me :)
from telethon import TelegramClient, sync
from telethon.tl.functions.channels import GetFullChannelRequest
api_id = API ID
api_hash = 'API HASH'
client = TelegramClient('session_name', api_id, api_hash)
client.start()
if (client.is_user_authorized() == False):
phone_number = 'PHONE NUMBER'
client.send_code_request(phone_number)
myself = client.sign_in(phone_number, input('Enter code: '))
channel = client.get_entity('CHANNEL LINK')
members = client.get_participants(channel)
print(len(members))
It is possible to do it also through GetFullChannelRequest in telethon
async def main():
async with client_to_manage as client:
full_info = await client(GetFullChannelRequest(channel="moscowproc"))
print(f"count: {full_info.full_chat.participants_count}")
if __name__ == '__main__':
client_to_manage.loop.run_until_complete(main())
or to write it without async/await
def main():
with client_to_manage as client:
full_info = client.loop.run_until_complete(client(GetFullChannelRequest(channel="moscowproc")))
print(f"count: {full_info.full_chat.participants_count}")
if __name__ == '__main__':
main()
Also as above was said, it is also feasible by bot-api with
getChatMembersCount method. You can curl it or use python to query needed url
with python code can look like this one:
import json
from urllib.request import urlopen
url ="https://api.telegram.org/bot<your-bot-api-token>/getChatMembersCount?chat_id=#<channel-name>"
with urlopen(url) as f:
resp = json.load(f)
print(resp['result'])
where <your-bot-api-token> is token provided by BotFather, and <channel-name> is channel name which amount of subscribers you want to know (of course, everything without "<>")
to check firstly, simply curl it:
curl https://api.telegram.org/bot<your-bot-api-token>/getChatMembersCount?chat_id=#<channel-name>

Google Reader API Unread Count

Does Google Reader have an API and if so, how can I get the count of the number of unread posts for a specific user knowing their username and password?
This URL will give you a count of unread posts per feed. You can then iterate over the feeds and sum up the counts.
http://www.google.com/reader/api/0/unread-count?all=true
Here is a minimalist example in Python...parsing the xml/json and summing the counts is left as an exercise for the reader:
import urllib
import urllib2
username = 'username#gmail.com'
password = '******'
# Authenticate to obtain SID
auth_url = 'https://www.google.com/accounts/ClientLogin'
auth_req_data = urllib.urlencode({'Email': username,
'Passwd': password,
'service': 'reader'})
auth_req = urllib2.Request(auth_url, data=auth_req_data)
auth_resp = urllib2.urlopen(auth_req)
auth_resp_content = auth_resp.read()
auth_resp_dict = dict(x.split('=') for x in auth_resp_content.split('\n') if x)
auth_token = auth_resp_dict["Auth"]
# Create a cookie in the header using the SID
header = {}
header['Authorization'] = 'GoogleLogin auth=%s' % auth_token
reader_base_url = 'http://www.google.com/reader/api/0/unread-count?%s'
reader_req_data = urllib.urlencode({'all': 'true',
'output': 'xml'})
reader_url = reader_base_url % (reader_req_data)
reader_req = urllib2.Request(reader_url, None, header)
reader_resp = urllib2.urlopen(reader_req)
reader_resp_content = reader_resp.read()
print reader_resp_content
And some additional links on the topic:
http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI
How do you access an authenticated Google App Engine service from a (non-web) python client?
http://blog.gpowered.net/2007/08/google-reader-api-functions.html
It is there. Still in Beta though.
Here is an update to this answer
import urllib
import urllib2
username = 'username#gmail.com'
password = '******'
# Authenticate to obtain Auth
auth_url = 'https://www.google.com/accounts/ClientLogin'
#auth_req_data = urllib.urlencode({'Email': username,
# 'Passwd': password})
auth_req_data = urllib.urlencode({'Email': username,
'Passwd': password,
'service': 'reader'})
auth_req = urllib2.Request(auth_url, data=auth_req_data)
auth_resp = urllib2.urlopen(auth_req)
auth_resp_content = auth_resp.read()
auth_resp_dict = dict(x.split('=') for x in auth_resp_content.split('\n') if x)
# SID = auth_resp_dict["SID"]
AUTH = auth_resp_dict["Auth"]
# Create a cookie in the header using the Auth
header = {}
#header['Cookie'] = 'Name=SID;SID=%s;Domain=.google.com;Path=/;Expires=160000000000' % SID
header['Authorization'] = 'GoogleLogin auth=%s' % AUTH
reader_base_url = 'http://www.google.com/reader/api/0/unread-count?%s'
reader_req_data = urllib.urlencode({'all': 'true',
'output': 'xml'})
reader_url = reader_base_url % (reader_req_data)
reader_req = urllib2.Request(reader_url, None, header)
reader_resp = urllib2.urlopen(reader_req)
reader_resp_content = reader_resp.read()
print reader_resp_content
Google Reader removed SID auth around June, 2010 (I think), using new Auth from ClientLogin is the new way and it's a bit simpler (header is shorter). You will have to add service in data for requesting Auth, I noticed no Auth returned if you don't send the service=reader.
You can read more about the change of authentication method in this thread.
In the API posted in [1], the "token" field should be "T"
[1] http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI