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 local WSGI server authorizer #128

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft

Conversation

NadimAsad
Copy link

No documentation string, tests or styling have been provided with initial commit. I'm currently looking for maintainer feedback for the proposed addition of new local WSGI server based authorizer class.

@NadimAsad NadimAsad marked this pull request as draft August 10, 2021 00:03
Copy link
Member

@LilSpazJoekp LilSpazJoekp left a comment

Choose a reason for hiding this comment

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

What I've found so far. I think this would be better suited as an example instead of being part of prawcore.

Regardless, how would one use this? Could you provide a working example?

prawcore/auth.py Outdated Show resolved Hide resolved
* Raise InvalidInvocation exception with LocalWSGIServerAuthorizer if redirect URI location isn't local server location
@NadimAsad
Copy link
Author

The state was supposed to be user specified, I forgot to fix this while I was creating the class. The example for the flow can be found in the updated obtain_refresh_token.py. The old code to obtain refresh token was replaced to use the new proposed class.

@NadimAsad
Copy link
Author

NadimAsad commented Aug 10, 2021

Example for flow

#!/usr/bin/env python

"""This example demonstrates the flow for retrieving a refresh token.

In order for this example to work your application's redirect URI must be set
to http://localhost:65010/auth_callback.

This tool can be used to conveniently create refresh tokens for later use with
your web application OAuth2 credentials.

"""
import os
import sys
import uuid

import prawcore


def main():
    """Provide the program's entry point when directly executed."""
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} SCOPE...")
        return 1

    authorizer = prawcore.LocalWSGIServerAuthorizer(
        prawcore.TrustedAuthenticator(
            prawcore.Requestor("prawcore_refresh_token_example"),
            os.environ["PRAWCORE_CLIENT_ID"],
            os.environ["PRAWCORE_CLIENT_SECRET"],
            "http://localhost:65010/auth_callback",
        ),
        sys.argv[1:],
        duration="permanent",
    )
    authorizer.authorize_local_server(state=str(uuid.uuid4()))
    print(f"Refresh token: {authorizer.refresh_token}")


if __name__ == "__main__":
    sys.exit(main())

@NadimAsad
Copy link
Author

NadimAsad commented Aug 10, 2021

Using custom praw Reddit client

praw.ini

[eXRCWebAppClient]
client_id=<WEB-APP-CLIENT-ID>
client_secret=<WEB-APP-CLIENT-SECRET>
local_client_scopes=read identity
redirect_uri=http://localhost:65010/auth_callback

Python Interpreter Output

>>> from praw import Reddit
>>> reddit = Reddit("eXRCWebAppClient", user_agent="eXRCWebAppClient_test")
>>> print(reddit.user.me())
eXMirrorBot
>>> print(reddit.auth._reddit._core._authorizer.refresh_token)
<VALID-USER-REFRESH-TOKEN>

This basically can be used as a first time authorizer to get a refreshable token directly from praw. The refresh token can be later assigned to a different domain in the config file.

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.

Overall, something about the code this PR introduces doesn't quite feel right. Even in PRAW (this one more so) I'd argue provided code does more than it should. In a production environment where someone wishes to obtain access tokens for users I wouldn't recommend they use this Authorizer, and instead manually leverage one of the existing ones within their existing web application. For personal use, I'm curious what the short comings are for the existing example -- or why we couldn't provide a simpler example which leverages the wsgiref code.

What do you think?


from uuid import uuid4
from urllib.parse import parse_qs, urlparse
from wsgiref.simple_server import make_server, WSGIRequestHandler
Copy link
Member

Choose a reason for hiding this comment

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

I didn't know this was in the standard library. Very cool.

@LilSpazJoekp LilSpazJoekp marked this pull request as ready for review August 11, 2021 03:40
@LilSpazJoekp LilSpazJoekp marked this pull request as draft August 11, 2021 03:40
@NadimAsad
Copy link
Author

My main intention for creating this PR was because the tutorial given in the docs to obtain a refreshable token looked too complex for my liking and is IMO not end-user friendly to easily obtain a refresh token for PRAW. I don't like entering my Reddit username / password / 2FA code through terminal to use the password flow and would like to avoid using this if possible. Even if this PR is not accepted, I personally will be maintaining a fork with the proposed authorizer for my own personal use. If there is any changes that needed to make this suitable for production environment, feel free to let me know. Otherwise, feel free to close this PR.

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

3 participants