I am creating an app for use in our organization that will login users based on their Office 365 credentials using OAuth2.0. I am fetching an access token that I will store in a session variable. Here is an example of what I am doing:
#never_cache
def authorization(request):
microsoft = OAuth2Session(client_id,scope=scope,redirect_uri=redirect_uri)
token = ""
try:
users = 'https://graph.microsoft.com/v1.0/me' ##msgraph query url-
##This query is purelyjust used to
##authenticate user!
token = microsoft.fetch_token(token_url,client_secret=client_secret,code=request.GET.get('code', '')) ##Code is the authorization code present
##in request URL
header = {'Authorization': 'Bearer ' + token['access_token']}
response = requests.get(url = users, headers = header)
if int(response.status_code) != 200: ##if status code is not 200, then authentication failed. Redirect to login.
print ('Not validated. Return to login.')
request.session.flush()
return redirect('http://localhost:8000/login')
except Exception as e:
print ('User not does not have authentication rights')
request.session.flush()
return redirect('http://localhost:8000/login')
request.session['oauth_state'] = 'authorized'
response = HttpResponseRedirect('http://localhost:8000/search')
return response
I am then using this to check if 'oauth_state' is set to 'authorized'. However, I may change this so that the token is used to query the MS Graph API in each function in order to check if the user has proper permissions or not. Here's an example of what I am doing:
def search(request):
try:
if (str(request.session['oauth_state']) != 'authorized'):
print ('Not authorized')
request.session.flush()
return redirect('http://localhost:8000/login')
except Exception as e:
print ('Not authorized')
request.session.flush()
return redirect('http://localhost:8000/login')
<rest of code>
How insecure is this? Should I possibly be passing in the token to the response header? Or should I get rid of this method, and use django's standard auth and login system? I really appreciated the benefits of OAuth2.0, but if this method compromises our security, I might scrap it.
Related
I am implementing a Flask-RESTFul API where I receive a token from postman and compare it with the token I configured in my code as below:
file: functions.py
def authenticate():
headers = flask.request.headers
bearer = headers.get('Authorization')
token = bearer.split()[1]
try:
if str(hashlib.md5(b'Token_String').hexdigest()) == token:
logger.info('Token authentication successful.')
return True
else:
logger.error('Token autherization failed. Please check the token supplied.')
return False
except Exception as e:
if token is None:
logger.info('Token cannot be null. Supply a token with API call.')
return {'message': 'Token cannot be null. Exception: {error}'.format(error=e)}, 400
else:
logger.info('Token cannot be null. Supply a token with API call.')
return {'message': 'Error reading token. Cannot be Null/Empty. Exception: {error}'.format(error=e)}, 400
This is my API's get method:
class APIClass(Resource):
#classmethod
def get(self):
logger.info('Initiating get()')
if fc.authenticate():
run_some_sql_statements
else:
return {'message': 'Token authentication failed'}, 401
pass
Instead of using an IF-Condition, is there a way I can use the method: authenticate from functions.py file as a decorator on top of my get().
I tried doing this and faced the below error:
from validations import functions as fc
#classmethod
#fc.authenticate
def get(self):
But I see a compilation error: Function 'authenticate' lacks a positional argument
Could anyone let me know what is the mistake I made here and how can I correct it ?
The flask-restful docs contain a section about resource method decorators:
https://flask-restful.readthedocs.io/en/latest/extending.html#resource-method-decorators
class APIClass(Resource):
method_decorators = [authenticate]
Hellos firends,
I have REST service in Python Django application. I am trying to store some values in the request session post successful login service call.
like the following
request.session['valid']=True
and the I am able to check that the values set properly.
The in the next request when I am trying to retrieve the value I am not able to find any of the keys I had stored.
following is the code to retrieve the keys
if 'valid' not in request.session:
print('Invalid request. . .')
return False
elif request.session['valid']==True:
username=request.session['username']
print('Request validated. . .')
return True
I have the frontend app running on React and Backend REST is on DRF. After the login is done on the following code,
#csrf_exempt
#api_view(['POST'])
def login_details(request):
if request.method == 'POST':
headers = {
'Content-type': 'application/json',
}
# Assuming at this point login is successful, so I am setting the session
request.session['username']=TF_VAR_user_name
request=initSession(request)
data = txt
response = requests.post('https://hooks.slack.com/services/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', headers=headers, data=data)
print(response)
return Response(data_json)
except cx_Oracle.DatabaseError as exc:
error, = exc.args
m = error.message
err="Oracle-Error-Message: "+ str(error.code) + " Oracle-Error-Message: "+error.message
dic2={"Oracle-Error-Code":str(error.code),"Oracle-Error-Message":error.message}
print(dic2)
m=json.dumps(dic2)
n=json.loads(m)
txt="{'text':'User "+atp_userid+" Oracle-Error-Message: "+error.message+"'}"
data = txt
response = requests.post('https://hooks.slack.com/services/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', headers=headers, data=data)
return Response(n)
else:
return Response({ "message":"Unauthoried, please login."},status=status.HTTP_401_UNAUTHORIZED)
The I am trying to read Stored values in the following code,
#csrf_exempt
#api_view(['POST'])
def dashboard(request):
if 'valid' not in request.session:
print('Invalid request. . .')
elif request.session['valid']==True:
username=request.session['username']
print('Request validated. . .')
Please help me how can store values in session and retrieve in the subsequent request. I am sorry for the trouble as I am completely new to Python and Django
I am writing a custom Python class to encapsulate the Poloniex trading API. However, I am running in to a problem with the request returning a "404 Error". I have been over and over the documentation and am quite sure that I am utilizing the right endpoint... What else could I be doing wrong here:
...
self.trading_api = 'https://poloniex.com/tradingapi'
self.api_key = 'My API key'
self.secret_key = bytes('My Secret Key', 'latin-1')
...
req['nonce'] = int(time.time()*1000)
data = urllib.parse.urlencode(req).encode()
sign = hmac.new(self.secret_key, data, sha512)
signature=sign.hexdigest()
headers = dict(Key=self.api_key, Sign=signature)
conn = urllib.request.Request(self.trading_api, headers=headers)
self.rate_limit()
try:
requested = urllib.request.urlopen(conn, data=data)
return requested
The A in the url must be capitalized:
self.trading_api = 'https://poloniex.com/tradingApi'
While Poloniex's documentation does not make note of this (in fact the url used was copied directly from their page), remember to capitalize it!
I'm trying to resolve problem with Basic Authentication in flask using HTTPBasicAuth.
When I'm accessing using curl or web browser everything works well.
This are examples which works:
curl -u [access_token]:unused -i X GET http://127.0.0.1:5000/api/v1/token
or
http://[access_token]:unused#127.0.0.1:5000/api/v1/token
But when I'm using Authorization: Basic [token] or Authorization: Basic [token]:unused in header of request I get 500 error from server.
Verifying access token or email and password:
#auth.verify_password
def verify_password(email_or_token, password):
user = User.verify_auth_token(email_or_token)
if not user:
user = User.query.filter_by(email = email_or_token).first()
if not user or not user.verify_password(password):
return False
g.user = user
return True
User model:
class User(db.Model):
def generate_auth_token(self, expiration = 600):
s = Serializer(app.config['SECRET_KEY'], expires_in = expiration)
return s.dumps({ 'id': self.id })
#staticmethod
def verify_auth_token(token):
s = Serializer(app.config['SECRET_KEY'])
try:
data = s.loads(token)
except SignatureExpired:
return None # valid token, but expired
except BadSignature:
return None # invalid token
user = User.query.get(data['id'])
return user
I found that when I'm using token or email and password in header as Basic [token/email]:[password/unused], email_or_token and password properties are None.
Error: TypeError: argument of type 'NoneType' is not iterable
Why error occurs while using Authorization: Basic [token/email]:[password/unused] in header of request? What is solution for this?
You must Base64-encode the the credential portion of your Authorization header. This can be done with the command line base64 utility.
echo 'token:unused' | base64
From the example here, the username password combination of Aladdin:OpenSesame becomes:
Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l
The reason that you don't have to worry about this with curl or the browser, is that they will perform the encoding automatically for you.
I am trying to authenticate user using FIWARE.
It returns a 404. Thus fails at Step 1 itself. What is the access token url ? Any other pointers to check
I have tried variations with 'oauth/access_token', 'oauth/token' 'oauth2/token' 'oauth2/access_token' . All of them dont seem to work.
My Code is Below:
import oauth2 as oauth
# OAuth secret into your project's settings.
consumer = oauth2.Consumer(settings.FIWARE_CLIENT_ID,settings.FIWARE_CLIENT_SECRET)
client = oauth2.Client(consumer)
access_token_url = 'https://account.lab.fiware.org/oauth2/access_token'
# This is the slightly different URL used to authenticate/authorize.
authenticate_url = 'https://account.lab.fiware.org/oauth2/authorize'
def fiware_login(request):
# Step 1. Get a request token from FIWARE.
resp, content = client.request(access_token_url, "GET")
print resp
if resp['status'] != '200':
print content
raise Exception("Invalid response from FIWARE.")
# Step 2. Redirect the user to the authentication URL.
url = "%s?access_token=%s" % (authenticate_url,
resp['access_token'])
return HttpResponseRedirect(url)
Correct endpoint is "/oauth2/token".
Maybe you should use POST method instead of GET.
For more information see https://github.com/ging/fi-ware-idm/wiki/Using-the-FI-LAB-instance