Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add two factor callback #111

Merged
merged 1 commit into from
Jun 5, 2021
Merged

Add two factor callback #111

merged 1 commit into from
Jun 5, 2021

Conversation

MaybeNetwork
Copy link
Contributor

This feature allows script authorizations to supply an optional 'otp' parameter when authenticating. This is accomplished by adding a callback named two_factor_callback to the method ScriptAuthorizer.refresh. See 97 and praw's 1496 for previous discussions of this.


I have added some support for running other tests with 2fa enabled. There is now a test_two_factor_callback function in conftest, which is used in script auth tests to generate an OTP. By default, it returns None, which allows all tests to pass. This PR also adds two tests that show what successful and unsuccessful authorization attempts look like. I have included a third test in test_authorizer, test_refresh_with__2fa, that is commented out and does not have a corresponding cassette. If you change test_two_factor_callback to something that will generate your real otp code, you can use this test to produce the same output as test_refresh_with__valid_otp. You don't need to install a separate library to run the test if you have already have a 2fa authenticator device, program, or app. Just change the definition of test_two_factor_callback from return None to return input("OTP: "), run the test with pytest -s, and enter the code when prompted.

There are some issues with running tests with 2fa enabled. The uri for the initial authorization in all previous tests run with a password flow looks like

"grant_type=password&password=<PASSWORD>&username=<USERNAME>"

but if you use 2fa, this changes to

"grant_type=password&otp=123456&password=<PASSWORD>&username=<USERNAME>"`

This means that all tests which match uris will fail if you change the test_two_factor_callback to anything other than something that returns None. This could be dealt with by adding before_record and before_playback callbacks to the Betamax config, but I don't think it is worth doing that right now. Also, the rate limit for the password flow doesn't really allow you to record multiple tests at once. If you try, you will get the same {'error': 'invalid_grant'} message if you're still in timeout that you get when you supply the wrong credentials. The other flows aren't affected.

Other notes: if you don't have 2fa on your account, you can authorize with the otp parameter present as long as it is set to the empty string. If you make it anything other than the empty string, you'll get an invalid grant.

Copy link
Member

@bboe bboe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor comments, otherwise this PR looks great.

@@ -31,6 +31,11 @@ def b64_string(input_string):
return b64encode(input_string.encode("utf-8")).decode("utf-8")


def test_two_factor_callback():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this isn't a test case can we remove the test_ prefix please?

@@ -340,6 +341,60 @@ def test_refresh(self):
self.assertEqual(set(["*"]), authorizer.scopes)
self.assertTrue(authorizer.is_valid())

# def test_refresh_with__2fa(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this example is necessary. If you want to add some information in the documentation about running tests with 2FA that'd be great, but not necessary for this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I included it just in case you wanted to verify that the feature works, since the other tests don't really prove it.

@bboe bboe merged commit 437c2e4 into praw-dev:master Jun 5, 2021
@bboe
Copy link
Member

bboe commented Jun 5, 2021

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants