librelist archives

« back to archive

Issue with Two-Factor Authentification for Github3

Issue with Two-Factor Authentification for Github3

From:
Christoph Neumann
Date:
2015-07-31 @ 09:43
Hi everyone,

first of all thank you for your great library. Great work.

I'm eager to use it, but I do have a small issue with the 2FA and the 
example you are providing in the docs.

First of all, I think, the "two_factor_callback=my_two_factor_function" 
part is lacking "()"at the end: 
"two_factor_callback=my_two_factor_function()". I created a pull-request 
for that.

However, even if I fix this, I end up getting a "Your callback should be 
callable" issue. What do I do wrong? Tried Python2 and 3. Any idea?

Thanks
Chris


import github3

try:
    # Python 2
    prompt = raw_input
except NameError:
    # Python 3
    prompt = input

def my_two_factor_function():
    code = ''
    while not code:
        # The user could accidentally press Enter before being ready,
        # let's protect them from doing that.
        code = prompt('Enter 2FA code: ')
    return code

g = github3.login('sigmavirus24', 'my_password',
                  two_factor_callback=my_two_factor_function)


Re: [github3.py] Issue with Two-Factor Authentification for Github3

From:
Ian Cordasco
Date:
2015-07-31 @ 13:43
Replies in-line Christoph

On Fri, Jul 31, 2015 at 4:43 AM, Christoph Neumann <
mail@christoph-neumann.de> wrote:

> Hi everyone,
>
> first of all thank you for your great library. Great work.
>
> I'm eager to use it, but I do have a small issue with the 2FA and the
> example you are providing in the docs.
>
> First of all, I think, the "two_factor_callback=my_two_factor_function" part
> is lacking "()"at the end: "two_factor_callback=
> my_two_factor_function()". I created a pull-request for that.
>
>
I can understand why that might be confusing. Are you familiar with the
idea of a "callback"? In languages "callbacks" are often a function to be
called in the event something happens. github3.py uses them so that when it
sees that 2FA is required, it calls the function you've provided to get a
2FA token. If you do

    two_factor_callback=my_two_factor_function()

It will prompt you for a 2FA token exactly once and never again.


> However, even if I fix this, I end up getting a "Your callback should be
> callable" issue. What do I do wrong? Tried Python2 and 3. Any idea?
>

Did you have problems using the example as it was written? It should Just
Work™


> Thanks
> Chris
>
> import github3
> try:
>     # Python 2
>     prompt = raw_inputexcept NameError:
>     # Python 3
>     prompt = input
> def my_two_factor_function():
>     code = ''
>     while not code:
>         # The user could accidentally press Enter before being ready,
>         # let's protect them from doing that.
>         code = prompt('Enter 2FA code: ')
>     return code
> g = github3.login('sigmavirus24', 'my_password',
>                   two_factor_callback=my_two_factor_function)
>
>
>
>

Re: [github3.py] Issue with Two-Factor Authentification for Github3

From:
Christoph Neumann
Date:
2015-07-31 @ 14:17
Hi Ian,

thanks for your quick response.

I know about callbacks. If I use the code "as-is", then the 
my_two_factor_function is not even called, because you are assigning a 
variable "two_factor_callback= my_two_factor_function" instead of calling 
the function "two_factor_callback=my_two_factor_function()". So I am not 
even prompted for the 2FA and if I continue on, e.g. this statement ....

users = gh.search_users('myuser')

... raises an authentication issue.

If I change your example to 
"...,two_factor_callback=my_two_factor_function())" , I am prompted for 
the 2FA code, but then I get the "Your callback should be callable error" 
instead.

In your code, you seem to check if the function is from the instance 
Callable, however, as far as I know, you need to have the __call__ 
function implemented in a class, for an object to be considered an 
instance of "Callable". As we are passing a function, this might be the 
reason, why it doesn't work.

Thanks,
Christoph

My current code:

try:
    # Python 2
    prompt = raw_input
except NameError:
    # Python 3
    prompt = input

def my_two_factor_function():
    code = ''
    while not code:
        # The user could accidentally press Enter before being ready,
        # let's protect them from doing that.
        code = prompt('Enter 2FA code: ')
    return code

gh = github3.login(GITHUB_USER, password=GITHUB_PASSWORD, 
two_factor_callback=my_two_factor_function())

users = gh.search_users('myuser')


On 31 Jul 2015, at 15:43, Ian Cordasco 
<graffatcolmingov@gmail.com<mailto:graffatcolmingov@gmail.com>> wrote:

Replies in-line Christoph

On Fri, Jul 31, 2015 at 4:43 AM, Christoph Neumann 
<mail@christoph-neumann.de<mailto:mail@christoph-neumann.de>> wrote:
Hi everyone,

