feat: token based auth in frappeclient
This commit is contained in:
parent
68a3bd0a36
commit
3f415094e9
2 changed files with 29 additions and 10 deletions
|
|
@ -164,23 +164,29 @@ def validate_auth_via_api_keys():
|
|||
"""
|
||||
try:
|
||||
authorization_header = frappe.get_request_header("Authorization", None).split(" ") if frappe.get_request_header("Authorization") else None
|
||||
authorization_source = frappe.get_request_header("Frappe-Authorization-Source", None)
|
||||
if authorization_header and authorization_header[0] == 'Basic':
|
||||
token = frappe.safe_decode(base64.b64decode(authorization_header[1])).split(":")
|
||||
validate_api_key_secret(token[0], token[1])
|
||||
elif authorization_header and authorization_header[0] == 'token':
|
||||
token = authorization_header[1].split(":")
|
||||
validate_api_key_secret(token[0], token[1])
|
||||
|
||||
if authorization_source:
|
||||
validate_api_key_secret(token[0], token[1], authorization_source)
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def validate_api_key_secret(api_key, api_secret):
|
||||
user = frappe.db.get_value(
|
||||
doctype="User",
|
||||
def validate_api_key_secret(api_key, api_secret, frappe_authorization_source=None):
|
||||
""" frappe_authorization_source to provide api key and secret for a doctype apart from User """
|
||||
if not frappe_authorization_source:
|
||||
frappe_authorization_source = 'User'
|
||||
doc = frappe.db.get_value(
|
||||
doctype=frappe_authorization_source,
|
||||
filters={"api_key": api_key},
|
||||
fieldname=['name']
|
||||
fieldname=["name"]
|
||||
)
|
||||
form_dict = frappe.local.form_dict
|
||||
user_secret = frappe.utils.password.get_decrypted_password ("User", user, fieldname='api_secret')
|
||||
if api_secret == user_secret:
|
||||
doc_secret = frappe.utils.password.get_decrypted_password(frappe_authorization_source, doc, fieldname="api_secret")
|
||||
if api_secret == doc_secret:
|
||||
user = frappe.db.get_value(frappe_authorization_source, doc, 'user')
|
||||
frappe.set_user(user)
|
||||
frappe.local.form_dict = form_dict
|
||||
frappe.local.form_dict = form_dict
|
||||
|
|
@ -3,6 +3,7 @@ import requests
|
|||
import json
|
||||
import frappe
|
||||
from six import iteritems, string_types
|
||||
from base64 import b64encode
|
||||
|
||||
'''
|
||||
FrappeClient is a library that helps you connect with other frappe systems
|
||||
|
|
@ -18,7 +19,7 @@ class FrappeException(Exception):
|
|||
pass
|
||||
|
||||
class FrappeClient(object):
|
||||
def __init__(self, url, username=None, password=None, verify=True):
|
||||
def __init__(self, url, username=None, password=None, verify=True, api_key=None, api_secret=None, frappe_authorization_source = None):
|
||||
self.headers = dict(Accept='application/json')
|
||||
self.verify = verify
|
||||
self.session = requests.session()
|
||||
|
|
@ -28,6 +29,10 @@ class FrappeClient(object):
|
|||
if username and password:
|
||||
self._login(username, password)
|
||||
|
||||
# token based authentication if api_key and api_secret provided
|
||||
elif api_key and api_secret:
|
||||
self.authenticate(api_key, api_secret, frappe_authorization_source)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
|
|
@ -49,6 +54,14 @@ class FrappeClient(object):
|
|||
raise SiteExpiredError
|
||||
raise AuthError
|
||||
|
||||
def authenticate(self, api_key, api_secret, frappe_authorization_source=None):
|
||||
token = b64encode('{}:{}'. format(api_key, api_secret))
|
||||
auth_header = {'Authorization': 'Basic {}'.format(token)}
|
||||
self.session.headers.update(auth_header)
|
||||
if frappe_authorization_source:
|
||||
auth_source = {'Frappe-Authorization-Source': frappe_authorization_source}
|
||||
self.session.headers.update(auth_source)
|
||||
|
||||
def logout(self):
|
||||
'''Logout session'''
|
||||
self.session.get(self.url, params={
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue