Authenticating via OAuth
************************

PRAW supports the three types of applications that can be registered
on Reddit. Those are:

* Script Application

* Web Application

* Installed Application

Before you can use any one of these with PRAW, you must first register
an application of the appropriate type on Reddit.


Script Application
==================

**Script** applications are the simplest type of application to work
with because they don’t involve any sort of callback process to obtain
an "access_token".

While **script** applications do not involve a redirect uri, Reddit
still requires that you provide one when registering your application
– "http://localhost:8080" is a simple one to use.

In order to use a **script** application with PRAW you need four
pieces of information:

client_id:
   The client ID is the 14 character string listed just under
   “personal use script” for the desired developed application

client_secret:
   The client secret is the 27 character string listed adjacent to
   "secret" for the application.

password:
   The password for the Reddit account used to register the **script**
   application.

username:
   The username of the Reddit account used to register the **script**
   application.

With this information authorizing as "username" using a **script** app
is as simple as:

   reddit = praw.Reddit(client_id='SI8pN3DSbt0zor',
                        client_secret='xaxkj7HNh8kwg8e5t4m6KvSrbTI',
                        password='1guiwevlfo00esyy',
                        user_agent='testscript by /u/fakebot3',
                        username='fakebot3')

To verify that you are authenticated as the correct user run:

   print(reddit.user.me())

The output should contain the same name as you entered for "username".

Note: If the following exception is raised, double check your
  credentials, and ensure that that the username and password you are
  using are for the same user with which the script application is
  associated:

     OAuthException: invalid_grant error processing request


Two-Factor Authentication
-------------------------

A 2FA token can be used by joining it to the password with a colon:

   reddit = praw.Reddit(client_id='SI8pN3DSbt0zor',
                        client_secret='xaxkj7HNh8kwg8e5t4m6KvSrbTI',
                        password='1guiwevlfo00esyy:955413',
                        user_agent='testscript by /u/fakebot3',
                        username='fakebot3')

However, for an automated script there is little benefit to using 2FA.
The token must be refreshed after one hour; therefore, the 2FA secret
would have to be stored along with the rest of the credentials in
order to generate the token, which defeats the point of having an
extra credential beyond the password.

If you do choose to use 2FA, you must handle the
"prawcore.OAuthException" that will be raised by API calls after one
hour.


Web Application
===============

A **web** application is useful for two primary purposes:

* You have a website and want to be able to access Reddit from your
  users’ accounts.

* You want to limit the access one of your PRAW-based programs has
  to Reddit, or simply do not want to pass your username and password
  to PRAW.

When registering a **web** application you must provide a valid
redirect uri. If you are running a website you will want to enter the
appropriate callback URL and configure that endpoint to complete the
code flow.

If you aren’t actually running a website, you can use the Obtaining a
Refresh Token script to obtain "refresh_tokens". Enter
"http://localhost:8080" as the redirect uri when using this script.

Whether or not you use the script there are two processes involved in
obtaining access or refresh tokens.


Obtain the Authorization URL
----------------------------

The first step to completing the **web** application code flow is to
obtain the authorization URL. You can do that as follows:

   reddit = praw.Reddit(client_id='SI8pN3DSbt0zor',
                        client_secret='xaxkj7HNh8kwg8e5t4m6KvSrbTI',
                        redirect_uri='http://localhost:8080',
                        user_agent='testscript by /u/fakebot3')
   print(reddit.auth.url(['identity'], '...', 'permanent'))

The above will output an authorization URL for a permanent token that
has only the *identity* scope. See "url()" for more information on
these parameters.

This URL should be accessed by the account that desires to authorize
their Reddit access to your application. On completion of that flow,
the user’s browser will be redirected to the specified "redirect_uri".
After extracting verifying the "state" and extracting the "code" you
can obtain the refresh token via:

   print(reddit.auth.authorize(code))
   print(reddit.user.me())

The first line of output is the "refresh_token". You can save this for
later use (see Using a Saved Refresh Token).

The second line of output reveals the name of the Redditor that
completed the **web** application code flow. It also indicates that
the "reddit" instance is now associated with that account.


Installed Application
=====================

The code flow can be used with an **installed** application just as
described above with one change: set the value of "client_secret" to
"None" when initializing "Reddit".

The implicit flow is similar, however, the token is returned directly
as part of the redirect. For the implicit flow call "url()" like so:

   print(reddit.auth.url(['identity'], '...', implicit=True)

Then use "implicit()" to provide the authorization to the "Reddit"
instance.


Using a Saved Refresh Token
===========================

A saved refresh token can be used to immediately obtain an authorized
instance of "Reddit" like so:

   reddit = praw.Reddit(client_id='SI8pN3DSbt0zor',
                        client_secret='xaxkj7HNh8kwg8e5t4m6KvSrbTI',
                        refresh_token='WeheY7PwgeCZj4S3QgUcLhKE5S2s4eAYdxM',
                        user_agent='testscript by /u/fakebot3')
   print(reddit.auth.scopes())

The output from the above code displays which scopes are available on
the "Reddit" instance.

Note: Observe that "redirect_uri" does not need to be provided in
  such cases. It is only needed when "url()" is used.


Read Only Mode
==============

All application types support a read only mode. Read only mode
provides access to Reddit like a logged out user would see including
the default Subreddits in the "reddit.front" listings.

In the absence of a "refresh_token" both **web** and **installed**
applications start in the **read only** mode. With such applications
**read only** mode is disabled when "authorize()", "implicit()" are
successfully called. **Script** applications start up with **read
only** mode disabled.

Read only mode can be toggled via:

   # Enable read only mode
   reddit.read_only = True

   # Disable read only mode (must have a valid authorization)
   reddit.read_only = False