first of all thank you for your great library. Great work.

I'm eager to use it, but I do have a small issue with the 2FA and the 
example you are providing in the docs.

First of all, I think, the "two_factor_callback=my_two_factor_function" 
part is lacking "()"at the end: 
"two_factor_callback=my_two_factor_function()". I created a pull-request 
for that.


I can understand why that might be confusing. Are you familiar with the 
idea of a "callback"? In languages "callbacks" are often a function to be 
called in the event something happens. github3.py uses them so that when 
it sees that 2FA is required, it calls the function you've provided to get
a 2FA token. If you do

    two_factor_callback=my_two_factor_function()

It will prompt you for a 2FA token exactly once and never again.

However, even if I fix this, I end up getting a "Your callback should be 
callable" issue. What do I do wrong? Tried Python2 and 3. Any idea?

Did you have problems using the example as it was written? It should Just Work™

Thanks
Chris


import github3

try:
    # Python 2
    prompt = raw_input
except NameError:
    # Python 3
    prompt = input

def my_two_factor_function():
    code = ''
    while not code:
        # The user could accidentally press Enter before being ready,
        # let's protect them from doing that.
        code = prompt('Enter 2FA code: ')
    return code

g = github3.login('sigmavirus24', 'my_password',
                  two_factor_callback=my_two_factor_function)





Re: [github3.py] Issue with Two-Factor Authentification for Github3

From:
Ian Cordasco
Date:
2015-07-31 @ 14:35
On Fri, Jul 31, 2015 at 9:17 AM, Christoph Neumann <
mail@christoph-neumann.de> wrote:

> Hi Ian,
>
> thanks for your quick response.
>
> I know about callbacks. If I use the code "as-is", then the
> my_two_factor_function is not even called, because you are assigning a
> variable "two_factor_callback= my_two_factor_function" instead of calling
> the function "two_factor_callback=my_two_factor_function()". So I am not
> even prompted for the 2FA and if I continue on, e.g. this statement ....
>
> users = gh.search_users('myuser')
>
> ... raises an authentication issue.
>

Could you perhaps be more specific?


> If I change your example to
> "...,two_factor_callback=my_two_factor_function())" , I am prompted for the
> 2FA code, but then I get the "Your callback should be callable error"
> instead.
>
> In your code, you seem to check if the function is from the instance
> Callable, however, as far as I know, you need to have the __call__ function
> implemented in a class, for an object to be considered an instance of
> "Callable". As we are passing a function, this might be the reason, why it
> doesn't work.
>
>
Please write a test showing that functions do not pass that check.

What version of github3.py are you using?

Re: [github3.py] Issue with Two-Factor Authentification for Github3

From:
Christoph Neumann
Date:
2015-07-31 @ 14:48
Hi, sure. Your example. Please not, I am not promted for any 2FA.

>>> import github3
>>>
>>>
>>> try:
...     # Python 2
...     prompt = raw_input
... except NameError:
...     # Python 3
...     prompt = input
...
>>> def my_two_factor_function():
...     code = ''
...     while not code:
...         # The user could accidentally press Enter before being ready,
...         # let's protect them from doing that.
...         code = prompt('Enter 2FA code: ')
...     return code
...
>>> gh = github3.login("user", password="password", 
two_factor_callback=my_two_factor_function)
>>>
>>> users = gh.search_users('myuser')
>>>
>>> for user in users:
...     if not 
gh.is<http://t.sidekickopen13.com/e1t/c/5/f18dQhb0S7lC8dDMPbW2n0x6l2B9nMJW7t5XYg1p1BpnW3Mx_6T1q7wNRVQBcsP56dW3Nf4cpYLq02?si=6403665664933888&pi=4EBE4D53-5E13-40ED-9AD9-86BF69A9EA05&t=http%3A%2F%2Fgh%2Eis>_following(user):
...         gh.follow(user)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.7/site-packages/github3/structs.py", line 68, in
__iter__
    json = self._get_json(response)
  File "/Library/Python/2.7/site-packages/github3/structs.py", line 134, 
in _get_json
    json = self._json(response, 200)
  File "/Library/Python/2.7/site-packages/github3/models.py", line 153, in _json
    if self._boolean(response, status_code, 404) and response.content:
  File "/Library/Python/2.7/site-packages/github3/models.py", line 174, in
_boolean
    raise error_for(response)
github3.exceptions.AuthenticationFailed: 401 Bad credentials

Imho, you need to change the assignment of the two_factor_callback as 
highlighted below (adding () to actually call the function), then you are 
promoted (red text), but: you run into this error:

