├── ExampleWebsite
├── Bin
│ ├── OAuth2Class.dll
│ └── OAuth2Class.pdb
├── Web.config
├── auth.aspx
├── auth.aspx.cs
├── default.aspx
├── default.aspx.cs
├── global.asax
├── login.aspx
├── login.aspx.cs
└── web.Debug.config
├── OAuth2.sln
├── OAuth2.v12.suo
├── OAuth2Class
├── OAuth2.cs
├── OAuth2Class.csproj
├── Properties
│ └── AssemblyInfo.cs
├── bin
│ └── Debug
│ │ ├── OAuth2Class.dll
│ │ └── OAuth2Class.pdb
└── obj
│ └── Debug
│ ├── DesignTimeResolveAssemblyReferencesInput.cache
│ ├── OAuth2Class.csproj.FileListAbsolute.txt
│ ├── OAuth2Class.csprojResolveAssemblyReference.cache
│ ├── OAuth2Class.dll
│ ├── OAuth2Class.pdb
│ ├── TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
│ ├── TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
│ └── TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
├── license.md
└── readme.md
/ExampleWebsite/Bin/OAuth2Class.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/ExampleWebsite/Bin/OAuth2Class.dll
--------------------------------------------------------------------------------
/ExampleWebsite/Bin/OAuth2Class.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/ExampleWebsite/Bin/OAuth2Class.pdb
--------------------------------------------------------------------------------
/ExampleWebsite/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ExampleWebsite/auth.aspx:
--------------------------------------------------------------------------------
1 | <%@ Page Language="C#" AutoEventWireup="true" CodeFile="auth.aspx.cs" Inherits="auth" %>
--------------------------------------------------------------------------------
/ExampleWebsite/auth.aspx.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web.Configuration;
3 | using System.Web.UI;
4 |
5 | public partial class auth : Page {
6 | protected void Page_Load(object sender, EventArgs e) {
7 | // We get the provider from the passed URL itself. This is configured in
8 | // the global.asax file.
9 | var provider = this.RouteData.Values["provider"].ToString();
10 |
11 | // We fetch the clientID and clientSecret from the web.config appSettings.
12 | var clientID = WebConfigurationManager.AppSettings["OAuth2_" + provider + "_ClientID"];
13 | var clientSecret = WebConfigurationManager.AppSettings["OAuth2_" + provider + "_ClientSecret"];
14 |
15 | // Create a new instance of the class. Since this is the return trip-code
16 | // for this website, we don't need to give redirectURL and accessToken.
17 | var oauth2 = new FederatedLogin.OAuth2(
18 | clientID,
19 | clientSecret,
20 | provider);
21 |
22 | // Attempt to handle the response from the server and verify the login.
23 | oauth2.HandleResponse();
24 |
25 | // If we're authenticated, store the user info.
26 | if (oauth2.IsAuthorized) {
27 | Session["OAuth2_" + provider + "_AccessToken"] = oauth2.AccessToken;
28 | Session["OAuth2_" + provider + "_UserInfo"] = oauth2.UserInfo;
29 | }
30 |
31 | // If we encountered an error, log it!
32 | if (oauth2.Error != null) {
33 | Session["OAuth2_" + provider + "_Error"] = oauth2.Error;
34 | Session["OAuth2_" + provider + "_ErrorReason"] = oauth2.ErrorReason;
35 | Session["OAuth2_" + provider + "_ErrorDescription"] = oauth2.ErrorDescription;
36 | }
37 |
38 | // Redirect back to default.aspx.
39 | Response.Redirect("/");
40 | }
41 | }
--------------------------------------------------------------------------------
/ExampleWebsite/default.aspx:
--------------------------------------------------------------------------------
1 | <%@ Page Language="C#" AutoEventWireup="true" CodeFile="default.aspx.cs" Inherits="_default" %>
2 |
3 |
4 |
5 | OAuth2 Example Website
6 |
7 |
8 |
19 |
20 |
--------------------------------------------------------------------------------
/ExampleWebsite/default.aspx.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web.UI;
3 |
4 | public partial class _default : Page {
5 | protected void Page_Load(object sender, EventArgs e) {
6 | const string provider = "facebook";
7 |
8 | var userInfo = (Session["OAuth2_" + provider + "_UserInfo"] != null ? Session["OAuth2_" + provider + "_UserInfo"] as FederatedLogin.OAuth2.OAuth2UserInfo : null);
9 | var error = (Session["OAuth2_" + provider + "_Error"] != null ? Session["OAuth2_" + provider + "_Error"].ToString() : null);
10 | var errorReason = (Session["OAuth2_" + provider + "_ErrorReason"] != null ? Session["OAuth2_" + provider + "_ErrorReason"].ToString() : null);
11 | var errorDescription = (Session["OAuth2_" + provider + "_ErrorDescription"] != null ? Session["OAuth2_" + provider + "_ErrorDescription"].ToString() : null);
12 |
13 | if (userInfo != null)
14 | this.ltInfo.Text = "Logged in as " + userInfo.Name;
15 |
16 | if (error != null)
17 | this.ltError.Text =
18 | "Error: " + error + "
\r\n" +
19 | "ErrorReason: " + errorReason + "
\r\n" +
20 | "ErrorDescription: " + errorDescription + "
\r\n";
21 | }
22 | }
--------------------------------------------------------------------------------
/ExampleWebsite/global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Language="C#" %>
2 | <%@ Import Namespace="System.Web.Routing" %>
3 |
--------------------------------------------------------------------------------
/ExampleWebsite/login.aspx:
--------------------------------------------------------------------------------
1 | <%@ Page Language="C#" AutoEventWireup="true" CodeFile="login.aspx.cs" Inherits="login" %>
--------------------------------------------------------------------------------
/ExampleWebsite/login.aspx.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web.Configuration;
3 | using System.Web.UI;
4 |
5 | public partial class login : Page {
6 | protected void Page_Load(object sender, EventArgs e) {
7 | // We get the provider from the passed URL itself. This is configured in
8 | // the global.asax file.
9 | var provider = this.RouteData.Values["provider"].ToString();
10 |
11 | // We fetch the clientID and clientSecret from the web.config appSettings.
12 | var clientID = WebConfigurationManager.AppSettings["OAuth2_" + provider + "_ClientID"];
13 | var clientSecret = WebConfigurationManager.AppSettings["OAuth2_" + provider + "_ClientSecret"];
14 |
15 | // Fetch the access token from the session, so if we've already been logged
16 | // in to Facebook, we can just refresh the token.
17 | string accessToken = null;
18 | if (Session["OAuth2_" + provider + "_AccessToken"] != null)
19 | accessToken = Session["OAuth2_" + provider + "_AccessToken"].ToString();
20 |
21 | // Create a new instance of the class. If we don't provide the redirectURL
22 | // parameter, it will be automatically constructed as /login//auth.
23 | var oauth2 = new FederatedLogin.OAuth2(
24 | clientID,
25 | clientSecret,
26 | provider,
27 | null,
28 | accessToken);
29 |
30 | // Now we're ready to init the authentication part of our routine. If we
31 | // didn't pass in any access-token or the token isn't valid, the user will
32 | // be forwarded to the provider at this time for re-validation.
33 | oauth2.Authenticate();
34 |
35 | // If we're authenticated, store the user info.
36 | if (oauth2.IsAuthorized) {
37 | Session["OAuth2_" + provider + "_AccessToken"] = oauth2.AccessToken;
38 | Session["OAuth2_" + provider + "_UserInfo"] = oauth2.UserInfo;
39 | }
40 |
41 | // If we encountered an error, log it!
42 | if (oauth2.Error != null) {
43 | Session["OAuth2_" + provider + "_Error"] = oauth2.Error;
44 | Session["OAuth2_" + provider + "_ErrorReason"] = oauth2.ErrorReason;
45 | Session["OAuth2_" + provider + "_ErrorDescription"] = oauth2.ErrorDescription;
46 | }
47 |
48 | // Redirect back to default.aspx.
49 | Response.Redirect("/");
50 | }
51 | }
--------------------------------------------------------------------------------
/ExampleWebsite/web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/OAuth2.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuth2Class", "OAuth2Class\OAuth2Class.csproj", "{79F2A6B2-EC0F-4792-8316-CC85CDE346D5}"
7 | EndProject
8 | Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "ExampleWebsite(1)", "http://localhost:49937", "{ED17D93D-8D8C-4CC6-9593-BF2AF425AFD5}"
9 | ProjectSection(WebsiteProperties) = preProject
10 | UseIISExpress = "true"
11 | TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.5"
12 | ProjectReferences = "{79f2a6b2-ec0f-4792-8316-cc85cde346d5}|OAuth2Class.dll;"
13 | Debug.AspNetCompiler.VirtualPath = "/localhost_49937"
14 | Debug.AspNetCompiler.PhysicalPath = "ExampleWebsite\"
15 | Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_49937\"
16 | Debug.AspNetCompiler.Updateable = "true"
17 | Debug.AspNetCompiler.ForceOverwrite = "true"
18 | Debug.AspNetCompiler.FixedNames = "false"
19 | Debug.AspNetCompiler.Debug = "True"
20 | Release.AspNetCompiler.VirtualPath = "/localhost_49937"
21 | Release.AspNetCompiler.PhysicalPath = "ExampleWebsite\"
22 | Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_49937\"
23 | Release.AspNetCompiler.Updateable = "true"
24 | Release.AspNetCompiler.ForceOverwrite = "true"
25 | Release.AspNetCompiler.FixedNames = "false"
26 | Release.AspNetCompiler.Debug = "False"
27 | SlnRelativePath = "ExampleWebsite\"
28 | DefaultWebSiteLanguage = "Visual C#"
29 | EndProjectSection
30 | EndProject
31 | Global
32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
33 | Debug|Any CPU = Debug|Any CPU
34 | Release|Any CPU = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
37 | {79F2A6B2-EC0F-4792-8316-CC85CDE346D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {79F2A6B2-EC0F-4792-8316-CC85CDE346D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {79F2A6B2-EC0F-4792-8316-CC85CDE346D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {79F2A6B2-EC0F-4792-8316-CC85CDE346D5}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {ED17D93D-8D8C-4CC6-9593-BF2AF425AFD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {ED17D93D-8D8C-4CC6-9593-BF2AF425AFD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {ED17D93D-8D8C-4CC6-9593-BF2AF425AFD5}.Release|Any CPU.ActiveCfg = Debug|Any CPU
44 | {ED17D93D-8D8C-4CC6-9593-BF2AF425AFD5}.Release|Any CPU.Build.0 = Debug|Any CPU
45 | EndGlobalSection
46 | GlobalSection(SolutionProperties) = preSolution
47 | HideSolutionNode = FALSE
48 | EndGlobalSection
49 | EndGlobal
50 |
--------------------------------------------------------------------------------
/OAuth2.v12.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2.v12.suo
--------------------------------------------------------------------------------
/OAuth2Class/OAuth2.cs:
--------------------------------------------------------------------------------
1 | // @file
2 | // A lightweight library for OAuth2 authentication.
3 | //
4 | // @author
5 | // Stian Hanger
6 | //
7 | // @url
8 | // https://github.com/nagilum/OAuth2Csharp
9 |
10 | using System;
11 | using System.Collections.Generic;
12 | using System.IO;
13 | using System.Linq;
14 | using System.Net;
15 | using System.ServiceModel;
16 | using System.Web;
17 | using System.Web.Script.Serialization;
18 |
19 | namespace FederatedLogin {
20 | ///
21 | /// Authorization, refresh, and validation of users through OAuth2.
22 | ///
23 | public class OAuth2 {
24 | ///
25 | /// A list of pre-defined provider endpoints.
26 | ///
27 | private readonly List endpoints = new List {
28 | new OAuth2Endpoint {
29 | Provider = "Facebook",
30 | AuthURL = "https://graph.facebook.com/oauth/authorize",
31 | AccessTokenURL = "https://graph.facebook.com/oauth/access_token",
32 | RefreshTokenURL = "https://graph.facebook.com/oauth/client_code",
33 | UserInfoURL = "https://graph.facebook.com/me"
34 | }
35 | };
36 |
37 | ///
38 | /// The current request object to use throughout the library.
39 | ///
40 | private readonly HttpRequest request = HttpContext.Current.Request;
41 |
42 | ///
43 | /// The current response object to use throughout the library.
44 | ///
45 | private readonly HttpResponse response = HttpContext.Current.Response;
46 |
47 | ///
48 | /// ClientID given by provider.
49 | ///
50 | private string clientID { get; set; }
51 |
52 | ///
53 | /// ClientSecret issued by provider.
54 | ///
55 | private string clientSecret { get; set; }
56 |
57 | ///
58 | /// Name of provider.
59 | ///
60 | private string provider { get; set; }
61 |
62 | ///
63 | /// URL for provider to redirect back to when auth is completed.
64 | ///
65 | private string redirectURL { get; set; }
66 |
67 | ///
68 | /// Access token issued by provider.
69 | ///
70 | public string AccessToken { get; private set; }
71 |
72 | ///
73 | /// Expiration date of the issued access token.
74 | ///
75 | public DateTime AccessTokenExpiration { get; private set; }
76 |
77 | ///
78 | /// The type of token issued by the provider.
79 | ///
80 | public string TokenType { get; set; }
81 |
82 | ///
83 | /// Reflects whether or not the user has been authorized.
84 | ///
85 | public bool IsAuthorized { get; private set; }
86 |
87 | ///
88 | /// Parsed user-info from serialized info from provider.
89 | ///
90 | public OAuth2UserInfo UserInfo { get; private set; }
91 |
92 | ///
93 | /// Serialized string of the user-info response from provider.
94 | ///
95 | public string UserInfoSerialized { get; private set; }
96 |
97 | ///
98 | /// General error message from provider.
99 | ///
100 | public string Error { get; set; }
101 |
102 | ///
103 | /// Reason for error, from provider.
104 | ///
105 | public string ErrorReason { get; set; }
106 |
107 | ///
108 | /// Description of error, from provider.
109 | ///
110 | public string ErrorDescription { get; set; }
111 |
112 | ///
113 | /// Initiate a new instance of the OAuth2 library.
114 | ///
115 | /// ClientID given by provider.
116 | /// ClientSecret issued by provider.
117 | /// Name of provider.
118 | /// URL for provider to redirect back to when auth is completed.
119 | /// (optional) Access token to refresh.
120 | public OAuth2(string clientID, string clientSecret, string provider, string redirectURL = null, string accessToken = null) {
121 | if (string.IsNullOrWhiteSpace(clientID) ||
122 | string.IsNullOrWhiteSpace(clientSecret))
123 | throw new MissingFieldException("Both clientID and clientSecret are required!");
124 |
125 | var endpoint =
126 | this.endpoints.SingleOrDefault(ep => ep.Provider.Equals(provider, StringComparison.CurrentCultureIgnoreCase));
127 |
128 | if (endpoint == null)
129 | throw new EndpointNotFoundException("Missing endpoint for given provider: " + provider);
130 |
131 | if (string.IsNullOrWhiteSpace(redirectURL))
132 | redirectURL =
133 | this.request.Url.Scheme +
134 | "://" +
135 | this.request.Url.Authority +
136 | "/login/" + provider + "/auth";
137 |
138 | this.clientID = clientID;
139 | this.clientSecret = clientSecret;
140 | this.provider = provider;
141 | this.redirectURL = redirectURL;
142 |
143 | this.AccessToken = accessToken;
144 | }
145 |
146 | ///
147 | /// Add an endpoint.
148 | ///
149 | /// Name of the provider.
150 | /// URL for user-redirection to provider auth-page.
151 | /// URL for access token validation.
152 | /// URL for access token refresh.
153 | /// URL for user infomation gathering.
154 | /// Provider-scope, if any.
155 | public void AddEndpoint(string provider, string authURL, string accessTokenURL, string refreshTokenURL, string userInfoURL, string scope = null) {
156 | this.endpoints.Add(
157 | new OAuth2Endpoint {
158 | Provider = provider,
159 | AuthURL = authURL,
160 | Scope = scope
161 | });
162 | }
163 |
164 | ///
165 | /// Redirect the user to the providers auth-page, or attempt to re-validate the stored access-token.
166 | ///
167 | public void Authenticate() {
168 | List> parameters;
169 | string url;
170 |
171 | var endpoint =
172 | this.endpoints.Single(ep => ep.Provider.Equals(provider, StringComparison.CurrentCultureIgnoreCase));
173 |
174 | if (!string.IsNullOrWhiteSpace(this.AccessToken)) {
175 | parameters = new List> {
176 | new Tuple("access_token", this.AccessToken),
177 | new Tuple("client_id", this.clientID),
178 | new Tuple("client_secret", this.clientSecret),
179 | new Tuple("redirect_uri", this.redirectURL)
180 | };
181 |
182 | url =
183 | endpoint.RefreshTokenURL + "?" +
184 | this.buildQueryString(parameters);
185 |
186 | var resp = this.makeWebRequest(url);
187 | var code = "";
188 |
189 | try {
190 | code = new JavaScriptSerializer().Deserialize(resp).Code;
191 | }
192 | catch (Exception ex) {
193 | this.Error = "Unable to parse JSON response.";
194 | this.ErrorDescription = ex.Message;
195 | }
196 |
197 | if (!string.IsNullOrWhiteSpace(code))
198 | this.handleCodeResponse(code);
199 |
200 | if (this.IsAuthorized)
201 | return;
202 | }
203 |
204 | parameters = new List> {
205 | new Tuple("client_id", this.clientID),
206 | new Tuple("display", "page"),
207 | new Tuple("locale", "en"),
208 | new Tuple("redirect_uri", this.redirectURL),
209 | new Tuple("response_type", "code")
210 | };
211 |
212 | if (!string.IsNullOrWhiteSpace(endpoint.Scope))
213 | parameters.Add(
214 | new Tuple("scope", endpoint.Scope));
215 |
216 | url =
217 | endpoint.AuthURL + "?" +
218 | this.buildQueryString(parameters);
219 |
220 | this.response.Redirect(url, true);
221 | }
222 |
223 | ///
224 | /// Check for OAuth2 code response and attempt to validate it.
225 | ///
226 | public void HandleResponse() {
227 | if (this.request.QueryString["code"] == null)
228 | return;
229 |
230 | var code = this.request.QueryString["code"];
231 | var error = this.request.QueryString["error"];
232 |
233 | if (!string.IsNullOrWhiteSpace(code)) {
234 | this.handleCodeResponse(code);
235 | }
236 | else if (!string.IsNullOrWhiteSpace(error)) {
237 | this.Error = error;
238 | this.ErrorReason = this.request.QueryString["error_reason"];
239 | this.ErrorDescription = this.request.QueryString["error_description"];
240 | }
241 | }
242 |
243 | ///
244 | /// Validate a user by checking the 'code' variable against the provider.
245 | ///
246 | /// Code to validate.
247 | private void handleCodeResponse(string code) {
248 | var parameters = new List> {
249 | new Tuple("client_id", this.clientID),
250 | new Tuple("redirect_uri", this.redirectURL),
251 | new Tuple("client_secret", this.clientSecret),
252 | new Tuple("code", code)
253 | };
254 |
255 | var endpoint =
256 | this.endpoints.Single(ep => ep.Provider.Equals(provider, StringComparison.CurrentCultureIgnoreCase));
257 |
258 | var url =
259 | endpoint.AccessTokenURL + "?" +
260 | this.buildQueryString(parameters);
261 |
262 | var resp = this.makeWebRequest(url);
263 |
264 | if (this.Error != null)
265 | return;
266 |
267 | this.analyzeAccessTokenResponse(resp);
268 |
269 | if (string.IsNullOrWhiteSpace(this.AccessToken) &&
270 | !this.IsAuthorized)
271 | return;
272 |
273 | parameters = new List> {
274 | new Tuple("access_token", this.AccessToken)
275 | };
276 |
277 | url =
278 | endpoint.UserInfoURL + "?" +
279 | this.buildQueryString(parameters);
280 |
281 | resp = this.makeWebRequest(url);
282 | this.analyzeUserInfoResponse(resp);
283 | }
284 |
285 | ///
286 | /// Attempt to analyze access-token response, either in string or JSON format.
287 | ///
288 | /// Strong or JSON response.
289 | private void analyzeAccessTokenResponse(string resp) {
290 | if (resp == null)
291 | return;
292 |
293 | this.AccessToken = null;
294 | this.AccessTokenExpiration = DateTime.MinValue;
295 |
296 | if (resp.StartsWith("{") &&
297 | resp.EndsWith("}")) {
298 | try {
299 | var cr = new JavaScriptSerializer().Deserialize(resp);
300 |
301 | if (!string.IsNullOrWhiteSpace(cr.Access_Token))
302 | this.AccessToken = cr.Access_Token;
303 |
304 | if (cr.Expires_In > 0)
305 | this.AccessTokenExpiration = DateTime.Now.AddSeconds(cr.Expires_In);
306 |
307 | if (!string.IsNullOrWhiteSpace(cr.Token_Type))
308 | this.TokenType = cr.Token_Type;
309 | }
310 | catch (Exception ex) {
311 | this.Error = "Unable to parse JSON response.";
312 | this.ErrorDescription = ex.Message;
313 | }
314 | }
315 | else {
316 | foreach (var entry in resp.Split('&')) {
317 | if (entry.IndexOf('=') == -1)
318 | continue;
319 |
320 | var key = entry.Substring(0, entry.IndexOf('='));
321 | var val = entry.Substring(entry.IndexOf('=') + 1);
322 |
323 | switch (key) {
324 | case "access_token":
325 | this.AccessToken = val;
326 | break;
327 |
328 | case "expires":
329 | case "expires_in":
330 | int exp;
331 | if (int.TryParse(val, out exp))
332 | this.AccessTokenExpiration = DateTime.Now.AddSeconds(exp);
333 |
334 | break;
335 |
336 | case "token_type":
337 | this.TokenType = val;
338 | break;
339 | }
340 | }
341 | }
342 |
343 | this.IsAuthorized = (!string.IsNullOrWhiteSpace(this.AccessToken) &&
344 | this.AccessTokenExpiration > DateTime.Now);
345 | }
346 |
347 | ///
348 | /// Attempt to analyze the user-info JSON object from provider.
349 | ///
350 | /// Serialized JSON object.
351 | private void analyzeUserInfoResponse(string resp) {
352 | if (resp == null)
353 | return;
354 |
355 | this.UserInfoSerialized = resp;
356 |
357 | try {
358 | this.UserInfo = new JavaScriptSerializer().Deserialize(resp);
359 | }
360 | catch (Exception ex) {
361 | this.Error = "Unable to parse JSON response.";
362 | this.ErrorDescription = ex.Message;
363 | }
364 | }
365 |
366 | ///
367 | /// Compiles a list of parameters into a working query-string.
368 | ///
369 | /// Parameters to compile.
370 | /// Compilled query-string.
371 | private string buildQueryString(IEnumerable> parameteres) {
372 | return
373 | parameteres.Aggregate("", (current, parameter) => current + ("&" + parameter.Item1 + "=" + HttpUtility.UrlEncode(parameter.Item2)))
374 | .Substring(1);
375 | }
376 |
377 | ///
378 | /// Perform a HTTP web request to a given URL.
379 | ///
380 | /// URL to request.
381 | /// String of response.
382 | private string makeWebRequest(string url) {
383 | try {
384 | var req = WebRequest.Create(url);
385 | var res = req.GetResponse();
386 | var httpres = res as HttpWebResponse;
387 | var status = 0;
388 |
389 | if (httpres != null)
390 | status = (int)httpres.StatusCode;
391 |
392 | if (status != 200)
393 | return null;
394 |
395 | var stream = res.GetResponseStream();
396 |
397 | if (stream == null)
398 | return null;
399 |
400 | var reader = new StreamReader(stream);
401 | var resp = reader.ReadToEnd();
402 |
403 | reader.Close();
404 | stream.Close();
405 |
406 | return resp;
407 | }
408 | catch (Exception ex) {
409 | this.Error = "Unable to properly make HTTP request.";
410 | this.ErrorDescription = ex.Message;
411 | }
412 |
413 | return null;
414 | }
415 |
416 | ///
417 | /// Endpoint to use for validation.
418 | ///
419 | private class OAuth2Endpoint {
420 | ///
421 | /// Name of provider.
422 | ///
423 | public string Provider { get; set; }
424 |
425 | ///
426 | /// URL for user-redirection to provider auth-page.
427 | ///
428 | public string AuthURL { get; set; }
429 |
430 | ///
431 | /// URL for access token validation.
432 | ///
433 | public string AccessTokenURL { get; set; }
434 |
435 | ///
436 | /// URL for access token refresh.
437 | ///
438 | public string RefreshTokenURL { get; set; }
439 |
440 | ///
441 | /// URL for user infomation gathering.
442 | ///
443 | public string UserInfoURL { get; set; }
444 |
445 | ///
446 | /// Provider-scope, if any.
447 | ///
448 | public string Scope { get; set; }
449 | }
450 |
451 | ///
452 | /// Object for json parsed code-response from provider.
453 | ///
454 | private class OAuth2CodeResponse {
455 | ///
456 | /// Code from provider.
457 | ///
458 | public string Code { get; set; }
459 |
460 | ///
461 | /// Token issued by the provider.
462 | ///
463 | public string Access_Token { get; set; }
464 |
465 | ///
466 | /// Amount of second til token expires.
467 | ///
468 | public int Expires_In { get; set; }
469 |
470 | ///
471 | /// The type of token issued by the provider.
472 | ///
473 | public string Token_Type { get; set; }
474 | }
475 |
476 | ///
477 | /// Object to store providers user-info.
478 | ///
479 | public class OAuth2UserInfo {
480 | ///
481 | /// ID issued by provider.
482 | ///
483 | public string ID { get; set; }
484 |
485 | ///
486 | /// E-mail for user.
487 | ///
488 | public string Email { get; set; }
489 |
490 | ///
491 | /// First name of user.
492 | ///
493 | public string FirstName { get; set; }
494 |
495 | ///
496 | /// First name of user.
497 | ///
498 | public string First_Name { get; set; }
499 |
500 | ///
501 | /// Last name of user.
502 | ///
503 | public string LastName { get; set; }
504 |
505 | ///
506 | /// Last name of user.
507 | ///
508 | public string Last_Name { get; set; }
509 |
510 | ///
511 | /// Full name of user.
512 | ///
513 | public string Name { get; set; }
514 |
515 | ///
516 | /// Gender of user.
517 | ///
518 | public string Gender { get; set; }
519 |
520 | ///
521 | /// Locale of user.
522 | ///
523 | public string Locale { get; set; }
524 |
525 | ///
526 | /// Time-zone of user.
527 | ///
528 | public int TimeZone { get; set; }
529 |
530 | ///
531 | /// Username of user.
532 | ///
533 | public string Username { get; set; }
534 | }
535 | }
536 | }
--------------------------------------------------------------------------------
/OAuth2Class/OAuth2Class.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {79F2A6B2-EC0F-4792-8316-CC85CDE346D5}
8 | Library
9 | Properties
10 | OAuth2Class
11 | OAuth2Class
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
56 |
--------------------------------------------------------------------------------
/OAuth2Class/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("OAuth2Class")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("OAuth2Class")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a3651757-3052-48e9-bdb1-fa16621726ec")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/OAuth2Class/bin/Debug/OAuth2Class.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/bin/Debug/OAuth2Class.dll
--------------------------------------------------------------------------------
/OAuth2Class/bin/Debug/OAuth2Class.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/bin/Debug/OAuth2Class.pdb
--------------------------------------------------------------------------------
/OAuth2Class/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
--------------------------------------------------------------------------------
/OAuth2Class/obj/Debug/OAuth2Class.csproj.FileListAbsolute.txt:
--------------------------------------------------------------------------------
1 | C:\Users\stianh\Documents\GitHub\OAuth2\OAuth2Class\bin\Debug\OAuth2Class.dll
2 | C:\Users\stianh\Documents\GitHub\OAuth2\OAuth2Class\bin\Debug\OAuth2Class.pdb
3 | C:\Users\stianh\Documents\GitHub\OAuth2\OAuth2Class\obj\Debug\OAuth2Class.csprojResolveAssemblyReference.cache
4 | C:\Users\stianh\Documents\GitHub\OAuth2\OAuth2Class\obj\Debug\OAuth2Class.dll
5 | C:\Users\stianh\Documents\GitHub\OAuth2\OAuth2Class\obj\Debug\OAuth2Class.pdb
6 |
--------------------------------------------------------------------------------
/OAuth2Class/obj/Debug/OAuth2Class.csprojResolveAssemblyReference.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/obj/Debug/OAuth2Class.csprojResolveAssemblyReference.cache
--------------------------------------------------------------------------------
/OAuth2Class/obj/Debug/OAuth2Class.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/obj/Debug/OAuth2Class.dll
--------------------------------------------------------------------------------
/OAuth2Class/obj/Debug/OAuth2Class.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/obj/Debug/OAuth2Class.pdb
--------------------------------------------------------------------------------
/OAuth2Class/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
--------------------------------------------------------------------------------
/OAuth2Class/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
--------------------------------------------------------------------------------
/OAuth2Class/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nagilum/-DEPRECATED-OAuth2Csharp/54bb143bbecf5b3302e30fcf953b9c9d26dd0151/OAuth2Class/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014, Stian Hanger
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # DEPRECATED
2 |
3 | This code is rather messy and I've written a more lean version over at https://github.com/nagilum/oauth2-csharp
4 |
5 |
6 |
7 | ## OAuth2 lib for Csharp
8 |
9 | A lightweight library for OAuth2 authentication.
10 |
11 | Requirements
12 | ------------
13 |
14 | The only file in the given solution that is nessecary is the OAuth2.cs file in the OAuth2Class folder.
15 | The rest is just added as an example of how you can structure the entire thing, either use is as a direct .cs file or as a assembly DLL.
16 |
17 | Usage
18 | -----
19 |
20 | Put this code on the login page:
21 |
22 | ```csharp
23 | var clientID = 'your-apps-client-id';
24 | var clientSecret = 'your-apps-client-secret';
25 | var provider = 'provider to use';
26 |
27 | // This is the URL the provider will send the user back to after authorization.
28 | // If you set this to null it will be constructed using the URL authority and
29 | // sub-path /login//auth
30 | var redirectURL = 'url-for-provider-return';
31 |
32 | // If you have the users access-token from a previous login with the same
33 | // provider, you can suply it here and the lib will try to refresh it so the
34 | // user don't have to take the round-trip to the provider. Set this to null
35 | // if you don't have it.
36 | var accessToken = 'stored-access-token-for-user';
37 |
38 | var oauth2 = new OAuth2(
39 | clientID,
40 | clientSecret,
41 | provider,
42 | redirectURL,
43 | accessToken);
44 |
45 | // This will try and refresh the access token if you specified id, if not, the
46 | // user will be forwarded to the providers login-page for authorization and
47 | // the request stops here.
48 | oauth2.Authenticate();
49 |
50 | if (oauth2.IsAuthorized) {
51 | // This code will trigger if the access-token was simply refreshed (and is
52 | // still valid). So here you can proceed with normal access-granted stuff.
53 | }
54 | ```
55 |
56 | Put this code on the auth page:
57 |
58 | ```csharp
59 | var clientID = 'your-apps-client-id';
60 | var clientSecret = 'your-apps-client-secret';
61 | var provider = 'provider to use';
62 |
63 | var oauth2 = new OAuth2(
64 | clientID,
65 | clientSecret,
66 | provider,
67 | redirectURL,
68 | accessToken);
69 |
70 | // Attempt to validate the code-response from the provider and retrieve a valid
71 | // access-token.
72 | oauth2.HandleResponse();
73 |
74 | if (oauth2.IsAuthorized) {
75 | // If the lib received a valid access-token, this code will trigger, and you
76 | // can go about your business as normal.
77 | }
78 | ```
79 |
80 | Properties
81 | ----------
82 |
83 | **AccessToken** (string)
84 |
85 | The valid access token issued by the provider.
86 |
87 | **AccessTokenExpiration** (DateTime)
88 |
89 | Exact date-time when the access token expires.
90 |
91 | **TokenType** (string)
92 |
93 | Which type of token the provider issued. f.eks: Bearer, so you can use it for
94 | API calls and the like.
95 |
96 | **IsAuthorized** (bool)
97 |
98 | Indicating whether or not the authentication process was completed and the user
99 | was successfully authorized by the provider, aka the go-signal.
100 |
101 | **UserInfo** (class)
102 |
103 | Formatted collection of user-information provided by the provider.
104 |
105 | **UserInfoSerialized** (string)
106 |
107 | Serialized JSON from the provider with user-info which was used to parse
108 | formatted info to the UserInfo class.
109 |
110 | **Error**, **ErrorReason**, and **ErrorDescription** (string)
111 |
112 | If an error occurred during the auth process, this is where the info about it
113 | will be.
114 |
115 | Additional Functions
116 | --------------------
117 |
118 | **AddEndpoint**
119 |
120 | You can use this function to programatically add additional endpoints for use.
121 | Obviously this has to be done prior to calling the ```Authenticate()``` function.
122 |
123 | ```csharp
124 | oauth2.AddEndpoint(
125 | 'provider-name',
126 | 'auth-url', // URL for user-redirection to provider auth-page.
127 | 'access-token-url', // URL for access token validation.
128 | 'refresh-token-url', // URL for access token refresh.
129 | 'user-info-url', // URL for user infomation gathering.
130 | 'scope' // Provider-scope, if any.
131 | );
132 | ```
133 |
--------------------------------------------------------------------------------