-
Notifications
You must be signed in to change notification settings - Fork 127
OAuth2
###Types of Authentication
There are five types of authentication available under Reddit's OAuth implementation: Script, application-only, application-only installed app, installed app, and web.
- Web app: Runs as part of a web service on a server you control. Can keep a secret.
- Installed app: Runs on devices you don't control, such as the user's mobile phone. Cannot keep a secret, and therefore, does not receive one.
- Script app: Runs on hardware you control, such as your own laptop or server. Can keep a secret. Only has access to your account.
- Application-only: A web or script app acting in a user-less context.
- Application-only installed app: The summation of "installed app" and "application-only."
###Script and Application-Only
These types are the easiest to authenticate. Invoking OAuthHelper.easyAuth(Credentials)
will result in a OAuthData
instance, given the credentials are valid. An example:
RedditClient redditClient = new RedditClient(...);
// This could also be Credentials.userless() or .userlessApp()
Credentials credentials = Credentials.script(...);
OAuthData authData = redditClient.getOAuthHelper().easyAuth(credentials);
redditClient.authenticate(authData);
###Web and Installed Apps
Web and installed apps are harder to authenticate because they require the user to allow the app's permissions (scopes) action using a browser. A rough outline of this process goes as follows:
- Obtain an authorization URL using
getAuthorizationUrl(Credentials, boolean, String...)
. - Point the user's browser to that URL and have the user login and then press 'accept' on the authentication form. The URL that the browser redirects to will be your app's redirect URI with some arguments in the query.
- Provide this data as well as the same
Credentials
instance toOAuthHelper.onUserChallenge(String, Credentials)
. This method will parse the query arguments and report any errors. Once the response's integrity has been verified, a request to obtain the OAuth access code will be made and an instance ofOAuthData
retrieved.
A minimal example for Android:
public class MainActivity extends Activity {
private static final String REDIRECT_URL = ...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create our RedditClient
RedditClient reddit = new RedditClient(UserAgent.of(...));
final OAuthHelper helper = reddit.getOAuthHelper();
// This is Android, so our OAuth app should be an installed app.
final Credentials credentials = Credentials.installedApp(...);
// If this is true, then you will be able to refresh to access token
boolean permanent = true;
// OAuth2 scopes to request. See https://www.reddit.com/dev/api/oauth for a full list
String[] scopes = {"identity", "read"};
URL authorizationUrl = helper.getAuthorizationUrl(credentials, permanent, scopes);
// Load the authorization URL into the browser
webView.loadUrl(authorizationUrl.toExternalForm());
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (url.contains("code=")) {
// We've detected the redirect URL
new UserChallengeTask(helper, credentials).execute(url);
}
}
});
}
private static final class UserChallengeTask extends AsyncTask<String, Void, OAuthData> {
private OAuthHelper helper;
private Credentials creds;
public UserChallengeTask(OAuthHelper helper, Credentials creds) {
// <assign fields to parameters>
}
@Override
protected OAuthData doInBackground(String... params) {
try {
return helper.onUserChallenge(params[0], REDIRECT_URL, creds);
} catch (NetworkException | OAuthException e) {
// Handle me gracefully
}
}
@Override
protected void onPostExecute(OAuthData oAuthData) {
reddit.authenticate(oAuthData);
}
}
}
###Refreshing Access Tokens
To refresh an access token, the permission must have been requested during getAuthorizationUrl(Credentials, boolean, String...)
, where permanent = true
. Note that this disqualifies script and application-only apps. A new access token may be requested using OAuthHelper.refreshToken(Credentials)
. For example:
// Provided that 'redditClient' is an already-authenticated RedditClient
// and `credentials' is a Credentials object for a web/installed app:
OAuthData newAuthData = redditClient.getOAuthHelper().refreshToken(credentials);
redditClient.authenticate(newAuthData);
###Revoking Access Tokens
Good clients clean up after themselves. That's why OAuthHelper.revokeToken(Credentials)
is provided. Simply call this method when your app no longer needs to hold on to the access token and it will be invalidated.