>>> # Github
... import github3
>>>
>>>
>>> try:
...     # Python 2
...     prompt = raw_input
... except NameError:
...     # Python 3
...     prompt = input
...
>>> def my_two_factor_function():
...     code = ''
...     while not code:
...         # The user could accidentally press Enter before being ready,
...         # let's protect them from doing that.
...         code = prompt('Enter 2FA code: ')
...     return code
...
>>> gh = github3.login("user", password="password", 
two_factor_callback=my_two_factor_function())
Enter 2FA code: 123456
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.7/site-packages/github3/api.py", line 63, in login
    g.login(username, password, token, two_factor_callback)
  File "/Library/Python/2.7/site-packages/github3/github.py", line 670, in login
    self.session.two_factor_auth_callback(two_factor_callback)
  File "/Library/Python/2.7/site-packages/github3/session.py", line 110, 
in two_factor_auth_callback
    raise ValueError('Your callback should be callable')
ValueError: Your callback should be callable


On 31 Jul 2015, at 16:35, Ian Cordasco 
<graffatcolmingov@gmail.com<mailto:graffatcolmingov@gmail.com>> wrote:



On Fri, Jul 31, 2015 at 9:17 AM, Christoph Neumann 
<mail@christoph-neumann.de<mailto:mail@christoph-neumann.de>> wrote:
Hi Ian,

thanks for your quick response.

I know about callbacks. If I use the code "as-is", then the 
my_two_factor_function is not even called, because you are assigning a 
variable "two_factor_callback= my_two_factor_function" instead of calling 
the function "two_factor_callback=my_two_factor_function()". So I am not 
even prompted for the 2FA and if I continue on, e.g. this statement ....

users = gh.search_users('myuser')

... raises an authentication issue.

Could you perhaps be more specific?

If I change your example to 
"...,two_factor_callback=my_two_factor_function())" , I am prompted for 
the 2FA code, but then I get the "Your callback should be callable error" 
instead.

In your code, you seem to check if the function is from the instance 
Callable, however, as far as I know, you need to have the __call__ 
function implemented in a class, for an object to be considered an 
instance of "Callable". As we are passing a function, this might be the 
reason, why it doesn't work.


Please write a test showing that functions do not pass that check.

What version of github3.py are you using?

Re: [github3.py] Issue with Two-Factor Authentification for Github3

From:
Ian Cordasco
Date:
2015-08-01 @ 13:59
On Fri, Jul 31, 2015 at 9:48 AM, Christoph Neumann
<mail@christoph-neumann.de> wrote:
>
> Hi, sure. Your example. Please not, I am not promted for any 2FA.
>
> >>> import github3
> >>>
> >>>
> >>> try:
> ...     # Python 2
> ...     prompt = raw_input
> ... except NameError:
> ...     # Python 3
> ...     prompt = input
> ...
> >>> def my_two_factor_function():
> ...     code = ''
> ...     while not code:
> ...         # The user could accidentally press Enter before being ready,
> ...         # let's protect them from doing that.
> ...         code = prompt('Enter 2FA code: ')
> ...     return code
> ...
> >>> gh = github3.login("user", password="password", 
two_factor_callback=my_two_factor_function)
> >>>
> >>> users = gh.search_users('myuser')
> >>>
> >>> for user in users:
> ...     if not gh.is_following(user):
> ...         gh.follow(user)
> ...
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "/Library/Python/2.7/site-packages/github3/structs.py", line 68, 
in __iter__
>     json = self._get_json(response)
>   File "/Library/Python/2.7/site-packages/github3/structs.py", line 134,
in _get_json
>     json = self._json(response, 200)
>   File "/Library/Python/2.7/site-packages/github3/models.py", line 153, in _json
>     if self._boolean(response, status_code, 404) and response.content:
>   File "/Library/Python/2.7/site-packages/github3/models.py", line 174, 
in _boolean
>     raise error_for(response)
> github3.exceptions.AuthenticationFailed: 401 Bad credentials
>

So I have 2FA enabled on a test account and when I try to use that
account with a mistyped password, I get the same exception and no
prompt for a token.

>
> Imho, you need to change the assignment of the two_factor_callback as 
highlighted below (adding () to actually call the function), then you are 
promoted (red text), but: you run into this error:
>

Please write a plain python test showing why checking for
collections.Callable is wrong. Something like:

import collections

def regular_function():
    pass

lambda_function = lambda: None

class Foo(object):
    def method(self):
        pass

method = Foo().method

print('Regular functions: %s' % isinstance(regular_function,
collections.Callable))
print('Lambda functions: %s' % isinstance(lambda_function,
collections.Callable))
print('Methods: %s' % isinstance(method, collections.Callable))

Any of those returning False will show that the example shouldn't be
passing in a function or checking that it is callable.