Files
Gardient 9583c1afb2 First actual commit
added sources to repository
2015-08-28 21:49:50 +03:00

175 lines
6.9 KiB
C#

using System;
using System.Net;
using System.Security.Authentication;
using System.Text;
using Newtonsoft.Json.Linq;
using RedditSharp.Things;
namespace RedditSharp
{
public class AuthProvider
{
private const string AccessUrl = "https://ssl.reddit.com/api/v1/access_token";
private const string OauthGetMeUrl = "https://oauth.reddit.com/api/v1/me";
public static string OAuthToken { get; set; }
public static string RefreshToken { get; set; }
[Flags]
public enum Scope
{
none = 0x0,
identity = 0x1,
edit = 0x2,
flair = 0x4,
history = 0x8,
modconfig = 0x10,
modflair = 0x20,
modlog = 0x40,
modposts = 0x80,
modwiki = 0x100,
mysubreddits = 0x200,
privatemessages = 0x400,
read = 0x800,
report = 0x1000,
save = 0x2000,
submit = 0x4000,
subscribe = 0x8000,
vote = 0x10000,
wikiedit = 0x20000,
wikiread = 0x40000
}
private readonly IWebAgent _webAgent;
private readonly string _redirectUri;
private readonly string _clientId;
private readonly string _clientSecret;
/// <summary>
/// Allows use of reddit's OAuth interface, using an app set up at https://ssl.reddit.com/prefs/apps/.
/// </summary>
/// <param name="clientId">Granted by reddit as part of app.</param>
/// <param name="clientSecret">Granted by reddit as part of app.</param>
/// <param name="redirectUri">Selected as part of app. Reddit will send users back here.</param>
public AuthProvider(string clientId, string clientSecret, string redirectUri)
{
_clientId = clientId;
_clientSecret = clientSecret;
_redirectUri = redirectUri;
_webAgent = new WebAgent();
}
/// <summary>
/// Creates the reddit OAuth2 Url to redirect the user to for authorization.
/// </summary>
/// <param name="state">Used to verify that the user received is the user that was sent</param>
/// <param name="scope">Determines what actions can be performed against the user.</param>
/// <param name="permanent">Set to true for access lasting longer than one hour.</param>
/// <returns></returns>
public string GetAuthUrl(string state, Scope scope, bool permanent = false)
{
return String.Format("https://ssl.reddit.com/api/v1/authorize?client_id={0}&response_type=code&state={1}&redirect_uri={2}&duration={3}&scope={4}", _clientId, state, _redirectUri, permanent ? "permanent" : "temporary", scope.ToString().Replace(" ",""));
}
/// <summary>
/// Gets the OAuth token for the user associated with the provided code.
/// </summary>
/// <param name="code">Sent by reddit as a parameter in the return uri.</param>
/// <param name="isRefresh">Set to true for refresh requests.</param>
/// <returns></returns>
public string GetOAuthToken(string code, bool isRefresh = false)
{
if (Type.GetType("Mono.Runtime") != null)
ServicePointManager.ServerCertificateValidationCallback = (s, c, ch, ssl) => true;
_webAgent.Cookies = new CookieContainer();
var request = _webAgent.CreatePost(AccessUrl);
request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(_clientId + ":" + _clientSecret));
var stream = request.GetRequestStream();
if (isRefresh)
{
_webAgent.WritePostBody(stream, new
{
grant_type = "refresh_token",
refresh_token = code
});
}
else
{
_webAgent.WritePostBody(stream, new
{
grant_type = "authorization_code",
code,
redirect_uri = _redirectUri
});
}
stream.Close();
var json = _webAgent.ExecuteRequest(request);
if (json["access_token"] != null)
{
if (json["refresh_token"] != null)
RefreshToken = json["refresh_token"].ToString();
OAuthToken = json["access_token"].ToString();
return json["access_token"].ToString();
}
throw new AuthenticationException("Could not log in.");
}
/// <summary>
/// Gets the OAuth token for the user.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="password">The user's password.</param>
/// <returns>The access token</returns>
public string GetOAuthToken(string username, string password)
{
if (Type.GetType("Mono.Runtime") != null)
ServicePointManager.ServerCertificateValidationCallback = (s, c, ch, ssl) => true;
_webAgent.Cookies = new CookieContainer();
var request = _webAgent.CreatePost(AccessUrl);
request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(_clientId + ":" + _clientSecret));
var stream = request.GetRequestStream();
_webAgent.WritePostBody(stream, new
{
grant_type = "password",
username,
password,
redirect_uri = _redirectUri
});
stream.Close();
var json = _webAgent.ExecuteRequest(request);
if (json["access_token"] != null)
{
if (json["refresh_token"] != null)
RefreshToken = json["refresh_token"].ToString();
OAuthToken = json["access_token"].ToString();
return json["access_token"].ToString();
}
throw new AuthenticationException("Could not log in.");
}
/// <summary>
/// Gets a user authenticated by OAuth2.
/// </summary>
/// <param name="accessToken">Obtained using GetOAuthToken</param>
/// <returns></returns>
[Obsolete("Reddit.InitOrUpdateUser is preferred")]
public AuthenticatedUser GetUser(string accessToken)
{
var request = _webAgent.CreateGet(OauthGetMeUrl);
request.Headers["Authorization"] = String.Format("bearer {0}", accessToken);
var response = (HttpWebResponse)request.GetResponse();
var result = _webAgent.GetResponseString(response.GetResponseStream());
var thingjson = "{\"kind\": \"t2\", \"data\": " + result + "}";
var json = JObject.Parse(thingjson);
return new AuthenticatedUser().Init(new Reddit(), json, _webAgent);
}
}
}