diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2010-08-01 07:37:21 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2010-08-01 08:58:43 -0700 |
commit | 222762e7b5d664f3e86683a55be6ea84710efc69 (patch) | |
tree | a37153096500bb86d4f8fbea4045f3cce93dfbc7 | |
parent | e7743dd039bab3788e682833368ca5a376b22354 (diff) | |
download | DotNetOpenAuth-222762e7b5d664f3e86683a55be6ea84710efc69.zip DotNetOpenAuth-222762e7b5d664f3e86683a55be6ea84710efc69.tar.gz DotNetOpenAuth-222762e7b5d664f3e86683a55be6ea84710efc69.tar.bz2 |
Some user-notification enhancements to the OAuth 2 samples.
-rw-r--r-- | samples/OAuthAuthorizationServer/Controllers/OAuthController.cs | 16 | ||||
-rw-r--r-- | samples/OAuthClient/SampleWcf2.aspx | 20 | ||||
-rw-r--r-- | samples/OAuthClient/SampleWcf2.aspx.cs | 27 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OAuth2/ClientBase.cs | 6 |
4 files changed, 52 insertions, 17 deletions
diff --git a/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs b/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs index 98fac04..0eb7c83 100644 --- a/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs +++ b/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs @@ -40,7 +40,18 @@ public ActionResult Token() { var request = this.authorizationServer.ReadAccessTokenRequest(); if (request != null) { - var response = this.authorizationServer.PrepareAccessTokenResponse(request, ResourceServerEncryptionPublicKey); + // Just for the sake of the sample, we use a short-lived token. This can be useful to mitigate the security risks + // of access tokens that are used over standard HTTP. + // But this is just the lifetime of the access token. The client can still renew it using their refresh token until + // the authorization itself expires. + TimeSpan accessTokenLifetime = TimeSpan.FromMinutes(2); + + // Also take into account the remaining life of the authorization and artificially shorten the access token's lifetime + // to account for that if necessary. + // TODO: code here + + // Prepare the refresh and access tokens. + var response = this.authorizationServer.PrepareAccessTokenResponse(request, ResourceServerEncryptionPublicKey, accessTokenLifetime); return this.authorizationServer.Channel.PrepareResponse(response).AsActionResult(); } @@ -80,6 +91,9 @@ IDirectedProtocolMessage response; if (isApproved) { + // The authorization we file in our database lasts until the user explicitly revokes it. + // You can cause the authorization to expire by setting the ExpirationDateUTC + // property in the below created ClientAuthorization. var client = MvcApplication.DataContext.Clients.First(c => c.ClientIdentifier == pendingRequest.ClientIdentifier); client.ClientAuthorizations.Add( new ClientAuthorization { diff --git a/samples/OAuthClient/SampleWcf2.aspx b/samples/OAuthClient/SampleWcf2.aspx index b19ae69..cfacaf1 100644 --- a/samples/OAuthClient/SampleWcf2.aspx +++ b/samples/OAuthClient/SampleWcf2.aspx @@ -1,13 +1,24 @@ -<%@ Page Title="OAuth 2.0 client (web server flow)" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" Inherits="OAuthClient.SampleWcf2" Codebehind="SampleWcf2.aspx.cs" %> +<%@ Page Title="OAuth 2.0 client (web server flow)" Language="C#" MasterPageFile="~/MasterPage.master" + AutoEventWireup="true" Inherits="OAuthClient.SampleWcf2" CodeBehind="SampleWcf2.aspx.cs" %> <asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> <fieldset title="Authorization"> + <p> + Check off the operations you'd like to authorization this client to make on + behalf of your account on the resource server.<br /> + Note that an authorization request may not actually result in you being prompted + to grant authorization if you've granted it previously. The authorization + server remembers what you've already approved. But even if you've + requested and received authorization for all three scopes above, you can request + access tokens for subsets of this set of scopes to limit what you can do below. + </p> <asp:CheckBoxList runat="server" ID="scopeList"> <asp:ListItem Value="http://tempuri.org/IDataApi/GetName">GetName</asp:ListItem> <asp:ListItem Value="http://tempuri.org/IDataApi/GetAge">GetAge</asp:ListItem> <asp:ListItem Value="http://tempuri.org/IDataApi/GetFavoriteSites">GetFavoriteSites</asp:ListItem> </asp:CheckBoxList> - <asp:Button ID="getAuthorizationButton" runat="server" Text="Request Authorization" OnClick="getAuthorizationButton_Click" /> + <asp:Button ID="getAuthorizationButton" runat="server" Text="Request Authorization" + OnClick="getAuthorizationButton_Click" /> <asp:Label ID="authorizationLabel" runat="server" /> </fieldset> <br /> @@ -17,7 +28,6 @@ <asp:Button ID="getAgeButton" runat="server" Text="Get Age" OnClick="getAgeButton_Click" /> <asp:Label ID="ageLabel" runat="server" /> <br /> - <asp:Button ID="getFavoriteSites" runat="server" Text="Get Favorite Sites" - onclick="getFavoriteSites_Click" /> + <asp:Button ID="getFavoriteSites" runat="server" Text="Get Favorite Sites" OnClick="getFavoriteSites_Click" /> <asp:Label ID="favoriteSitesLabel" runat="server" /> -</asp:Content>
\ No newline at end of file +</asp:Content> diff --git a/samples/OAuthClient/SampleWcf2.aspx.cs b/samples/OAuthClient/SampleWcf2.aspx.cs index 41f2896..7e0ea10 100644 --- a/samples/OAuthClient/SampleWcf2.aspx.cs +++ b/samples/OAuthClient/SampleWcf2.aspx.cs @@ -56,16 +56,22 @@ // 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 - } else { - 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; - } - authorizationLabel.Text = "Authorization received!"; - } } } + + 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; + } + authorizationLabel.Text = "Authorization received!"; + if (Authorization.AccessTokenExpirationUtc.HasValue) { + TimeSpan timeLeft = Authorization.AccessTokenExpirationUtc.Value - DateTime.UtcNow; + 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) { @@ -111,7 +117,10 @@ // Refresh the access token if it expires and if its lifetime is too short to be of use. if (Authorization.AccessTokenExpirationUtc.HasValue) { - Client.RefreshToken(Authorization, TimeSpan.FromMinutes(1)); + if (Client.RefreshToken(Authorization, TimeSpan.FromSeconds(30))) { + TimeSpan timeLeft = Authorization.AccessTokenExpirationUtc.Value - DateTime.UtcNow; + 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); diff --git a/src/DotNetOpenAuth/OAuth2/ClientBase.cs b/src/DotNetOpenAuth/OAuth2/ClientBase.cs index d9d9232..845d24c 100644 --- a/src/DotNetOpenAuth/OAuth2/ClientBase.cs +++ b/src/DotNetOpenAuth/OAuth2/ClientBase.cs @@ -94,7 +94,8 @@ namespace DotNetOpenAuth.OAuth2 { /// </summary> /// <param name="authorization">The authorization to update.</param> /// <param name="skipIfUsefulLifeExceeds">If given, the access token will <em>not</em> be refreshed if its remaining lifetime exceeds this value.</param> - public void RefreshToken(IAuthorizationState authorization, TimeSpan? skipIfUsefulLifeExceeds = null) { + /// <returns>A value indicating whether the access token was actually renewed; <c>true</c> if it was renewed, or <c>false</c> if it still had useful life remaining.</returns> + public bool RefreshToken(IAuthorizationState authorization, TimeSpan? skipIfUsefulLifeExceeds = null) { Contract.Requires<ArgumentNullException>(authorization != null, "authorization"); Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(authorization.RefreshToken)); @@ -103,7 +104,7 @@ namespace DotNetOpenAuth.OAuth2 { if (usefulLifeRemaining > skipIfUsefulLifeExceeds.Value) { // There is useful life remaining in the access token. Don't refresh. Logger.OAuth.DebugFormat("Skipping token refresh step because access token's remaining life is {0}, which exceeds {1}.", usefulLifeRemaining, skipIfUsefulLifeExceeds.Value); - return; + return false; } } @@ -129,6 +130,7 @@ namespace DotNetOpenAuth.OAuth2 { } authorization.SaveChanges(); + return true; } /// <summary> |