-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSomeoneIdClient.cs
315 lines (273 loc) · 10.7 KB
/
SomeoneIdClient.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
using SomeoneId.Net.Models;
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Web;
using System.Web.Script.Serialization;
namespace SomeoneId.Net
{
public class SomeoneIdClient
{
private const string SessionStateKey = "SomeoneId.Net.Client.State";
/// <summary>
/// service base uri
/// </summary>
public string BasePath { get; set; } = "https://www.someone.id/";
/// <summary>
/// service logon page
/// </summary>
public string LogonEndpoint
{
get { return BasePath + "account/Logon"; }
}
/// <summary>
/// service endpoint that return the accesstoken
/// </summary>
public string TokenEndpoint
{
get { return BasePath + "oauth/AccessToken"; }
}
/// <summary>
/// service endpoint that return the info about the logged user
/// according to logon request scope
/// </summary>
public string MeEndpoint
{
get { return BasePath + "oauth/Me"; }
}
private string clientId = "";
/// <summary>
/// registered app unique identifier on someone.id
/// </summary>
public string ClientId
{
get { return clientId; }
}
private string clientSecret = "";
/// <summary>
/// oauth secret key used to obtain AccessToken.
/// Always keep safe this code
/// </summary>
public string ClientSecret
{
get { return clientSecret; }
}
private string callbackUri = "";
/// <summary>
/// your application callback url.
/// The same you set during app creation
/// </summary>
public string CallbackUri
{
get { return callbackUri; }
}
private string cancelUrl = "";
/// <summary>
/// used when user go back to app
/// </summary>
public string CancelUrl
{
get { return cancelUrl; }
}
private string scope = "email";
/// <summary>
/// Include one or more scope values (space-separated) to request additional levels of access.
/// </summary>
public string Scope
{
set { scope = value; }
get { return scope; }
}
/// <summary>
/// (recommended)
/// The state parameter serves two functions. When the user is redirected back to your app, whatever value
/// you include as the state will also be included in the redirect. This gives your app a chance to persist
/// data between the user being directed to the authorization server and back again, such as using the state
/// parameter as a session key. This may be used to indicate what action in the app to perform after authorization
/// is complete, for example, indicating which of your app’s pages to redirect to after authorization.
/// This also serves as a CSRF protection mechanism.
/// When the user is redirected back to your app, double check that the state value matches what you
/// set it to originally. This will ensure an attacker can’t intercept the authorization flow.
/// </summary>
public string State
{
get
{
string res = "";
if (HttpContext.Current.Session[SessionStateKey] != null)
{
res = HttpContext.Current.Session[SessionStateKey].ToString();
}
return res;
}
}
private string accessToken = "";
public string AccessToken
{
get { return accessToken; }
}
/// <summary>
/// init app settings using web.config
/// </summary>
public SomeoneIdClient()
{
string clientId = getConfigValue("SomeoneClientId");
string clientSecret = getConfigValue("SomeoneClientSecret");
string callbackUri = getConfigValue("SomeoneCallbackuri");
string cancelUrl = getConfigValue("SomeoneCancelUrl");
init(clientId, clientSecret, callbackUri, cancelUrl);
}
/// <summary>
/// init app using parameters values
/// </summary>
public SomeoneIdClient(string clientId, string clientSecret, string callbackUri, string cancelUrl)
{
init(clientId, clientSecret, callbackUri, cancelUrl);
}
/// <summary>
/// redir to service auth page
/// </summary>
public void LogOn(string state = "")
{
string url = GetLogOnUri(state);
HttpContext.Current.Response.Redirect(url);
}
/// <summary>
/// retrieve the access token
/// </summary>
/// <returns></returns>
public string GetAccessToken(string code, string state)
{
int statusCode = 0;
try
{
if (state != this.State)
throw new SomeoneIdException(401, "Invalid state");
var accessTokenResult = new AccessTokenResult();
var serializer = new JavaScriptSerializer();
string reqUri = (TokenEndpoint
+ "?client_id={client_id}"
+ "&redirect_uri={redirect_uri}"
+ "&cancel_url={cancel_url}"
+ "&client_secret={client_secret}"
+ "&code={code}")
.Replace("{client_id}", this.ClientId)
.Replace("{redirect_uri}", this.CallbackUri)
.Replace("{cancel_url}", this.CancelUrl)
.Replace("{client_secret}", this.ClientSecret)
.Replace("{code}", code);
if (TokenEndpoint.StartsWith("https://"))
{
//20171031 problems with https on someone site
//try https://stackoverflow.com/questions/28286086/default-securityprotocol-in-net-4-5
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
}
HttpWebRequest wrLogon = (HttpWebRequest)WebRequest.Create(reqUri);
wrLogon.AllowAutoRedirect = false;
wrLogon.KeepAlive = true;
HttpWebResponse retreiveResponse = (HttpWebResponse)wrLogon.GetResponse();
statusCode = (int)retreiveResponse.StatusCode;
Stream objStream = retreiveResponse.GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string json = objReader.ReadToEnd();
retreiveResponse.Close();
accessTokenResult = serializer.Deserialize<AccessTokenResult>(json);
accessToken = accessTokenResult.access_token;
//SaveToken();
}
//catch (WebException wex)
//{
// HttpWebResponse wrs = (HttpWebResponse)wex.Response;
// throw new SomeoneIdException((int)wrs.StatusCode, wex.ToString());
//}
catch (Exception ex)
{
throw new SomeoneIdException(statusCode, ex.ToString());
}
return accessToken;
}
/// <summary>
/// Returns info about the logged user
/// according to logon request scope
/// </summary>
public MeResult GetMe(string accessToken)
{
int statusCode = 0;
var res = new MeResult();
var serializer = new JavaScriptSerializer();
try
{
string reqUri = (MeEndpoint
+ "?access_token={access_token}")
.Replace("{access_token}", accessToken);
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(reqUri);
wr.AllowAutoRedirect = false;
wr.KeepAlive = true;
HttpWebResponse retreiveResponse = (HttpWebResponse)wr.GetResponse();
statusCode = (int)retreiveResponse.StatusCode;
Stream objStream = retreiveResponse.GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string json = objReader.ReadToEnd();
retreiveResponse.Close();
res = serializer.Deserialize<MeResult>(json);
}
catch (WebException wex)
{
HttpWebResponse wrs = (HttpWebResponse)wex.Response;
throw new SomeoneIdException((int)wrs.StatusCode, wex.Message);
}
catch (Exception ex)
{
throw new SomeoneIdException(statusCode, ex.Message);
}
return res;
}
/// <summary>
///
/// </summary>
/// <param name="state">anti forgery state. new Guid if empty</param>
/// <returns></returns>
public string GetLogOnUri(string state = "")
{
if (string.IsNullOrEmpty(state))
state = Guid.NewGuid().ToString();
HttpContext.Current.Session.Remove(SessionStateKey);
HttpContext.Current.Session.Add(SessionStateKey, state);
string url = (LogonEndpoint
+ "?response_type=code"
+ "&client_id={clientId}"
+ "&scope={scope}"
+ "&state={state}"
+ "&redirect_uri={callbackUri}")
.Replace("{clientId}", clientId)
.Replace("{scope}", scope)
.Replace("{state}", state)
.Replace("{callbackUri}", callbackUri);
return url;
}
private string getConfigValue(string key, string defaultValue = "")
{
string res = defaultValue;
if (ConfigurationManager.AppSettings[key] != null)
res = ConfigurationManager.AppSettings[key];
return res;
}
private void init(string clientId, string clientSecret, string callbackUri, string cancelUrl)
{
if (string.IsNullOrEmpty(clientId)
|| string.IsNullOrEmpty(clientSecret)
|| string.IsNullOrEmpty(callbackUri))
{
throw new ArgumentException("Invalid someone.id app settings");
}
this.clientId = clientId;
this.clientSecret = clientSecret;
this.callbackUri = callbackUri;
if (!string.IsNullOrEmpty(cancelUrl))
this.cancelUrl = cancelUrl;
else
this.cancelUrl = callbackUri;
}
}
}