Modulr API 的身份验证失败 - Python
Authentication failing for Modulr API - Python
API 文档是 here
唯一的代码示例在 Java、here
每次我尝试进行身份验证时,我都会得到:
{
"error": "Authorization field missing, malformed or invalid"
}
我已经多次阅读授权文档,但仍然没有运气。
这是我的代码:
import requests
import secrets
import codecs
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime
import hashlib
import hmac
import base64
import urllib.parse
key = '<API_KEY>'
secret = '<API_SECRET>'
# Getting current time
now = datetime.now()
stamp = mktime(now.timetuple())
# Formats time into this format --> Mon, 25 Jul 2016 16:36:07 GMT
formated_time = format_date_time(stamp)
# Generates a secure random string for the nonce
nonce = secrets.token_urlsafe(30)
# Combines date and nonce into a single string that will be signed
signature_string = 'date' + ':' + formated_time + '\n' + 'x-mod-nonce' + ':' + nonce
# Expected output example --> date: Mon, 25 Jul 2016 16:36:07 GMT\nx-mod-nonce: 28154b2-9c62b93cc22a-24c9e2-5536d7d
# Encodes secret and message into a format that can be signed
secret = bytes(secret, encoding='utf-8')
message = bytes(signature_string,encoding='utf-8')
# Signing process
digester = hmac.new(secret, message, hashlib.sha1)
# Converts to hex
hex_code = digester.hexdigest()
# Decodes the signed string in hex into base64
b64 = codecs.encode(codecs.decode(hex_code, 'hex'), 'base64').decode()
# Encodes the string so it is safe for URL
url_safe_code = urllib.parse.quote(b64,safe='')
# Adds the key and signed response
authorization = f'Signature keyId="{key}",algorithm="hmac-sha1",headers="date x-mod-nonce",signature="{url_safe_code}"'
account_id = 'A120BU48'
url = f'https://api-sandbox.modulrfinance.com/api-sandbox/accounts/{account_id}'
headers = {
'Authorization': authorization, # Authorisation header
'Date' : formated_time, # Date header
'x-mod-nonce': nonce, # Addes nonce
'accept': 'application/json',
}
response = requests.get(url,headers=headers)
print(response.text)
我不确定这个过程哪里出了问题,据我所知,当我添加到身份验证示例的测试数据中时,签名被正确签名,我得到了预期的字符串。
如果您想尝试使用真正的 API 密钥,请注册访问 here
我尝试调用的 API 端点的文档是 here
您链接的文档在冒号和值之间有一个 space。
signature_string = 'date' + ':' + formated_time + '\n' + 'x-mod-nonce' + ':' + nonce
应该是:
signature_string = 'date' + ': ' + formated_time + '\n' + 'x-mod-nonce' + ': ' + nonce
或(更简单):
signature_string = 'date: ' + formated_time + '\n' + 'x-mod-nonce: ' + nonce
更新
我注册了看看发生了什么。我还 运行 您在文档中给出的示例代码,发现签名不完全正确。
除了我上面建议的更改之外,还有必要进行进一步的更改。
改线后
b64 = codecs.encode(codecs.decode(hex_code, 'hex'), 'base64').decode()
至
b64 = codecs.encode(codecs.decode(hex_code, 'hex'), 'base64').decode().strip()
示例的签名匹配。
在此之后,我可以使用自己的密钥连接到 API。
这是完整的工作代码:
import codecs
import hashlib
import hmac
import secrets
import urllib.parse
from datetime import datetime
from time import mktime
from wsgiref.handlers import format_date_time
import requests
key = '<key>'
secret = '<secret>'
account_id = '<account id>'
url = f'https://api-sandbox.modulrfinance.com/api-sandbox/accounts/{account_id}'
# Getting current time
now = datetime.now()
stamp = mktime(now.timetuple())
# Formats time into this format --> Mon, 25 Jul 2016 16:36:07 GMT
formatted_time = format_date_time(stamp)
# Generates a secure random string for the nonce
nonce = secrets.token_urlsafe(30)
# Combines date and nonce into a single string that will be signed
signature_string = 'date' + ': ' + formatted_time + '\n' + 'x-mod-nonce' + ': ' + nonce
# Encodes secret and message into a format that can be signed
secret = bytes(secret, encoding='utf-8')
message = bytes(signature_string, encoding='utf-8')
# Signing process
digester = hmac.new(secret, message, hashlib.sha1)
# Converts to hex
hex_code = digester.hexdigest()
# Decodes the signed string in hex into base64
b64 = codecs.encode(codecs.decode(hex_code, 'hex'), 'base64').decode().strip()
# Encodes the string so it is safe for URL
url_safe_code = urllib.parse.quote(b64, safe='')
# Adds the key and signed response
authorization = f'Signature keyId="{key}",algorithm="hmac-sha1",headers="date x-mod-nonce",signature="{url_safe_code}"'
headers = {
'Authorization': authorization, # Authorisation header
'Date': formatted_time, # Date header
'x-mod-nonce': nonce, # Adds nonce
'accept': 'application/json',
}
response = requests.get(url, headers=headers)
print(response.text)
API 文档是 here
唯一的代码示例在 Java、here
每次我尝试进行身份验证时,我都会得到:
{
"error": "Authorization field missing, malformed or invalid"
}
我已经多次阅读授权文档,但仍然没有运气。
这是我的代码:
import requests
import secrets
import codecs
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime
import hashlib
import hmac
import base64
import urllib.parse
key = '<API_KEY>'
secret = '<API_SECRET>'
# Getting current time
now = datetime.now()
stamp = mktime(now.timetuple())
# Formats time into this format --> Mon, 25 Jul 2016 16:36:07 GMT
formated_time = format_date_time(stamp)
# Generates a secure random string for the nonce
nonce = secrets.token_urlsafe(30)
# Combines date and nonce into a single string that will be signed
signature_string = 'date' + ':' + formated_time + '\n' + 'x-mod-nonce' + ':' + nonce
# Expected output example --> date: Mon, 25 Jul 2016 16:36:07 GMT\nx-mod-nonce: 28154b2-9c62b93cc22a-24c9e2-5536d7d
# Encodes secret and message into a format that can be signed
secret = bytes(secret, encoding='utf-8')
message = bytes(signature_string,encoding='utf-8')
# Signing process
digester = hmac.new(secret, message, hashlib.sha1)
# Converts to hex
hex_code = digester.hexdigest()
# Decodes the signed string in hex into base64
b64 = codecs.encode(codecs.decode(hex_code, 'hex'), 'base64').decode()
# Encodes the string so it is safe for URL
url_safe_code = urllib.parse.quote(b64,safe='')
# Adds the key and signed response
authorization = f'Signature keyId="{key}",algorithm="hmac-sha1",headers="date x-mod-nonce",signature="{url_safe_code}"'
account_id = 'A120BU48'
url = f'https://api-sandbox.modulrfinance.com/api-sandbox/accounts/{account_id}'
headers = {
'Authorization': authorization, # Authorisation header
'Date' : formated_time, # Date header
'x-mod-nonce': nonce, # Addes nonce
'accept': 'application/json',
}
response = requests.get(url,headers=headers)
print(response.text)
我不确定这个过程哪里出了问题,据我所知,当我添加到身份验证示例的测试数据中时,签名被正确签名,我得到了预期的字符串。
如果您想尝试使用真正的 API 密钥,请注册访问 here
我尝试调用的 API 端点的文档是 here
您链接的文档在冒号和值之间有一个 space。
signature_string = 'date' + ':' + formated_time + '\n' + 'x-mod-nonce' + ':' + nonce
应该是:
signature_string = 'date' + ': ' + formated_time + '\n' + 'x-mod-nonce' + ': ' + nonce
或(更简单):
signature_string = 'date: ' + formated_time + '\n' + 'x-mod-nonce: ' + nonce
更新
我注册了看看发生了什么。我还 运行 您在文档中给出的示例代码,发现签名不完全正确。
除了我上面建议的更改之外,还有必要进行进一步的更改。
改线后
b64 = codecs.encode(codecs.decode(hex_code, 'hex'), 'base64').decode()
至
b64 = codecs.encode(codecs.decode(hex_code, 'hex'), 'base64').decode().strip()
示例的签名匹配。
在此之后,我可以使用自己的密钥连接到 API。
这是完整的工作代码:
import codecs
import hashlib
import hmac
import secrets
import urllib.parse
from datetime import datetime
from time import mktime
from wsgiref.handlers import format_date_time
import requests
key = '<key>'
secret = '<secret>'
account_id = '<account id>'
url = f'https://api-sandbox.modulrfinance.com/api-sandbox/accounts/{account_id}'
# Getting current time
now = datetime.now()
stamp = mktime(now.timetuple())
# Formats time into this format --> Mon, 25 Jul 2016 16:36:07 GMT
formatted_time = format_date_time(stamp)
# Generates a secure random string for the nonce
nonce = secrets.token_urlsafe(30)
# Combines date and nonce into a single string that will be signed
signature_string = 'date' + ': ' + formatted_time + '\n' + 'x-mod-nonce' + ': ' + nonce
# Encodes secret and message into a format that can be signed
secret = bytes(secret, encoding='utf-8')
message = bytes(signature_string, encoding='utf-8')
# Signing process
digester = hmac.new(secret, message, hashlib.sha1)
# Converts to hex
hex_code = digester.hexdigest()
# Decodes the signed string in hex into base64
b64 = codecs.encode(codecs.decode(hex_code, 'hex'), 'base64').decode().strip()
# Encodes the string so it is safe for URL
url_safe_code = urllib.parse.quote(b64, safe='')
# Adds the key and signed response
authorization = f'Signature keyId="{key}",algorithm="hmac-sha1",headers="date x-mod-nonce",signature="{url_safe_code}"'
headers = {
'Authorization': authorization, # Authorisation header
'Date': formatted_time, # Date header
'x-mod-nonce': nonce, # Adds nonce
'accept': 'application/json',
}
response = requests.get(url, headers=headers)
print(response.text)