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
|
namespace OAuthClient {
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth2;
using SampleResourceServer;
public partial class SampleWcf2 : System.Web.UI.Page {
/// <summary>
/// The OAuth 2.0 client object to use to obtain authorization and authorize outgoing HTTP requests.
/// </summary>
private static readonly WebServerClient Client;
/// <summary>
/// The details about the sample OAuth-enabled WCF service that this sample client calls into.
/// </summary>
private static AuthorizationServerDescription authServerDescription = new AuthorizationServerDescription {
TokenEndpoint = new Uri("http://localhost:50172/OAuth/Token"),
AuthorizationEndpoint = new Uri("http://localhost:50172/OAuth/Authorize"),
};
/// <summary>
/// Initializes static members of the <see cref="SampleWcf2"/> class.
/// </summary>
static SampleWcf2() {
Client = new WebServerClient(authServerDescription, "sampleconsumer", "samplesecret");
}
/// <summary>
/// Gets or sets the authorization details for the logged in user.
/// </summary>
/// <value>The authorization details.</value>
/// <remarks>
/// Because this is a sample, we simply store the authorization information in memory with the user session.
/// A real web app should store at least the access and refresh tokens in this object in a database associated with the user.
/// </remarks>
private static IAuthorizationState Authorization {
get { return (AuthorizationState)HttpContext.Current.Session["Authorization"]; }
set { HttpContext.Current.Session["Authorization"] = value; }
}
protected void Page_Load(object sender, EventArgs e) {
this.RegisterAsyncTask(
new PageAsyncTask(
async ct => {
if (!IsPostBack) {
// Check to see if we're receiving a end user authorization response.
var authorization =
await Client.ProcessUserAuthorizationAsync(new HttpRequestWrapper(Request), Response.ClientDisconnectedToken);
if (authorization != null) {
// We are receiving an authorization response. Store it and associate it with this user.
Authorization = authorization;
Response.Redirect(Request.Path); // get rid of the /?code= parameter
}
}
if (Authorization != null) {
// Indicate to the user that we have already obtained authorization on some of these.
foreach (var li in this.scopeList.Items.OfType<ListItem>().Where(li => Authorization.Scope.Contains(li.Value))) {
li.Selected = true;
}
this.authorizationLabel.Text = "Authorization received!";
if (Authorization.AccessTokenExpirationUtc.HasValue) {
TimeSpan timeLeft = Authorization.AccessTokenExpirationUtc.Value - DateTime.UtcNow;
this.authorizationLabel.Text += string.Format(
CultureInfo.CurrentCulture, " (access token expires in {0} minutes)", Math.Round(timeLeft.TotalMinutes, 1));
}
}
this.getNameButton.Enabled = this.getAgeButton.Enabled = this.getFavoriteSites.Enabled = Authorization != null;
}));
}
protected void getAuthorizationButton_Click(object sender, EventArgs e) {
this.RegisterAsyncTask(
new PageAsyncTask(
async ct => {
string[] scopes =
(from item in this.scopeList.Items.OfType<ListItem>() where item.Selected select item.Value).ToArray();
var request =
await Client.PrepareRequestUserAuthorizationAsync(scopes, cancellationToken: Response.ClientDisconnectedToken);
await request.SendAsync();
this.Context.Response.End();
}));
}
protected void getNameButton_Click(object sender, EventArgs e) {
this.RegisterAsyncTask(
new PageAsyncTask(
async ct => {
try {
this.nameLabel.Text = await this.CallServiceAsync(client => client.GetName(), Response.ClientDisconnectedToken);
} catch (SecurityAccessDeniedException) {
this.nameLabel.Text = "Access denied!";
} catch (MessageSecurityException) {
this.nameLabel.Text = "Access denied!";
}
}));
}
protected void getAgeButton_Click(object sender, EventArgs e) {
this.RegisterAsyncTask(
new PageAsyncTask(
async ct => {
try {
int? age = await this.CallServiceAsync(client => client.GetAge(), Response.ClientDisconnectedToken);
this.ageLabel.Text = age.HasValue ? age.Value.ToString(CultureInfo.CurrentCulture) : "not available";
} catch (SecurityAccessDeniedException) {
this.ageLabel.Text = "Access denied!";
} catch (MessageSecurityException) {
this.ageLabel.Text = "Access denied!";
}
}));
}
protected void getFavoriteSites_Click(object sender, EventArgs e) {
this.RegisterAsyncTask(
new PageAsyncTask(
async ct => {
try {
string[] favoriteSites =
await this.CallServiceAsync(client => client.GetFavoriteSites(), Response.ClientDisconnectedToken);
this.favoriteSitesLabel.Text = string.Join(", ", favoriteSites);
} catch (SecurityAccessDeniedException) {
this.favoriteSitesLabel.Text = "Access denied!";
} catch (MessageSecurityException) {
this.favoriteSitesLabel.Text = "Access denied!";
}
}));
}
private async Task<T> CallServiceAsync<T>(Func<DataApiClient, T> predicate, CancellationToken cancellationToken) {
if (Authorization == null) {
throw new InvalidOperationException("No access token!");
}
var wcfClient = new DataApiClient();
// Refresh the access token if it expires and if its lifetime is too short to be of use.
if (Authorization.AccessTokenExpirationUtc.HasValue) {
if (await Client.RefreshAuthorizationAsync(Authorization, TimeSpan.FromSeconds(30))) {
TimeSpan timeLeft = Authorization.AccessTokenExpirationUtc.Value - DateTime.UtcNow;
this.authorizationLabel.Text += string.Format(CultureInfo.CurrentCulture, " - just renewed for {0} more minutes)", Math.Round(timeLeft.TotalMinutes, 1));
}
}
var httpRequest = (HttpWebRequest)WebRequest.Create(wcfClient.Endpoint.Address.Uri);
ClientBase.AuthorizeRequest(httpRequest, Authorization.AccessToken);
var httpDetails = new HttpRequestMessageProperty();
httpDetails.Headers[HttpRequestHeader.Authorization] = httpRequest.Headers[HttpRequestHeader.Authorization];
using (var scope = new OperationContextScope(wcfClient.InnerChannel)) {
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpDetails;
return predicate(wcfClient);
}
}
}
}
|