Skip to content

Commit

Permalink
Slim down the otpauth:// URIs
Browse files Browse the repository at this point in the history
Let's stop making the otpauth:// URI, and resulting QR codes, excessively
long by including default values of any of the parameters described in
https://github.com/google/google-authenticator/wiki/Key-Uri-Format
  • Loading branch information
dlenski committed Aug 1, 2024
1 parent c39cc27 commit 9f49da3
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 12 deletions.
4 changes: 2 additions & 2 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def test_generate_totp_uri():
'timeskew': 0,
}
test_secret = b'ZqeD\xd9wg]"\x12\x1f7\xc7v6"\xf0\x13\\i'
expected_uri = urlparse.urlparse('otpauth://totp/VIP%20Access:SYMC26070843?secret=LJYWKRGZO5TV2IQSD434O5RWELYBGXDJ&digits=6&algorithm=SHA1&period=30&image=https://raw.githubusercontent.com/dlenski/python-vipaccess/master/vipaccess.png')
expected_uri = urlparse.urlparse('otpauth://totp/VIP%20Access:SYMC26070843?secret=LJYWKRGZO5TV2IQSD434O5RWELYBGXDJ&image=' + VIP_ACCESS_LOGO)
generated_uri = urlparse.urlparse(generate_otp_uri(test_token, test_secret))
assert expected_uri.scheme == generated_uri.scheme
assert expected_uri.netloc == generated_uri.netloc
Expand All @@ -112,7 +112,7 @@ def test_generate_hotp_uri():
'timeskew': 0,
}
test_secret = b'\x9a\x13\xcd2!\xad\xbd\x97R\xfcEE\xb6\x92e\xb4\x14\xb0\xfem'
expected_uri = urlparse.urlparse('otpauth://hotp/VIP%20Access:UBHE57586348?digits=6&algorithm=SHA1&counter=1&secret=TIJ42MRBVW6ZOUX4IVC3NETFWQKLB7TN&image=https://raw.githubusercontent.com/dlenski/python-vipaccess/master/vipaccess.png')
expected_uri = urlparse.urlparse('otpauth://hotp/VIP%20Access:UBHE57586348?counter=1&secret=TIJ42MRBVW6ZOUX4IVC3NETFWQKLB7TN&image=' + VIP_ACCESS_LOGO)
generated_uri = urlparse.urlparse(generate_otp_uri(test_token, test_secret))
assert expected_uri.scheme == generated_uri.scheme
assert expected_uri.netloc == generated_uri.netloc
Expand Down
23 changes: 13 additions & 10 deletions vipaccess/provision.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import string
import sys
import time
import xml.etree.ElementTree as etree
# Python 2/3 compatibility
try:
import urllib.parse as urllib
Expand All @@ -37,7 +38,6 @@
from oath import totp, hotp
from vipaccess.version import __version__


PROVISIONING_URL = 'https://services.vip.symantec.com/prov'
VIP_ACCESS_LOGO = 'https://raw.githubusercontent.com/dlenski/python-vipaccess/master/vipaccess.png'

Expand Down Expand Up @@ -170,25 +170,28 @@ def generate_otp_uri(token, secret, issuer='VIP Access', image=VIP_ACCESS_LOGO):
secret = base64.b32encode(secret).upper()
data = dict(
secret=secret,
digits=token.get('digits', 6),
algorithm=token.get('algorithm', 'SHA1').upper(),
image=image,
# Per Google's otpauth:// URI spec (https://github.com/google/google-authenticator/wiki/Key-Uri-Format#issuer),
# the issuer in the URI path and the issuer parameter are equivalent.
# Per #53, Authy does not correctly parse the latter.
# Therefore, we include only the former (issuer in the URI path) for maximum compatibility.
# issuer=issuer,
)
if image:
data['image'] = image
if token.get('digits', 6) != 6: # 6 digits is the default
data['digits'] = token['digits']
if token.get('algorithm', 'SHA1').upper() != 'SHA1': # SHA1 is the default
algorithm=token['algorithm'].upper(),
if token.get('counter') is not None: # HOTP
data['counter'] = token['counter']
token_parameters['otp_type'] = urllib.quote('hotp')
token_parameters['otp_type'] = 'hotp'
elif token.get('period'): # TOTP
data['period'] = token['period']
token_parameters['otp_type'] = urllib.quote('totp')
if token['period'] != 30: # 30 seconds is the default
data['period'] = token['period']
token_parameters['otp_type'] = 'totp'
else: # Assume TOTP with default period 30 (FIXME)
data['period'] = 30
token_parameters['otp_type'] = urllib.quote('totp')
token_parameters['parameters'] = urllib.urlencode(data)
token_parameters['otp_type'] = 'totp'
token_parameters['parameters'] = urllib.urlencode(data, safe=':/')
return 'otpauth://%(otp_type)s/%(issuer)s:%(account_name)s?%(parameters)s' % token_parameters

def check_token(token, secret, session=requests, timestamp=None):
Expand Down

0 comments on commit 9f49da3

Please sign in to comment.