pyauth / pyotp

Python One-Time Password Library
https://pyauth.github.io/pyotp/
Other
2.91k stars 319 forks source link

Support for Steam TOTP #127

Closed or29544 closed 1 year ago

or29544 commented 2 years ago

Could we please have support for Steam's custom TOTP?

kislyuk commented 2 years ago

Thanks for your interest in PyOTP. Steam does not follow the TOTP RFC, so it is a non-standard implementation of TOTP. As such it is unlikely that we will develop support for it, however if someone wants to contribute an implementation with tests and documentation, we could include it in a pyotp.contrib.steam submodule.

Technically, Steam appears to use an OTP of length 5 with a 30 second tick and the same HOTP construction as standard HOTP, but with a custom alphabet for the OTP instead of digits. As such this can be a straightforward subclass of pyotp.TOTP overloading generate_otp() to change https://github.com/pyauth/pyotp/blob/develop/src/pyotp/otp.py#L33

or29544 commented 2 years ago

There is the Authenticator app that works with Steam TOTP. Unfortunately it's in Rust, not Python: otp.rs

einfachIrgendwer0815 commented 1 year ago

I made an implementation of Steams TOTP for python based on the mentioned otp.rs. https://gist.github.com/einfachIrgendwer0815/883a7d1f4e328b839fa3ddacca1b10d2

It's a subclass of pyotp.TOTP and overloads generate_otp().

raduzaharia-medium commented 1 year ago

So...could it be integrated in PyOTP? :astonished:

JamiKettunen commented 1 year ago

From what I can tell there's nothing to do anymore and this can be closed since v2.7.0 includes support and the following works for me as tested with v2.8.0:

import pyotp.contrib.steam
print(pyotp.contrib.Steam("SECRETKEY").now())
kislyuk commented 1 year ago

Correct, Steam TOTP is now supported thanks to work by @einfachIrgendwer0815 in #142. The remaining work was to add docs for it, which I just did.

JamiKettunen commented 1 year ago

Hm actually there seems to be an issue, consumers of this library can't use pyotp.parse_uri() with the otpauth://totp/Steam:USERNAME?secret=WHATEVER&period=30&digits=5&issuer=Steam&encoder=steam URIs and returns:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/site-packages/pyotp/__init__.py", line 80, in parse_uri
    raise ValueError("Digits may only be 6, 7, or 8")
ValueError: Digits may only be 6, 7, or 8

Would it be acceptable to add support for this, or should the consumers deal with this only pyotp.contrib module?

JamiKettunen commented 1 year ago

Ping @kislyuk ^

kislyuk commented 1 year ago

@JamiKettunen I'm happy to take PRs to adapt parse_uri to accommodate Steam. Would need a unit/regression test in place.

einfachIrgendwer0815 commented 1 year ago

@JamiKettunen Are you working on this? Otherwise I would like to do that.

JamiKettunen commented 1 year ago

@einfachIrgendwer0815 Feel free to take over, I tried something locally but wasn't successful