diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2012-02-02 19:55:29 -0800 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2012-02-02 19:55:29 -0800 |
commit | c1c763ef7ae943c7945c6d75459d02613329dd44 (patch) | |
tree | 3b39d9b629fc2435813fb666ad2e8bbb025714bf | |
parent | 492f4566b70142e5fc41a9c3fb4564c64c66ac5f (diff) | |
download | DotNetOpenAuth-c1c763ef7ae943c7945c6d75459d02613329dd44.zip DotNetOpenAuth-c1c763ef7ae943c7945c6d75459d02613329dd44.tar.gz DotNetOpenAuth-c1c763ef7ae943c7945c6d75459d02613329dd44.tar.bz2 |
Added OAuth 1.0 samples from v3.4 branch and fixed them up a bit so that
they work here.
Fixes #64
85 files changed, 5597 insertions, 0 deletions
diff --git a/samples/OAuthConsumer/Code/Logging.cs b/samples/OAuthConsumer/Code/Logging.cs new file mode 100644 index 0000000..510ea85 --- /dev/null +++ b/samples/OAuthConsumer/Code/Logging.cs @@ -0,0 +1,22 @@ +namespace OAuthConsumer { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Web; + + /// <summary> + /// Logging tools for this sample. + /// </summary> + public static class Logging { + /// <summary> + /// An application memory cache of recent log messages. + /// </summary> + public static StringBuilder LogMessages = new StringBuilder(); + + /// <summary> + /// The logger for this sample to use. + /// </summary> + public static log4net.ILog Logger = log4net.LogManager.GetLogger("DotNetOpenAuth.OAuthConsumer"); + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/Code/TracePageAppender.cs b/samples/OAuthConsumer/Code/TracePageAppender.cs new file mode 100644 index 0000000..5d3ba36 --- /dev/null +++ b/samples/OAuthConsumer/Code/TracePageAppender.cs @@ -0,0 +1,13 @@ +namespace OAuthConsumer { + using System; + using System.Collections.Generic; + using System.IO; + using System.Web; + + public class TracePageAppender : log4net.Appender.AppenderSkeleton { + protected override void Append(log4net.Core.LoggingEvent loggingEvent) { + StringWriter sw = new StringWriter(Logging.LogMessages); + Layout.Format(sw, loggingEvent); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/Default.aspx b/samples/OAuthConsumer/Default.aspx new file mode 100644 index 0000000..c952877 --- /dev/null +++ b/samples/OAuthConsumer/Default.aspx @@ -0,0 +1,14 @@ +<%@ Page Title="DotNetOpenAuth Consumer samples" Language="C#" MasterPageFile="~/MasterPage.master" + AutoEventWireup="true" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <p>OAuth allows this web site to access your private data with your authorization, but + without you having to give up your password. </p> + <p>Select a demo:</p> + <ul> + <li><a href="GoogleAddressBook.aspx">Download your Gmail address book</a></li> + <li><a href="Twitter.aspx">Get your Twitter updates</a></li> + <li><a href="SignInWithTwitter.aspx">Sign In With Twitter</a></li> + <li><a href="SampleWcf.aspx">Interop with Service Provider sample using WCF w/ OAuth</a></li> + </ul> +</asp:Content> diff --git a/samples/OAuthConsumer/Global.asax b/samples/OAuthConsumer/Global.asax new file mode 100644 index 0000000..06ffcd8 --- /dev/null +++ b/samples/OAuthConsumer/Global.asax @@ -0,0 +1 @@ +<%@ Application Language="C#" Inherits="OAuthConsumer.Global" CodeBehind="Global.asax.cs" %> diff --git a/samples/OAuthConsumer/Global.asax.cs b/samples/OAuthConsumer/Global.asax.cs new file mode 100644 index 0000000..10f297e --- /dev/null +++ b/samples/OAuthConsumer/Global.asax.cs @@ -0,0 +1,35 @@ +namespace OAuthConsumer { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + + public partial class Global : HttpApplication { + protected void Application_Start(object sender, EventArgs e) { + log4net.Config.XmlConfigurator.Configure(); + Logging.Logger.Info("Sample starting..."); + } + + protected void Application_End(object sender, EventArgs e) { + Logging.Logger.Info("Sample shutting down..."); + + // this would be automatic, but in partial trust scenarios it is not. + log4net.LogManager.Shutdown(); + } + + protected void Application_Error(object sender, EventArgs e) { + Logging.Logger.ErrorFormat("An unhandled exception was raised. Details follow: {0}", HttpContext.Current.Server.GetLastError()); + } + + protected void Session_Start(object sender, EventArgs e) { + // Code that runs when a new session is started + } + + protected void Session_End(object sender, EventArgs e) { + // Code that runs when a session ends. + // Note: The Session_End event is raised only when the sessionstate mode + // is set to InProc in the Web.config file. If session mode is set to StateServer + // or SQLServer, the event is not raised. + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/GoogleAddressBook.aspx b/samples/OAuthConsumer/GoogleAddressBook.aspx new file mode 100644 index 0000000..19fb505 --- /dev/null +++ b/samples/OAuthConsumer/GoogleAddressBook.aspx @@ -0,0 +1,26 @@ +<%@ Page Title="Gmail address book demo" Language="C#" MasterPageFile="~/MasterPage.master" + AutoEventWireup="true" Inherits="OAuthConsumer.GoogleAddressBook" Codebehind="GoogleAddressBook.aspx.cs" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0"> + <asp:View runat="server"> + <h2>Google setup</h2> + <p>A Google client app must be endorsed by a Google user. </p> + <ol> + <li><a target="_blank" href="https://www.google.com/accounts/ManageDomains">Visit Google + and create a client app</a>. </li> + <li>Modify your web.config file to include your consumer key and consumer secret. + </li> + </ol> + </asp:View> + <asp:View runat="server"> + <h2>Updates</h2> + <p>Ok, Google has authorized us to download your contacts. Click 'Get address book' + to download the first 5 contacts to this sample. Notice how we never asked you + for your Google username or password. </p> + <asp:Button ID="getAddressBookButton" runat="server" OnClick="getAddressBookButton_Click" + Text="Get address book" /> + <asp:PlaceHolder ID="resultsPlaceholder" runat="server" /> + </asp:View> + </asp:MultiView> +</asp:Content> diff --git a/samples/OAuthConsumer/GoogleAddressBook.aspx.cs b/samples/OAuthConsumer/GoogleAddressBook.aspx.cs new file mode 100644 index 0000000..ddca7e4 --- /dev/null +++ b/samples/OAuthConsumer/GoogleAddressBook.aspx.cs @@ -0,0 +1,75 @@ +namespace OAuthConsumer { + using System; + using System.Configuration; + using System.Linq; + using System.Text; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + using System.Xml.Linq; + using DotNetOpenAuth.ApplicationBlock; + using DotNetOpenAuth.OAuth; + + /// <summary> + /// A page to demonstrate downloading a Gmail address book using OAuth. + /// </summary> + public partial class GoogleAddressBook : System.Web.UI.Page { + private string AccessToken { + get { return (string)Session["GoogleAccessToken"]; } + set { Session["GoogleAccessToken"] = value; } + } + + private InMemoryTokenManager TokenManager { + get { + var tokenManager = (InMemoryTokenManager)Application["GoogleTokenManager"]; + if (tokenManager == null) { + string consumerKey = ConfigurationManager.AppSettings["googleConsumerKey"]; + string consumerSecret = ConfigurationManager.AppSettings["googleConsumerSecret"]; + if (!string.IsNullOrEmpty(consumerKey)) { + tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret); + Application["GoogleTokenManager"] = tokenManager; + } + } + + return tokenManager; + } + } + + protected void Page_Load(object sender, EventArgs e) { + if (this.TokenManager != null) { + this.MultiView1.ActiveViewIndex = 1; + + if (!IsPostBack) { + var google = new WebConsumer(GoogleConsumer.ServiceDescription, this.TokenManager); + + // Is Google calling back with authorization? + var accessTokenResponse = google.ProcessUserAuthorization(); + if (accessTokenResponse != null) { + this.AccessToken = accessTokenResponse.AccessToken; + } else if (this.AccessToken == null) { + // If we don't yet have access, immediately request it. + GoogleConsumer.RequestAuthorization(google, GoogleConsumer.Applications.Contacts); + } + } + } + } + + protected void getAddressBookButton_Click(object sender, EventArgs e) { + var google = new WebConsumer(GoogleConsumer.ServiceDescription, this.TokenManager); + + XDocument contactsDocument = GoogleConsumer.GetContacts(google, this.AccessToken, 5, 1); + var contacts = from entry in contactsDocument.Root.Elements(XName.Get("entry", "http://www.w3.org/2005/Atom")) + select new { Name = entry.Element(XName.Get("title", "http://www.w3.org/2005/Atom")).Value, Email = entry.Element(XName.Get("email", "http://schemas.google.com/g/2005")).Attribute("address").Value }; + StringBuilder tableBuilder = new StringBuilder(); + tableBuilder.Append("<table><tr><td>Name</td><td>Email</td></tr>"); + foreach (var contact in contacts) { + tableBuilder.AppendFormat( + "<tr><td>{0}</td><td>{1}</td></tr>", + HttpUtility.HtmlEncode(contact.Name), + HttpUtility.HtmlEncode(contact.Email)); + } + tableBuilder.Append("</table>"); + this.resultsPlaceholder.Controls.Add(new Literal { Text = tableBuilder.ToString() }); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/GoogleAddressBook.aspx.designer.cs b/samples/OAuthConsumer/GoogleAddressBook.aspx.designer.cs new file mode 100644 index 0000000..64558d5 --- /dev/null +++ b/samples/OAuthConsumer/GoogleAddressBook.aspx.designer.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthConsumer { + + + public partial class GoogleAddressBook { + + /// <summary> + /// MultiView1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.MultiView MultiView1; + + /// <summary> + /// getAddressBookButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button getAddressBookButton; + + /// <summary> + /// resultsPlaceholder control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.PlaceHolder resultsPlaceholder; + } +} diff --git a/samples/OAuthConsumer/GoogleApps2Legged.aspx b/samples/OAuthConsumer/GoogleApps2Legged.aspx new file mode 100644 index 0000000..cd9d9a1 --- /dev/null +++ b/samples/OAuthConsumer/GoogleApps2Legged.aspx @@ -0,0 +1,25 @@ +<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/MasterPage.master"CodeBehind="GoogleApps2Legged.aspx.cs" Inherits="OAuthConsumer.GoogleApps2Legged" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0"> + <asp:View runat="server"> + <h2>Google setup</h2> + <p>A Google client app must be endorsed by a Google user. </p> + <ol> + <li><a target="_blank" href="https://www.google.com/accounts/ManageDomains">Visit Google + and create a client app</a>. </li> + <li>Modify your web.config file to include your consumer key and consumer secret. + </li> + </ol> + </asp:View> + <asp:View runat="server"> + <h2>Updates</h2> + <p>Ok, Google has authorized us to download your contacts. Click 'Get address book' + to download the first 5 contacts to this sample. Notice how we never asked you + for your Google username or password. </p> + <asp:Button ID="getAddressBookButton" runat="server" OnClick="getAddressBookButton_Click" + Text="Get address book" /> + <asp:PlaceHolder ID="resultsPlaceholder" runat="server" /> + </asp:View> + </asp:MultiView> +</asp:Content> diff --git a/samples/OAuthConsumer/GoogleApps2Legged.aspx.cs b/samples/OAuthConsumer/GoogleApps2Legged.aspx.cs new file mode 100644 index 0000000..afb156b --- /dev/null +++ b/samples/OAuthConsumer/GoogleApps2Legged.aspx.cs @@ -0,0 +1,39 @@ +namespace OAuthConsumer { + using System; + using System.Collections.Generic; + using System.Configuration; + using System.Linq; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + using DotNetOpenAuth.ApplicationBlock; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.Messages; + + public partial class GoogleApps2Legged : System.Web.UI.Page { + private InMemoryTokenManager TokenManager { + get { + var tokenManager = (InMemoryTokenManager)Application["GoogleTokenManager"]; + if (tokenManager == null) { + string consumerKey = ConfigurationManager.AppSettings["googleConsumerKey"]; + string consumerSecret = ConfigurationManager.AppSettings["googleConsumerSecret"]; + if (!string.IsNullOrEmpty(consumerKey)) { + tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret); + Application["GoogleTokenManager"] = tokenManager; + } + } + + return tokenManager; + } + } + + protected void Page_Load(object sender, EventArgs e) { + var google = new WebConsumer(GoogleConsumer.ServiceDescription, this.TokenManager); + string accessToken = google.RequestNewClientAccount(); + ////string tokenSecret = google.TokenManager.GetTokenSecret(accessToken); + MessageReceivingEndpoint ep = null; // set up your authorized call here. + google.PrepareAuthorizedRequestAndSend(ep, accessToken); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/GoogleApps2Legged.aspx.designer.cs b/samples/OAuthConsumer/GoogleApps2Legged.aspx.designer.cs new file mode 100644 index 0000000..f952937 --- /dev/null +++ b/samples/OAuthConsumer/GoogleApps2Legged.aspx.designer.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthConsumer { + + + public partial class GoogleApps2Legged { + + /// <summary> + /// MultiView1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.MultiView MultiView1; + + /// <summary> + /// getAddressBookButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button getAddressBookButton; + + /// <summary> + /// resultsPlaceholder control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.PlaceHolder resultsPlaceholder; + } +} diff --git a/samples/OAuthConsumer/MasterPage.master b/samples/OAuthConsumer/MasterPage.master new file mode 100644 index 0000000..0044208 --- /dev/null +++ b/samples/OAuthConsumer/MasterPage.master @@ -0,0 +1,23 @@ +<%@ Master Language="C#" %> + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<script runat="server"> + +</script> + +<html xmlns="http://www.w3.org/1999/xhtml"> +<head runat="server"> + <title>DotNetOpenAuth Consumer sample</title> + <asp:ContentPlaceHolder ID="head" runat="server"/> +</head> +<body> + <form id="form1" runat="server"> + <h1>DotNetOpenAuth Consumer ASP.NET WebForms sample</h1> + <div> + <asp:ContentPlaceHolder ID="Body" runat="server"> + </asp:ContentPlaceHolder> + </div> + </form> +</body> +</html> diff --git a/samples/OAuthConsumer/OAuthConsumer.csproj b/samples/OAuthConsumer/OAuthConsumer.csproj new file mode 100644 index 0000000..0d65bec --- /dev/null +++ b/samples/OAuthConsumer/OAuthConsumer.csproj @@ -0,0 +1,213 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))\EnlistmentInfo.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))' != '' " /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion> + </ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}</ProjectGuid> + <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>OAuthConsumer</RootNamespace> + <AssemblyName>OAuthConsumer</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <TargetFrameworkProfile /> + <UseIISExpress>false</UseIISExpress> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\</OutputPath> + <DefineConstants>TRACE;DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup> + <DefineConstants>$(DefineConstants);SAMPLESONLY</DefineConstants> + </PropertyGroup> + <ItemGroup> + <Reference Include="log4net"> + <HintPath>..\..\lib\log4net.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Runtime.Serialization" /> + <Reference Include="System.ServiceModel" /> + <Reference Include="System.Web.Extensions" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Web" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Configuration" /> + <Reference Include="System.Web.Services" /> + <Reference Include="System.EnterpriseServices" /> + <Reference Include="System.Web.DynamicData" /> + <Reference Include="System.Web.Entity" /> + <Reference Include="System.Xml.Linq" /> + </ItemGroup> + <ItemGroup> + <Content Include="Default.aspx" /> + <Content Include="favicon.ico" /> + <Content Include="Global.asax" /> + <Content Include="GoogleAddressBook.aspx" /> + <Content Include="GoogleApps2Legged.aspx" /> + <Content Include="images\Sign-in-with-Twitter-darker.png" /> + <Content Include="SampleWcf.aspx" /> + <Content Include="Yammer.aspx" /> + <None Include="Service References\SampleServiceProvider\DataApi.disco" /> + <None Include="Service References\SampleServiceProvider\configuration91.svcinfo" /> + <None Include="Service References\SampleServiceProvider\configuration.svcinfo" /> + <None Include="Service References\SampleServiceProvider\Reference.svcmap"> + <Generator>WCF Proxy Generator</Generator> + <LastGenOutput>Reference.cs</LastGenOutput> + </None> + <Content Include="SignInWithTwitter.aspx" /> + <Content Include="TracePage.aspx" /> + <Content Include="Twitter.aspx" /> + <Content Include="Web.config" /> + <None Include="Service References\SampleServiceProvider\DataApi1.xsd"> + <SubType>Designer</SubType> + </None> + <None Include="Service References\SampleServiceProvider\DataApi2.xsd"> + <SubType>Designer</SubType> + </None> + </ItemGroup> + <ItemGroup> + <Compile Include="..\DotNetOpenAuth.ApplicationBlock\InMemoryTokenManager.cs"> + <Link>Code\InMemoryTokenManager.cs</Link> + </Compile> + <Compile Include="Global.asax.cs"> + <DependentUpon>Global.asax</DependentUpon> + </Compile> + <Compile Include="GoogleAddressBook.aspx.designer.cs"> + <DependentUpon>GoogleAddressBook.aspx</DependentUpon> + </Compile> + <Compile Include="GoogleApps2Legged.aspx.cs"> + <DependentUpon>GoogleApps2Legged.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="GoogleApps2Legged.aspx.designer.cs"> + <DependentUpon>GoogleApps2Legged.aspx</DependentUpon> + </Compile> + <Compile Include="SampleWcf.aspx.cs"> + <DependentUpon>SampleWcf.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="SampleWcf.aspx.designer.cs"> + <DependentUpon>SampleWcf.aspx</DependentUpon> + </Compile> + <Compile Include="Service References\SampleServiceProvider\Reference.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Reference.svcmap</DependentUpon> + </Compile> + <Compile Include="SignInWithTwitter.aspx.cs"> + <DependentUpon>SignInWithTwitter.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="SignInWithTwitter.aspx.designer.cs"> + <DependentUpon>SignInWithTwitter.aspx</DependentUpon> + </Compile> + <Compile Include="TracePage.aspx.cs"> + <DependentUpon>TracePage.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="TracePage.aspx.designer.cs"> + <DependentUpon>TracePage.aspx</DependentUpon> + </Compile> + <Compile Include="Twitter.aspx.cs"> + <DependentUpon>Twitter.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="Code\Logging.cs" /> + <Compile Include="Code\TracePageAppender.cs" /> + <Compile Include="GoogleAddressBook.aspx.cs"> + <DependentUpon>GoogleAddressBook.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Twitter.aspx.designer.cs"> + <DependentUpon>Twitter.aspx</DependentUpon> + </Compile> + <Compile Include="Yammer.aspx.cs"> + <DependentUpon>Yammer.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="Yammer.aspx.designer.cs"> + <DependentUpon>Yammer.aspx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <Folder Include="App_Data\" /> + </ItemGroup> + <ItemGroup> + <Content Include="MasterPage.master" /> + <None Include="Service References\SampleServiceProvider\DataApi.wsdl" /> + <None Include="Service References\SampleServiceProvider\DataApi.xsd"> + <SubType>Designer</SubType> + </None> + <None Include="Settings.StyleCop" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\src\DotNetOpenAuth.Core\DotNetOpenAuth.Core.csproj"> + <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> + <Name>DotNetOpenAuth.Core</Name> + </ProjectReference> + <ProjectReference Include="..\..\src\DotNetOpenAuth.OAuth.Consumer\DotNetOpenAuth.OAuth.Consumer.csproj"> + <Project>{B202E40D-4663-4A2B-ACDA-865F88FF7CAA}</Project> + <Name>DotNetOpenAuth.OAuth.Consumer</Name> + </ProjectReference> + <ProjectReference Include="..\..\src\DotNetOpenAuth.OAuth\DotNetOpenAuth.OAuth.csproj"> + <Project>{A288FCC8-6FCF-46DA-A45E-5F9281556361}</Project> + <Name>DotNetOpenAuth.OAuth</Name> + </ProjectReference> + <ProjectReference Include="..\..\src\DotNetOpenAuth.OpenId\DotNetOpenAuth.OpenId.csproj"> + <Project>{3896A32A-E876-4C23-B9B8-78E17D134CD3}</Project> + <Name>DotNetOpenAuth.OpenId</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.ApplicationBlock\DotNetOpenAuth.ApplicationBlock.csproj"> + <Project>{AA78D112-D889-414B-A7D4-467B34C7B663}</Project> + <Name>DotNetOpenAuth.ApplicationBlock</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <WCFMetadata Include="Service References\" /> + </ItemGroup> + <ItemGroup> + <WCFMetadataStorage Include="Service References\SampleServiceProvider\" /> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> + <ProjectExtensions> + <VisualStudio> + <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> + <WebProjectProperties> + <UseIIS>False</UseIIS> + <AutoAssignPort>False</AutoAssignPort> + <DevelopmentServerPort>59721</DevelopmentServerPort> + <DevelopmentServerVPath>/</DevelopmentServerVPath> + <IISUrl> + </IISUrl> + <NTLMAuthentication>False</NTLMAuthentication> + <UseCustomServer>False</UseCustomServer> + <CustomServerUrl> + </CustomServerUrl> + <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> + </WebProjectProperties> + </FlavorProperties> + </VisualStudio> + </ProjectExtensions> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " /> +</Project>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Properties/AssemblyInfo.cs b/samples/OAuthConsumer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..35efa1c --- /dev/null +++ b/samples/OAuthConsumer/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OAuthConsumer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OAuthConsumer")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("12549916-9ec2-4cf6-9fe3-82ea1f6ea665")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/OAuthConsumer/SampleWcf.aspx b/samples/OAuthConsumer/SampleWcf.aspx new file mode 100644 index 0000000..fb318ce --- /dev/null +++ b/samples/OAuthConsumer/SampleWcf.aspx @@ -0,0 +1,23 @@ +<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" Inherits="OAuthConsumer.SampleWcf" Codebehind="SampleWcf.aspx.cs" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <fieldset title="Authorization"> + <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="Get Authorization" OnClick="getAuthorizationButton_Click" /> + <asp:Label ID="authorizationLabel" runat="server" /> + </fieldset> + <br /> + <asp:Button ID="getNameButton" runat="server" Text="Get Name" OnClick="getNameButton_Click" /> + <asp:Label ID="nameLabel" runat="server" /> + <br /> + <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:Label ID="favoriteSitesLabel" runat="server" /> +</asp:Content> diff --git a/samples/OAuthConsumer/SampleWcf.aspx.cs b/samples/OAuthConsumer/SampleWcf.aspx.cs new file mode 100644 index 0000000..489e294 --- /dev/null +++ b/samples/OAuthConsumer/SampleWcf.aspx.cs @@ -0,0 +1,119 @@ +namespace OAuthConsumer { + 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.Web.UI.WebControls; + using DotNetOpenAuth; + using DotNetOpenAuth.ApplicationBlock; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using OAuthConsumer.SampleServiceProvider; + + /// <summary> + /// Sample consumer of our Service Provider sample's WCF service. + /// </summary> + public partial class SampleWcf : System.Web.UI.Page { + protected void Page_Load(object sender, EventArgs e) { + if (!IsPostBack) { + if (Session["WcfTokenManager"] != null) { + WebConsumer consumer = this.CreateConsumer(); + var accessTokenMessage = consumer.ProcessUserAuthorization(); + if (accessTokenMessage != null) { + Session["WcfAccessToken"] = accessTokenMessage.AccessToken; + this.authorizationLabel.Text = "Authorized! Access token: " + accessTokenMessage.AccessToken; + } + } + } + } + + protected void getAuthorizationButton_Click(object sender, EventArgs e) { + WebConsumer consumer = this.CreateConsumer(); + UriBuilder callback = new UriBuilder(Request.Url); + callback.Query = null; + string[] scopes = (from item in this.scopeList.Items.OfType<ListItem>() + where item.Selected + select item.Value).ToArray(); + string scope = string.Join("|", scopes); + var requestParams = new Dictionary<string, string> { + { "scope", scope }, + }; + var response = consumer.PrepareRequestUserAuthorization(callback.Uri, requestParams, null); + consumer.Channel.Send(response); + } + + protected void getNameButton_Click(object sender, EventArgs e) { + try { + this.nameLabel.Text = CallService(client => client.GetName()); + } catch (SecurityAccessDeniedException) { + this.nameLabel.Text = "Access denied!"; + } + } + + protected void getAgeButton_Click(object sender, EventArgs e) { + try { + int? age = CallService(client => client.GetAge()); + this.ageLabel.Text = age.HasValue ? age.Value.ToString(CultureInfo.CurrentCulture) : "not available"; + } catch (SecurityAccessDeniedException) { + this.ageLabel.Text = "Access denied!"; + } + } + + protected void getFavoriteSites_Click(object sender, EventArgs e) { + try { + string[] favoriteSites = CallService(client => client.GetFavoriteSites()); + this.favoriteSitesLabel.Text = string.Join(", ", favoriteSites); + } catch (SecurityAccessDeniedException) { + this.favoriteSitesLabel.Text = "Access denied!"; + } + } + + private T CallService<T>(Func<DataApiClient, T> predicate) { + DataApiClient client = new DataApiClient(); + var serviceEndpoint = new MessageReceivingEndpoint(client.Endpoint.Address.Uri, HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.PostRequest); + var accessToken = Session["WcfAccessToken"] as string; + if (accessToken == null) { + throw new InvalidOperationException("No access token!"); + } + WebConsumer consumer = this.CreateConsumer(); + WebRequest httpRequest = consumer.PrepareAuthorizedRequest(serviceEndpoint, accessToken); + + HttpRequestMessageProperty httpDetails = new HttpRequestMessageProperty(); + httpDetails.Headers[HttpRequestHeader.Authorization] = httpRequest.Headers[HttpRequestHeader.Authorization]; + using (OperationContextScope scope = new OperationContextScope(client.InnerChannel)) { + OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpDetails; + return predicate(client); + } + } + + private WebConsumer CreateConsumer() { + string consumerKey = "sampleconsumer"; + string consumerSecret = "samplesecret"; + var tokenManager = Session["WcfTokenManager"] as InMemoryTokenManager; + if (tokenManager == null) { + tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret); + Session["WcfTokenManager"] = tokenManager; + } + MessageReceivingEndpoint oauthEndpoint = new MessageReceivingEndpoint( + new Uri("http://localhost:65169/OAuth.ashx"), + HttpDeliveryMethods.PostRequest); + WebConsumer consumer = new WebConsumer( + new ServiceProviderDescription { + RequestTokenEndpoint = oauthEndpoint, + UserAuthorizationEndpoint = oauthEndpoint, + AccessTokenEndpoint = oauthEndpoint, + TamperProtectionElements = new DotNetOpenAuth.Messaging.ITamperProtectionChannelBindingElement[] { + new HmacSha1SigningBindingElement(), + }, + }, + tokenManager); + + return consumer; + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/SampleWcf.aspx.designer.cs b/samples/OAuthConsumer/SampleWcf.aspx.designer.cs new file mode 100644 index 0000000..c041338 --- /dev/null +++ b/samples/OAuthConsumer/SampleWcf.aspx.designer.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthConsumer { + + + public partial class SampleWcf { + + /// <summary> + /// scopeList control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.CheckBoxList scopeList; + + /// <summary> + /// getAuthorizationButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button getAuthorizationButton; + + /// <summary> + /// authorizationLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label authorizationLabel; + + /// <summary> + /// getNameButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button getNameButton; + + /// <summary> + /// nameLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label nameLabel; + + /// <summary> + /// getAgeButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button getAgeButton; + + /// <summary> + /// ageLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label ageLabel; + + /// <summary> + /// getFavoriteSites control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button getFavoriteSites; + + /// <summary> + /// favoriteSitesLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label favoriteSitesLabel; + } +} diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.disco b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.disco new file mode 100644 index 0000000..f8d5e5b --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.disco @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/"> + <contractRef ref="http://localhost:65169/DataApi.svc?wsdl" docRef="http://localhost:65169/DataApi.svc" xmlns="http://schemas.xmlsoap.org/disco/scl/" /> +</discovery>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.wsdl b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.wsdl new file mode 100644 index 0000000..702762a --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.wsdl @@ -0,0 +1,310 @@ +<?xml version="1.0" encoding="utf-8"?> +<wsdl:definitions xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:tns="http://tempuri.org/" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="DataApi" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> + <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_policy"> + <wsp:ExactlyOne> + <wsp:All> + <sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <wsp:Policy> + <sp:ProtectionToken> + <wsp:Policy> + <sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> + <wsp:Policy> + <sp:RequireDerivedKeys /> + <sp:BootstrapPolicy> + <wsp:Policy> + <sp:SignedParts> + <sp:Body /> + <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> + </sp:SignedParts> + <sp:EncryptedParts> + <sp:Body /> + </sp:EncryptedParts> + <sp:SymmetricBinding> + <wsp:Policy> + <sp:ProtectionToken> + <wsp:Policy> + <sp:SpnegoContextToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> + <wsp:Policy> + <sp:RequireDerivedKeys /> + </wsp:Policy> + </sp:SpnegoContextToken> + </wsp:Policy> + </sp:ProtectionToken> + <sp:AlgorithmSuite> + <wsp:Policy> + <sp:Basic256 /> + </wsp:Policy> + </sp:AlgorithmSuite> + <sp:Layout> + <wsp:Policy> + <sp:Strict /> + </wsp:Policy> + </sp:Layout> + <sp:IncludeTimestamp /> + <sp:EncryptSignature /> + <sp:OnlySignEntireHeadersAndBody /> + </wsp:Policy> + </sp:SymmetricBinding> + <sp:Wss11> + <wsp:Policy> + <sp:MustSupportRefKeyIdentifier /> + <sp:MustSupportRefIssuerSerial /> + <sp:MustSupportRefThumbprint /> + <sp:MustSupportRefEncryptedKey /> + </wsp:Policy> + </sp:Wss11> + <sp:Trust10> + <wsp:Policy> + <sp:MustSupportIssuedTokens /> + <sp:RequireClientEntropy /> + <sp:RequireServerEntropy /> + </wsp:Policy> + </sp:Trust10> + </wsp:Policy> + </sp:BootstrapPolicy> + </wsp:Policy> + </sp:SecureConversationToken> + </wsp:Policy> + </sp:ProtectionToken> + <sp:AlgorithmSuite> + <wsp:Policy> + <sp:Basic256 /> + </wsp:Policy> + </sp:AlgorithmSuite> + <sp:Layout> + <wsp:Policy> + <sp:Strict /> + </wsp:Policy> + </sp:Layout> + <sp:IncludeTimestamp /> + <sp:EncryptSignature /> + <sp:OnlySignEntireHeadersAndBody /> + </wsp:Policy> + </sp:SymmetricBinding> + <sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <wsp:Policy> + <sp:MustSupportRefKeyIdentifier /> + <sp:MustSupportRefIssuerSerial /> + <sp:MustSupportRefThumbprint /> + <sp:MustSupportRefEncryptedKey /> + </wsp:Policy> + </sp:Wss11> + <sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <wsp:Policy> + <sp:MustSupportIssuedTokens /> + <sp:RequireClientEntropy /> + <sp:RequireServerEntropy /> + </wsp:Policy> + </sp:Trust10> + <wsaw:UsingAddressing /> + </wsp:All> + </wsp:ExactlyOne> + </wsp:Policy> + <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetAge_Input_policy"> + <wsp:ExactlyOne> + <wsp:All> + <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> + </sp:SignedParts> + <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + </sp:EncryptedParts> + </wsp:All> + </wsp:ExactlyOne> + </wsp:Policy> + <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetAge_output_policy"> + <wsp:ExactlyOne> + <wsp:All> + <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> + </sp:SignedParts> + <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + </sp:EncryptedParts> + </wsp:All> + </wsp:ExactlyOne> + </wsp:Policy> + <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetName_Input_policy"> + <wsp:ExactlyOne> + <wsp:All> + <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> + </sp:SignedParts> + <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + </sp:EncryptedParts> + </wsp:All> + </wsp:ExactlyOne> + </wsp:Policy> + <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetName_output_policy"> + <wsp:ExactlyOne> + <wsp:All> + <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> + </sp:SignedParts> + <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + </sp:EncryptedParts> + </wsp:All> + </wsp:ExactlyOne> + </wsp:Policy> + <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetFavoriteSites_Input_policy"> + <wsp:ExactlyOne> + <wsp:All> + <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> + </sp:SignedParts> + <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + </sp:EncryptedParts> + </wsp:All> + </wsp:ExactlyOne> + </wsp:Policy> + <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetFavoriteSites_output_policy"> + <wsp:ExactlyOne> + <wsp:All> + <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" /> + <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" /> + </sp:SignedParts> + <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body /> + </sp:EncryptedParts> + </wsp:All> + </wsp:ExactlyOne> + </wsp:Policy> + <wsdl:types> + <xsd:schema targetNamespace="http://tempuri.org/Imports"> + <xsd:import schemaLocation="http://localhost:65169/DataApi.svc?xsd=xsd0" namespace="http://tempuri.org/" /> + <xsd:import schemaLocation="http://localhost:65169/DataApi.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" /> + <xsd:import schemaLocation="http://localhost:65169/DataApi.svc?xsd=xsd2" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" /> + </xsd:schema> + </wsdl:types> + <wsdl:message name="IDataApi_GetAge_InputMessage"> + <wsdl:part name="parameters" element="tns:GetAge" /> + </wsdl:message> + <wsdl:message name="IDataApi_GetAge_OutputMessage"> + <wsdl:part name="parameters" element="tns:GetAgeResponse" /> + </wsdl:message> + <wsdl:message name="IDataApi_GetName_InputMessage"> + <wsdl:part name="parameters" element="tns:GetName" /> + </wsdl:message> + <wsdl:message name="IDataApi_GetName_OutputMessage"> + <wsdl:part name="parameters" element="tns:GetNameResponse" /> + </wsdl:message> + <wsdl:message name="IDataApi_GetFavoriteSites_InputMessage"> + <wsdl:part name="parameters" element="tns:GetFavoriteSites" /> + </wsdl:message> + <wsdl:message name="IDataApi_GetFavoriteSites_OutputMessage"> + <wsdl:part name="parameters" element="tns:GetFavoriteSitesResponse" /> + </wsdl:message> + <wsdl:portType name="IDataApi"> + <wsdl:operation name="GetAge"> + <wsdl:input wsaw:Action="http://tempuri.org/IDataApi/GetAge" message="tns:IDataApi_GetAge_InputMessage" /> + <wsdl:output wsaw:Action="http://tempuri.org/IDataApi/GetAgeResponse" message="tns:IDataApi_GetAge_OutputMessage" /> + </wsdl:operation> + <wsdl:operation name="GetName"> + <wsdl:input wsaw:Action="http://tempuri.org/IDataApi/GetName" message="tns:IDataApi_GetName_InputMessage" /> + <wsdl:output wsaw:Action="http://tempuri.org/IDataApi/GetNameResponse" message="tns:IDataApi_GetName_OutputMessage" /> + </wsdl:operation> + <wsdl:operation name="GetFavoriteSites"> + <wsdl:input wsaw:Action="http://tempuri.org/IDataApi/GetFavoriteSites" message="tns:IDataApi_GetFavoriteSites_InputMessage" /> + <wsdl:output wsaw:Action="http://tempuri.org/IDataApi/GetFavoriteSitesResponse" message="tns:IDataApi_GetFavoriteSites_OutputMessage" /> + </wsdl:operation> + </wsdl:portType> + <wsdl:binding name="WSHttpBinding_IDataApi" type="tns:IDataApi"> + <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_policy" /> + <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" /> + <wsdl:operation name="GetAge"> + <soap12:operation soapAction="http://tempuri.org/IDataApi/GetAge" style="document" /> + <wsdl:input> + <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetAge_Input_policy" /> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetAge_output_policy" /> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="GetName"> + <soap12:operation soapAction="http://tempuri.org/IDataApi/GetName" style="document" /> + <wsdl:input> + <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetName_Input_policy" /> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetName_output_policy" /> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="GetFavoriteSites"> + <soap12:operation soapAction="http://tempuri.org/IDataApi/GetFavoriteSites" style="document" /> + <wsdl:input> + <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetFavoriteSites_Input_policy" /> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetFavoriteSites_output_policy" /> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + <wsdl:service name="DataApi"> + <wsdl:port name="WSHttpBinding_IDataApi" binding="tns:WSHttpBinding_IDataApi"> + <soap12:address location="http://localhost:65169/DataApi.svc" /> + <wsa10:EndpointReference> + <wsa10:Address>http://localhost:65169/DataApi.svc</wsa10:Address> + <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity"> + <Dns>localhost</Dns> + </Identity> + </wsa10:EndpointReference> + </wsdl:port> + </wsdl:service> +</wsdl:definitions>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.xsd b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.xsd new file mode 100644 index 0000000..3109534 --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi.xsd @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<xs:schema xmlns:tns="http://tempuri.org/" elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:import schemaLocation="http://localhost:65169/DataApi.svc?xsd=xsd2" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" /> + <xs:element name="GetAge"> + <xs:complexType> + <xs:sequence /> + </xs:complexType> + </xs:element> + <xs:element name="GetAgeResponse"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" name="GetAgeResult" nillable="true" type="xs:int" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="GetName"> + <xs:complexType> + <xs:sequence /> + </xs:complexType> + </xs:element> + <xs:element name="GetNameResponse"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" name="GetNameResult" nillable="true" type="xs:string" /> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="GetFavoriteSites"> + <xs:complexType> + <xs:sequence /> + </xs:complexType> + </xs:element> + <xs:element name="GetFavoriteSitesResponse"> + <xs:complexType> + <xs:sequence> + <xs:element xmlns:q1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" minOccurs="0" name="GetFavoriteSitesResult" nillable="true" type="q1:ArrayOfstring" /> + </xs:sequence> + </xs:complexType> + </xs:element> +</xs:schema>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi1.xsd b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi1.xsd new file mode 100644 index 0000000..d58e7f3 --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi1.xsd @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<xs:schema xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:element name="anyType" nillable="true" type="xs:anyType" /> + <xs:element name="anyURI" nillable="true" type="xs:anyURI" /> + <xs:element name="base64Binary" nillable="true" type="xs:base64Binary" /> + <xs:element name="boolean" nillable="true" type="xs:boolean" /> + <xs:element name="byte" nillable="true" type="xs:byte" /> + <xs:element name="dateTime" nillable="true" type="xs:dateTime" /> + <xs:element name="decimal" nillable="true" type="xs:decimal" /> + <xs:element name="double" nillable="true" type="xs:double" /> + <xs:element name="float" nillable="true" type="xs:float" /> + <xs:element name="int" nillable="true" type="xs:int" /> + <xs:element name="long" nillable="true" type="xs:long" /> + <xs:element name="QName" nillable="true" type="xs:QName" /> + <xs:element name="short" nillable="true" type="xs:short" /> + <xs:element name="string" nillable="true" type="xs:string" /> + <xs:element name="unsignedByte" nillable="true" type="xs:unsignedByte" /> + <xs:element name="unsignedInt" nillable="true" type="xs:unsignedInt" /> + <xs:element name="unsignedLong" nillable="true" type="xs:unsignedLong" /> + <xs:element name="unsignedShort" nillable="true" type="xs:unsignedShort" /> + <xs:element name="char" nillable="true" type="tns:char" /> + <xs:simpleType name="char"> + <xs:restriction base="xs:int" /> + </xs:simpleType> + <xs:element name="duration" nillable="true" type="tns:duration" /> + <xs:simpleType name="duration"> + <xs:restriction base="xs:duration"> + <xs:pattern value="\-?P(\d*D)?(T(\d*H)?(\d*M)?(\d*(\.\d*)?S)?)?" /> + <xs:minInclusive value="-P10675199DT2H48M5.4775808S" /> + <xs:maxInclusive value="P10675199DT2H48M5.4775807S" /> + </xs:restriction> + </xs:simpleType> + <xs:element name="guid" nillable="true" type="tns:guid" /> + <xs:simpleType name="guid"> + <xs:restriction base="xs:string"> + <xs:pattern value="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}" /> + </xs:restriction> + </xs:simpleType> + <xs:attribute name="FactoryType" type="xs:QName" /> + <xs:attribute name="Id" type="xs:ID" /> + <xs:attribute name="Ref" type="xs:IDREF" /> +</xs:schema>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi2.xsd b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi2.xsd new file mode 100644 index 0000000..04a74a4 --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/DataApi2.xsd @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<xs:schema xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:complexType name="ArrayOfstring"> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="xs:string" /> + </xs:sequence> + </xs:complexType> + <xs:element name="ArrayOfstring" nillable="true" type="tns:ArrayOfstring" /> +</xs:schema>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/Reference.cs b/samples/OAuthConsumer/Service References/SampleServiceProvider/Reference.cs new file mode 100644 index 0000000..a1d1eae --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/Reference.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthConsumer.SampleServiceProvider { + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] + [System.ServiceModel.ServiceContractAttribute(ConfigurationName="SampleServiceProvider.IDataApi")] + public interface IDataApi { + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IDataApi/GetAge", ReplyAction="http://tempuri.org/IDataApi/GetAgeResponse")] + System.Nullable<int> GetAge(); + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IDataApi/GetName", ReplyAction="http://tempuri.org/IDataApi/GetNameResponse")] + string GetName(); + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IDataApi/GetFavoriteSites", ReplyAction="http://tempuri.org/IDataApi/GetFavoriteSitesResponse")] + string[] GetFavoriteSites(); + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] + public interface IDataApiChannel : OAuthConsumer.SampleServiceProvider.IDataApi, System.ServiceModel.IClientChannel { + } + + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] + public partial class DataApiClient : System.ServiceModel.ClientBase<OAuthConsumer.SampleServiceProvider.IDataApi>, OAuthConsumer.SampleServiceProvider.IDataApi { + + public DataApiClient() { + } + + public DataApiClient(string endpointConfigurationName) : + base(endpointConfigurationName) { + } + + public DataApiClient(string endpointConfigurationName, string remoteAddress) : + base(endpointConfigurationName, remoteAddress) { + } + + public DataApiClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : + base(endpointConfigurationName, remoteAddress) { + } + + public DataApiClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : + base(binding, remoteAddress) { + } + + public System.Nullable<int> GetAge() { + return base.Channel.GetAge(); + } + + public string GetName() { + return base.Channel.GetName(); + } + + public string[] GetFavoriteSites() { + return base.Channel.GetFavoriteSites(); + } + } +} diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/Reference.svcmap b/samples/OAuthConsumer/Service References/SampleServiceProvider/Reference.svcmap new file mode 100644 index 0000000..4463f99 --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/Reference.svcmap @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<ReferenceGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="41652b7a-0e9d-40be-8e75-8ccd843850c4" xmlns="urn:schemas-microsoft-com:xml-wcfservicemap"> + <ClientOptions> + <GenerateAsynchronousMethods>false</GenerateAsynchronousMethods> + <EnableDataBinding>true</EnableDataBinding> + <ExcludedTypes /> + <ImportXmlTypes>false</ImportXmlTypes> + <GenerateInternalTypes>false</GenerateInternalTypes> + <GenerateMessageContracts>false</GenerateMessageContracts> + <NamespaceMappings /> + <CollectionMappings /> + <GenerateSerializableTypes>true</GenerateSerializableTypes> + <Serializer>Auto</Serializer> + <UseSerializerForFaults>true</UseSerializerForFaults> + <ReferenceAllAssemblies>true</ReferenceAllAssemblies> + <ReferencedAssemblies /> + <ReferencedDataContractTypes /> + <ServiceContractMappings /> + </ClientOptions> + <MetadataSources> + <MetadataSource Address="http://localhost:65169/DataApi.svc" Protocol="http" SourceId="1" /> + </MetadataSources> + <Metadata> + <MetadataFile FileName="DataApi.xsd" MetadataType="Schema" ID="82a34da8-d721-4c35-aaf9-fc5d08771cd2" SourceId="1" SourceUrl="http://localhost:65169/DataApi.svc?xsd=xsd0" /> + <MetadataFile FileName="DataApi.wsdl" MetadataType="Wsdl" ID="96350220-1df2-429e-8cb5-4fc33703bcc7" SourceId="1" SourceUrl="http://localhost:65169/DataApi.svc?wsdl" /> + <MetadataFile FileName="DataApi.disco" MetadataType="Disco" ID="c4f66dee-ac01-4476-afb0-34f7350c06ad" SourceId="1" SourceUrl="http://localhost:65169/DataApi.svc?disco" /> + <MetadataFile FileName="DataApi1.xsd" MetadataType="Schema" ID="7aaf262f-6342-421b-8f44-0e624be7a5fb" SourceId="1" SourceUrl="http://localhost:65169/DataApi.svc?xsd=xsd1" /> + <MetadataFile FileName="DataApi2.xsd" MetadataType="Schema" ID="67c1ea8d-12c4-4a0c-aa33-7226018cf16e" SourceId="1" SourceUrl="http://localhost:65169/DataApi.svc?xsd=xsd2" /> + </Metadata> + <Extensions> + <ExtensionFile FileName="configuration91.svcinfo" Name="configuration91.svcinfo" /> + <ExtensionFile FileName="configuration.svcinfo" Name="configuration.svcinfo" /> + </Extensions> +</ReferenceGroup>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/configuration.svcinfo b/samples/OAuthConsumer/Service References/SampleServiceProvider/configuration.svcinfo new file mode 100644 index 0000000..24b13a5 --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/configuration.svcinfo @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<configurationSnapshot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:schemas-microsoft-com:xml-wcfconfigurationsnapshot"> + <behaviors /> + <bindings> + <binding digest="System.ServiceModel.Configuration.WSHttpBindingElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089:<?xml version="1.0" encoding="utf-16"?><Data hostNameComparisonMode="StrongWildcard" messageEncoding="Text" name="WSHttpBinding_IDataApi1" textEncoding="utf-8" transactionFlow="false"><readerQuotas maxArrayLength="16384" maxBytesPerRead="4096" maxDepth="32" maxNameTableCharCount="16384" maxStringContentLength="8192" /><reliableSession enabled="false" inactivityTimeout="00:10:00" ordered="true" /><security mode="Message"><message algorithmSuite="Default" clientCredentialType="Windows" negotiateServiceCredential="true" /><transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /></security></Data>" bindingType="wsHttpBinding" name="WSHttpBinding_IDataApi1" /> + </bindings> + <endpoints> + <endpoint normalizedDigest="<?xml version="1.0" encoding="utf-16"?><Data address="http://localhost:65169/DataApi.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDataApi1" contract="SampleServiceProvider.IDataApi" name="WSHttpBinding_IDataApi1"><identity><dns value="localhost" /></identity></Data>" digest="<?xml version="1.0" encoding="utf-16"?><Data address="http://localhost:65169/DataApi.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDataApi1" contract="SampleServiceProvider.IDataApi" name="WSHttpBinding_IDataApi1"><identity><dns value="localhost" /></identity></Data>" contractName="SampleServiceProvider.IDataApi" name="WSHttpBinding_IDataApi1" /> + </endpoints> +</configurationSnapshot>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Service References/SampleServiceProvider/configuration91.svcinfo b/samples/OAuthConsumer/Service References/SampleServiceProvider/configuration91.svcinfo new file mode 100644 index 0000000..822d218 --- /dev/null +++ b/samples/OAuthConsumer/Service References/SampleServiceProvider/configuration91.svcinfo @@ -0,0 +1,216 @@ +<?xml version="1.0" encoding="utf-8"?> +<SavedWcfConfigurationInformation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="9.1" CheckSum="GUEgzgg89GpE4CgPbgPkvKCNLCE="> + <bindingConfigurations> + <bindingConfiguration bindingType="wsHttpBinding" name="WSHttpBinding_IDataApi1"> + <properties> + <property path="/name" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>WSHttpBinding_IDataApi1</serializedValue> + </property> + <property path="/closeTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>00:01:00</serializedValue> + </property> + <property path="/openTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>00:01:00</serializedValue> + </property> + <property path="/receiveTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>00:10:00</serializedValue> + </property> + <property path="/sendTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>00:01:00</serializedValue> + </property> + <property path="/bypassProxyOnLocal" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>False</serializedValue> + </property> + <property path="/transactionFlow" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>False</serializedValue> + </property> + <property path="/hostNameComparisonMode" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.HostNameComparisonMode, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>StrongWildcard</serializedValue> + </property> + <property path="/maxBufferPoolSize" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>524288</serializedValue> + </property> + <property path="/maxReceivedMessageSize" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>65536</serializedValue> + </property> + <property path="/messageEncoding" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.WSMessageEncoding, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>Text</serializedValue> + </property> + <property path="/proxyAddress" isComplexType="false" isExplicitlyDefined="false" clrType="System.Uri, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/readerQuotas" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.XmlDictionaryReaderQuotasElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.XmlDictionaryReaderQuotasElement</serializedValue> + </property> + <property path="/readerQuotas/maxDepth" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>32</serializedValue> + </property> + <property path="/readerQuotas/maxStringContentLength" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>8192</serializedValue> + </property> + <property path="/readerQuotas/maxArrayLength" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>16384</serializedValue> + </property> + <property path="/readerQuotas/maxBytesPerRead" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>4096</serializedValue> + </property> + <property path="/readerQuotas/maxNameTableCharCount" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>16384</serializedValue> + </property> + <property path="/reliableSession" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.StandardBindingOptionalReliableSessionElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.StandardBindingOptionalReliableSessionElement</serializedValue> + </property> + <property path="/reliableSession/ordered" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>True</serializedValue> + </property> + <property path="/reliableSession/inactivityTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>00:10:00</serializedValue> + </property> + <property path="/reliableSession/enabled" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>False</serializedValue> + </property> + <property path="/textEncoding" isComplexType="false" isExplicitlyDefined="true" clrType="System.Text.Encoding, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.Text.UTF8Encoding</serializedValue> + </property> + <property path="/useDefaultWebProxy" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>True</serializedValue> + </property> + <property path="/allowCookies" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>False</serializedValue> + </property> + <property path="/security" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.WSHttpSecurityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.WSHttpSecurityElement</serializedValue> + </property> + <property path="/security/mode" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.SecurityMode, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>Message</serializedValue> + </property> + <property path="/security/transport" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.WSHttpTransportSecurityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.WSHttpTransportSecurityElement</serializedValue> + </property> + <property path="/security/transport/clientCredentialType" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.HttpClientCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>Windows</serializedValue> + </property> + <property path="/security/transport/proxyCredentialType" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.HttpProxyCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>None</serializedValue> + </property> + <property path="/security/transport/extendedProtectionPolicy" isComplexType="true" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement</serializedValue> + </property> + <property path="/security/transport/extendedProtectionPolicy/policyEnforcement" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.PolicyEnforcement, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>Never</serializedValue> + </property> + <property path="/security/transport/extendedProtectionPolicy/protectionScenario" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.ProtectionScenario, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>TransportSelected</serializedValue> + </property> + <property path="/security/transport/extendedProtectionPolicy/customServiceNames" isComplexType="true" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.Configuration.ServiceNameElementCollection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>(Collection)</serializedValue> + </property> + <property path="/security/transport/realm" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/security/message" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.NonDualMessageSecurityOverHttpElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.NonDualMessageSecurityOverHttpElement</serializedValue> + </property> + <property path="/security/message/clientCredentialType" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.MessageCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>Windows</serializedValue> + </property> + <property path="/security/message/negotiateServiceCredential" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>True</serializedValue> + </property> + <property path="/security/message/algorithmSuite" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.Security.SecurityAlgorithmSuite, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>Default</serializedValue> + </property> + <property path="/security/message/establishSecurityContext" isComplexType="false" isExplicitlyDefined="false" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>True</serializedValue> + </property> + </properties> + </bindingConfiguration> + </bindingConfigurations> + <endpoints> + <endpoint name="WSHttpBinding_IDataApi1" contract="SampleServiceProvider.IDataApi" bindingType="wsHttpBinding" address="http://localhost:65169/DataApi.svc" bindingConfiguration="WSHttpBinding_IDataApi1"> + <properties> + <property path="/address" isComplexType="false" isExplicitlyDefined="true" clrType="System.Uri, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>http://localhost:65169/DataApi.svc</serializedValue> + </property> + <property path="/behaviorConfiguration" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/binding" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>wsHttpBinding</serializedValue> + </property> + <property path="/bindingConfiguration" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>WSHttpBinding_IDataApi1</serializedValue> + </property> + <property path="/contract" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>SampleServiceProvider.IDataApi</serializedValue> + </property> + <property path="/headers" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.AddressHeaderCollectionElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.AddressHeaderCollectionElement</serializedValue> + </property> + <property path="/headers/headers" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.Channels.AddressHeaderCollection, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue><Header /></serializedValue> + </property> + <property path="/identity" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.IdentityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.IdentityElement</serializedValue> + </property> + <property path="/identity/userPrincipalName" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.UserPrincipalNameElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.UserPrincipalNameElement</serializedValue> + </property> + <property path="/identity/userPrincipalName/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/identity/servicePrincipalName" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.ServicePrincipalNameElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.ServicePrincipalNameElement</serializedValue> + </property> + <property path="/identity/servicePrincipalName/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/identity/dns" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.DnsElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.DnsElement</serializedValue> + </property> + <property path="/identity/dns/value" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>localhost</serializedValue> + </property> + <property path="/identity/rsa" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.RsaElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.RsaElement</serializedValue> + </property> + <property path="/identity/rsa/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/identity/certificate" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.CertificateElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.CertificateElement</serializedValue> + </property> + <property path="/identity/certificate/encodedValue" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/identity/certificateReference" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.CertificateReferenceElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>System.ServiceModel.Configuration.CertificateReferenceElement</serializedValue> + </property> + <property path="/identity/certificateReference/storeName" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.StoreName, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>My</serializedValue> + </property> + <property path="/identity/certificateReference/storeLocation" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.StoreLocation, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>LocalMachine</serializedValue> + </property> + <property path="/identity/certificateReference/x509FindType" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.X509FindType, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>FindBySubjectDistinguishedName</serializedValue> + </property> + <property path="/identity/certificateReference/findValue" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/identity/certificateReference/isChainIncluded" isComplexType="false" isExplicitlyDefined="false" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>False</serializedValue> + </property> + <property path="/name" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue>WSHttpBinding_IDataApi1</serializedValue> + </property> + <property path="/kind" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + <property path="/endpointConfiguration" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <serializedValue /> + </property> + </properties> + </endpoint> + </endpoints> +</SavedWcfConfigurationInformation>
\ No newline at end of file diff --git a/samples/OAuthConsumer/Settings.StyleCop b/samples/OAuthConsumer/Settings.StyleCop new file mode 100644 index 0000000..7f55ce6 --- /dev/null +++ b/samples/OAuthConsumer/Settings.StyleCop @@ -0,0 +1 @@ +<StyleCopSettings Version="4.3" />
\ No newline at end of file diff --git a/samples/OAuthConsumer/SignInWithTwitter.aspx b/samples/OAuthConsumer/SignInWithTwitter.aspx new file mode 100644 index 0000000..86d29a4 --- /dev/null +++ b/samples/OAuthConsumer/SignInWithTwitter.aspx @@ -0,0 +1,38 @@ +<%@ Page Language="C#" AutoEventWireup="true" + Inherits="OAuthConsumer.SignInWithTwitter" Codebehind="SignInWithTwitter.aspx.cs" %> + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head runat="server"> + <title>Sign-in with Twitter</title> +</head> +<body> + <form id="form1" runat="server"> + <div> + <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0"> + <asp:View ID="View1" runat="server"> + <h2> + Twitter setup</h2> + <p> + A Twitter client app must be endorsed by a Twitter user. + </p> + <ol> + <li><a target="_blank" href="https://twitter.com/oauth_clients">Visit Twitter and create + a client app</a>. </li> + <li>Modify your web.config file to include your consumer key and consumer secret.</li> + </ol> + </asp:View> + <asp:View ID="View2" runat="server"> + <asp:ImageButton ImageUrl="~/images/Sign-in-with-Twitter-darker.png" runat="server" + AlternateText="Sign In With Twitter" ID="signInButton" OnClick="signInButton_Click" /> + <asp:CheckBox Text="force re-login" runat="server" ID="forceLoginCheckbox" /> + <br /> + <asp:Panel runat="server" ID="loggedInPanel" Visible="false"> + Now logged in as + <asp:Label Text="[name]" runat="server" ID="loggedInName" /> + </asp:Panel> + </asp:View> + </asp:MultiView> + </form> +</body> +</html> diff --git a/samples/OAuthConsumer/SignInWithTwitter.aspx.cs b/samples/OAuthConsumer/SignInWithTwitter.aspx.cs new file mode 100644 index 0000000..e104f3a --- /dev/null +++ b/samples/OAuthConsumer/SignInWithTwitter.aspx.cs @@ -0,0 +1,39 @@ +namespace OAuthConsumer { + using System; + using System.Collections.Generic; + using System.Configuration; + using System.Linq; + using System.Web; + using System.Web.Security; + using System.Web.UI; + using System.Web.UI.WebControls; + using System.Xml.Linq; + using System.Xml.XPath; + using DotNetOpenAuth.ApplicationBlock; + using DotNetOpenAuth.OAuth; + + public partial class SignInWithTwitter : System.Web.UI.Page { + protected void Page_Load(object sender, EventArgs e) { + if (TwitterConsumer.IsTwitterConsumerConfigured) { + this.MultiView1.ActiveViewIndex = 1; + + if (!IsPostBack) { + string screenName; + int userId; + if (TwitterConsumer.TryFinishSignInWithTwitter(out screenName, out userId)) { + this.loggedInPanel.Visible = true; + this.loggedInName.Text = screenName; + + // In a real app, the Twitter username would likely be used + // to log the user into the application. + ////FormsAuthentication.RedirectFromLoginPage(screenName, false); + } + } + } + } + + protected void signInButton_Click(object sender, ImageClickEventArgs e) { + TwitterConsumer.StartSignInWithTwitter(this.forceLoginCheckbox.Checked).Send(); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/SignInWithTwitter.aspx.designer.cs b/samples/OAuthConsumer/SignInWithTwitter.aspx.designer.cs new file mode 100644 index 0000000..962a1af --- /dev/null +++ b/samples/OAuthConsumer/SignInWithTwitter.aspx.designer.cs @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthConsumer { + + + public partial class SignInWithTwitter { + + /// <summary> + /// form1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + + /// <summary> + /// MultiView1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.MultiView MultiView1; + + /// <summary> + /// View1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.View View1; + + /// <summary> + /// View2 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.View View2; + + /// <summary> + /// signInButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.ImageButton signInButton; + + /// <summary> + /// forceLoginCheckbox control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.CheckBox forceLoginCheckbox; + + /// <summary> + /// loggedInPanel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Panel loggedInPanel; + + /// <summary> + /// loggedInName control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label loggedInName; + } +} diff --git a/samples/OAuthConsumer/TracePage.aspx b/samples/OAuthConsumer/TracePage.aspx new file mode 100644 index 0000000..d3539fb --- /dev/null +++ b/samples/OAuthConsumer/TracePage.aspx @@ -0,0 +1,18 @@ +<%@ Page Language="C#" AutoEventWireup="true" Inherits="OAuthConsumer.TracePage" Codebehind="TracePage.aspx.cs" %> + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head runat="server"> + <title></title> +</head> +<body> + <form id="form1" runat="server"> + <p align="right"> + <asp:Button runat="server" Text="Clear log" ID="clearLogButton" OnClick="clearLogButton_Click" /> + </p> + <pre> + <asp:PlaceHolder runat="server" ID="placeHolder1" /> + </pre> + </form> +</body> +</html> diff --git a/samples/OAuthConsumer/TracePage.aspx.cs b/samples/OAuthConsumer/TracePage.aspx.cs new file mode 100644 index 0000000..b9ca260 --- /dev/null +++ b/samples/OAuthConsumer/TracePage.aspx.cs @@ -0,0 +1,23 @@ +namespace OAuthConsumer { + using System; + using System.Collections.Generic; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + + /// <summary> + /// A page to display recent log messages. + /// </summary> + public partial class TracePage : System.Web.UI.Page { + protected void Page_Load(object sender, EventArgs e) { + this.placeHolder1.Controls.Add(new Label { Text = HttpUtility.HtmlEncode(Logging.LogMessages.ToString()) }); + } + + protected void clearLogButton_Click(object sender, EventArgs e) { + Logging.LogMessages.Length = 0; + + // clear the page immediately, and allow for F5 without a Postback warning. + Response.Redirect(Request.Url.AbsoluteUri); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/TracePage.aspx.designer.cs b/samples/OAuthConsumer/TracePage.aspx.designer.cs new file mode 100644 index 0000000..73184b5 --- /dev/null +++ b/samples/OAuthConsumer/TracePage.aspx.designer.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthConsumer { + + + public partial class TracePage { + + /// <summary> + /// form1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + + /// <summary> + /// clearLogButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button clearLogButton; + + /// <summary> + /// placeHolder1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.PlaceHolder placeHolder1; + } +} diff --git a/samples/OAuthConsumer/Twitter.aspx b/samples/OAuthConsumer/Twitter.aspx new file mode 100644 index 0000000..a24c7bd --- /dev/null +++ b/samples/OAuthConsumer/Twitter.aspx @@ -0,0 +1,35 @@ +<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" Inherits="OAuthConsumer.Twitter" Codebehind="Twitter.aspx.cs" %> + +<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"> +</asp:Content> +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0"> + <asp:View ID="View1" runat="server"> + <h2>Twitter setup</h2> + <p>A Twitter client app must be endorsed by a Twitter user. </p> + <ol> + <li><a target="_blank" href="https://twitter.com/oauth_clients">Visit Twitter and create + a client app</a>. </li> + <li>Modify your web.config file to include your consumer key and consumer secret.</li> + </ol> + </asp:View> + <asp:View runat="server"> + <h2>Updates</h2> + <p>Ok, Twitter has authorized us to download your feeds. Notice how we never asked + you for your Twitter username or password. </p> + <p> + Upload a new profile photo: + <asp:FileUpload ID="profilePhoto" runat="server" /> + <asp:Button ID="uploadProfilePhotoButton" runat="server" + onclick="uploadProfilePhotoButton_Click" Text="Upload photo" /> + <asp:Label ID="photoUploadedLabel" runat="server" EnableViewState="False" + Text="Done!" Visible="False"></asp:Label> + </p> + <p> + Click 'Get updates' to download updates to this sample. + </p> + <asp:Button ID="downloadUpdates" runat="server" Text="Get updates" OnClick="downloadUpdates_Click" /> + <asp:PlaceHolder runat="server" ID="resultsPlaceholder" /> + </asp:View> + </asp:MultiView> +</asp:Content> diff --git a/samples/OAuthConsumer/Twitter.aspx.cs b/samples/OAuthConsumer/Twitter.aspx.cs new file mode 100644 index 0000000..8288ed0 --- /dev/null +++ b/samples/OAuthConsumer/Twitter.aspx.cs @@ -0,0 +1,96 @@ +namespace OAuthConsumer { + using System; + using System.Collections.Generic; + using System.Configuration; + using System.Linq; + using System.Text; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + using System.Xml.Linq; + using System.Xml.XPath; + using DotNetOpenAuth.ApplicationBlock; + using DotNetOpenAuth.OAuth; + + public partial class Twitter : System.Web.UI.Page { + private string AccessToken { + get { return (string)Session["TwitterAccessToken"]; } + set { Session["TwitterAccessToken"] = value; } + } + + private InMemoryTokenManager TokenManager { + get { + var tokenManager = (InMemoryTokenManager)Application["TwitterTokenManager"]; + if (tokenManager == null) { + string consumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"]; + string consumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"]; + if (!string.IsNullOrEmpty(consumerKey)) { + tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret); + Application["TwitterTokenManager"] = tokenManager; + } + } + + return tokenManager; + } + } + + protected void Page_Load(object sender, EventArgs e) { + if (this.TokenManager != null) { + this.MultiView1.ActiveViewIndex = 1; + + if (!IsPostBack) { + var twitter = new WebConsumer(TwitterConsumer.ServiceDescription, this.TokenManager); + + // Is Twitter calling back with authorization? + var accessTokenResponse = twitter.ProcessUserAuthorization(); + if (accessTokenResponse != null) { + this.AccessToken = accessTokenResponse.AccessToken; + } else if (this.AccessToken == null) { + // If we don't yet have access, immediately request it. + twitter.Channel.Send(twitter.PrepareRequestUserAuthorization()); + } + } + } + } + + protected void downloadUpdates_Click(object sender, EventArgs e) { + var twitter = new WebConsumer(TwitterConsumer.ServiceDescription, this.TokenManager); + XPathDocument updates = new XPathDocument(TwitterConsumer.GetUpdates(twitter, this.AccessToken).CreateReader()); + XPathNavigator nav = updates.CreateNavigator(); + var parsedUpdates = from status in nav.Select("/statuses/status").OfType<XPathNavigator>() + where !status.SelectSingleNode("user/protected").ValueAsBoolean + select new { + User = status.SelectSingleNode("user/name").InnerXml, + Status = status.SelectSingleNode("text").InnerXml, + }; + + StringBuilder tableBuilder = new StringBuilder(); + tableBuilder.Append("<table><tr><td>Name</td><td>Update</td></tr>"); + + foreach (var update in parsedUpdates) { + tableBuilder.AppendFormat( + "<tr><td>{0}</td><td>{1}</td></tr>", + HttpUtility.HtmlEncode(update.User), + HttpUtility.HtmlEncode(update.Status)); + } + tableBuilder.Append("</table>"); + this.resultsPlaceholder.Controls.Add(new Literal { Text = tableBuilder.ToString() }); + } + + protected void uploadProfilePhotoButton_Click(object sender, EventArgs e) { + if (this.profilePhoto.PostedFile.ContentType == null) { + this.photoUploadedLabel.Visible = true; + this.photoUploadedLabel.Text = "Select a file first."; + return; + } + + var twitter = new WebConsumer(TwitterConsumer.ServiceDescription, this.TokenManager); + XDocument imageResult = TwitterConsumer.UpdateProfileImage( + twitter, + this.AccessToken, + this.profilePhoto.PostedFile.InputStream, + this.profilePhoto.PostedFile.ContentType); + this.photoUploadedLabel.Visible = true; + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/Twitter.aspx.designer.cs b/samples/OAuthConsumer/Twitter.aspx.designer.cs new file mode 100644 index 0000000..7c37271 --- /dev/null +++ b/samples/OAuthConsumer/Twitter.aspx.designer.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthConsumer { + + + public partial class Twitter { + + /// <summary> + /// MultiView1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.MultiView MultiView1; + + /// <summary> + /// View1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.View View1; + + /// <summary> + /// profilePhoto control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.FileUpload profilePhoto; + + /// <summary> + /// uploadProfilePhotoButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button uploadProfilePhotoButton; + + /// <summary> + /// photoUploadedLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label photoUploadedLabel; + + /// <summary> + /// downloadUpdates control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button downloadUpdates; + + /// <summary> + /// resultsPlaceholder control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.PlaceHolder resultsPlaceholder; + } +} diff --git a/samples/OAuthConsumer/Web.config b/samples/OAuthConsumer/Web.config new file mode 100644 index 0000000..cdff87a --- /dev/null +++ b/samples/OAuthConsumer/Web.config @@ -0,0 +1,206 @@ +<?xml version="1.0"?> +<configuration> + <configSections> + <section name="uri" type="System.Configuration.UriSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> + <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler" requirePermission="false" /> + <sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth.Core"> + <section name="oauth" type="DotNetOpenAuth.Configuration.OAuthElement, DotNetOpenAuth.OAuth" requirePermission="false" allowLocation="true" /> + <section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" /> + <section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" /> + </sectionGroup> + <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> + <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> + <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> + <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> + <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/> + <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> + <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> + <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> + </sectionGroup> + </sectionGroup> + </sectionGroup> + </configSections> + + <!-- The uri section is necessary to turn on .NET 3.5 support for IDN (international domain names), + which is necessary for OpenID urls with unicode characters in the domain/host name. + It is also required to put the Uri class into RFC 3986 escaping mode, which OpenID and OAuth require. --> + <uri> + <idn enabled="All"/> + <iriParsing enabled="true"/> + </uri> + + <system.net> + <defaultProxy enabled="true" /> + <settings> + <!-- This setting causes .NET to check certificate revocation lists (CRL) + before trusting HTTPS certificates. But this setting tends to not + be allowed in shared hosting environments. --> + <!--<servicePointManager checkCertificateRevocationList="true"/>--> + </settings> + </system.net> + + <!-- this is an optional configuration section where aspects of dotnetopenauth can be customized --> + <dotNetOpenAuth> + <!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. --> + <reporting enabled="true" /> + </dotNetOpenAuth> + + <appSettings> + <!-- Fill in your various consumer keys and secrets here to make the sample work. --> + <!-- You must get these values by signing up with each individual service provider. --> + <!-- Twitter sign-up: https://twitter.com/oauth_clients --> + <add key="twitterConsumerKey" value="" /> + <add key="twitterConsumerSecret" value="" /> + <!-- Google sign-up: https://www.google.com/accounts/ManageDomains --> + <add key="googleConsumerKey" value="anonymous"/> + <add key="googleConsumerSecret" value="anonymous"/> + <!-- Yammer sign-up: https://www.yammer.com/client_applications/new --> + <add key="yammerConsumerKey" value=""/> + <add key="yammerConsumerSecret" value=""/> + </appSettings> + <connectionStrings/> + + <system.web> + <!-- + Set compilation debug="true" to insert debugging + symbols into the compiled page. Because this + affects performance, set this value to true only + during development. + --> + <compilation debug="true"> + <assemblies> + <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> + </assemblies> + </compilation> + <!-- + The <authentication> section enables configuration + of the security authentication mode used by + ASP.NET to identify an incoming user. + --> + <authentication mode="Windows"/> + <!-- + The <customErrors> section enables configuration + of what to do if/when an unhandled error occurs + during the execution of a request. Specifically, + it enables developers to configure html error pages + to be displayed in place of a error stack trace. + + <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm"> + <error statusCode="403" redirect="NoAccess.htm" /> + <error statusCode="404" redirect="FileNotFound.htm" /> + </customErrors> + --> + <pages> + <controls> + <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + </controls> + </pages> + <httpHandlers> + <remove verb="*" path="*.asmx"/> + <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/> + </httpHandlers> + <httpModules> + <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + </httpModules> + </system.web> + <system.codedom> + <compilers> + <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <providerOption name="CompilerVersion" value="v3.5"/> + <providerOption name="WarnAsError" value="false"/> + </compiler> + <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <providerOption name="CompilerVersion" value="v3.5"/> + <providerOption name="OptionInfer" value="true"/> + <providerOption name="WarnAsError" value="false"/> + </compiler> + </compilers> + </system.codedom> + <!-- + The system.webServer section is required for running ASP.NET AJAX under Internet + Information Services 7.0. It is not necessary for previous version of IIS. + --> + <system.webServer> + <validation validateIntegratedModeConfiguration="false"/> + <modules> + <remove name="ScriptModule"/> + <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + </modules> + <handlers> + <remove name="WebServiceHandlerFactory-Integrated"/> + <remove name="ScriptHandlerFactory"/> + <remove name="ScriptHandlerFactoryAppServices"/> + <remove name="ScriptResource"/> + <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + </handlers> + </system.webServer> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/> + <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/> + <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/> + </dependentAssembly> + </assemblyBinding> + </runtime> + <log4net> + <appender name="TracePageAppender" type="OAuthConsumer.TracePageAppender, OAuthConsumer"> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date (GMT%date{%z}) [%thread] %-5level %logger - %message%newline" /> + </layout> + </appender> + <!-- Setup the root category, add the appenders and set the default level --> + <root> + <level value="INFO" /> + <!--<appender-ref ref="RollingFileAppender" />--> + <appender-ref ref="TracePageAppender" /> + </root> + <!-- Specify the level for some specific categories --> + <logger name="DotNetOpenAuth"> + <level value="ALL" /> + </logger> + </log4net> + <system.serviceModel> + <bindings> + <wsHttpBinding> + <binding name="WSHttpBinding_IDataApi" closeTimeout="00:01:00" + openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" + bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" + maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" + textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"> + <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" + maxBytesPerRead="4096" maxNameTableCharCount="16384" /> + <reliableSession ordered="true" inactivityTimeout="00:10:00" + enabled="false" /> + <security mode="Message"> + <transport clientCredentialType="Windows" proxyCredentialType="None" + realm=""/> + <message clientCredentialType="Windows" negotiateServiceCredential="true" + algorithmSuite="Default" establishSecurityContext="true" /> + </security> + </binding> + </wsHttpBinding> + </bindings> + <client> + <endpoint address="http://localhost:65169/DataApi.svc" + binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDataApi" + contract="SampleServiceProvider.IDataApi" name="WSHttpBinding_IDataApi"> + <identity> + <dns value="localhost" /> + </identity> + </endpoint> + </client> + </system.serviceModel> +</configuration> diff --git a/samples/OAuthConsumer/Yammer.aspx b/samples/OAuthConsumer/Yammer.aspx new file mode 100644 index 0000000..90b61b8 --- /dev/null +++ b/samples/OAuthConsumer/Yammer.aspx @@ -0,0 +1,48 @@ +<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/MasterPage.master" + CodeBehind="Yammer.aspx.cs" Inherits="OAuthConsumer.Yammer" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0"> + <asp:View ID="ClientRegistrationRequiredView" runat="server"> + <h2> + Yammer setup</h2> + <p> + A Yammer client app must be registered. + </p> + <ol> + <li><a target="_blank" href="https://www.yammer.com/client_applications/new">Visit Yammer + and register a client app</a>. </li> + <li>Modify your web.config file to include your consumer key and consumer secret. + </li> + </ol> + </asp:View> + <asp:View ID="BeginAuthorizationView" runat="server"> + <asp:Label Text="An error occurred in authorization. You may try again." EnableViewState="false" Visible="false" ForeColor="Red" ID="authorizationErrorLabel" runat="server" /> + <asp:Button Text="Obtain authorization now" runat="server" ID="obtainAuthorizationButton" + OnClick="obtainAuthorizationButton_Click" /> + </asp:View> + <asp:View ID="CompleteAuthorizationView" runat="server"> + After you have authorized Yammer to share your information, please enter the code + Yammer gives you here: + <asp:TextBox runat="server" ID="yammerUserCode" EnableViewState="false" /> + <asp:RequiredFieldValidator ErrorMessage="*" ControlToValidate="yammerUserCode" runat="server" /> + <asp:Button Text="Finish" runat="server" ID="finishAuthorizationButton" OnClick="finishAuthorizationButton_Click" /> + </asp:View> + <asp:View ID="AuthorizationCompleteView" runat="server"> + <h2> + Updates + </h2> + <p>The access token we have obtained is: + <asp:Label ID="accessTokenLabel" runat="server" /> + </p> + <p> + Ok, Yammer has authorized us to download your messages. Click 'Get messages' + to download the latest few messages to this sample. Notice how we never asked you + for your Yammer username or password. + </p> + <asp:Button ID="getYammerMessagesButton" runat="server" OnClick="getYammerMessages_Click" + Text="Get address book" /> + <asp:PlaceHolder ID="resultsPlaceholder" runat="server" /> + </asp:View> + </asp:MultiView> +</asp:Content> diff --git a/samples/OAuthConsumer/Yammer.aspx.cs b/samples/OAuthConsumer/Yammer.aspx.cs new file mode 100644 index 0000000..d8993fe --- /dev/null +++ b/samples/OAuthConsumer/Yammer.aspx.cs @@ -0,0 +1,76 @@ +namespace OAuthConsumer { + using System; + using System.Collections.Generic; + using System.Configuration; + using System.Linq; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + using DotNetOpenAuth.ApplicationBlock; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + + public partial class Yammer : System.Web.UI.Page { + private string RequestToken { + get { return (string)ViewState["YammerRequestToken"]; } + set { ViewState["YammerRequestToken"] = value; } + } + + private string AccessToken { + get { return (string)Session["YammerAccessToken"]; } + set { Session["YammerAccessToken"] = value; } + } + + private InMemoryTokenManager TokenManager { + get { + var tokenManager = (InMemoryTokenManager)Application["YammerTokenManager"]; + if (tokenManager == null) { + string consumerKey = ConfigurationManager.AppSettings["YammerConsumerKey"]; + string consumerSecret = ConfigurationManager.AppSettings["YammerConsumerSecret"]; + if (!string.IsNullOrEmpty(consumerKey)) { + tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret); + Application["YammerTokenManager"] = tokenManager; + } + } + + return tokenManager; + } + } + + protected void Page_Load(object sender, EventArgs e) { + if (this.TokenManager != null) { + this.MultiView1.SetActiveView(this.BeginAuthorizationView); + } + } + + protected void getYammerMessages_Click(object sender, EventArgs e) { + var yammer = new WebConsumer(YammerConsumer.ServiceDescription, this.TokenManager); + } + + protected void obtainAuthorizationButton_Click(object sender, EventArgs e) { + var yammer = YammerConsumer.CreateConsumer(this.TokenManager); + string requestToken; + Uri popupWindowLocation = YammerConsumer.PrepareRequestAuthorization(yammer, out requestToken); + this.RequestToken = requestToken; + string javascript = "window.open('" + popupWindowLocation.AbsoluteUri + "');"; + this.Page.ClientScript.RegisterStartupScript(GetType(), "YammerPopup", javascript, true); + this.MultiView1.SetActiveView(this.CompleteAuthorizationView); + } + + protected void finishAuthorizationButton_Click(object sender, EventArgs e) { + if (!Page.IsValid) { + return; + } + + var yammer = YammerConsumer.CreateConsumer(this.TokenManager); + var authorizationResponse = YammerConsumer.CompleteAuthorization(yammer, this.RequestToken, this.yammerUserCode.Text); + if (authorizationResponse != null) { + this.accessTokenLabel.Text = HttpUtility.HtmlEncode(authorizationResponse.AccessToken); + this.MultiView1.SetActiveView(this.AuthorizationCompleteView); + } else { + this.MultiView1.SetActiveView(this.BeginAuthorizationView); + this.authorizationErrorLabel.Visible = true; + } + } + } +}
\ No newline at end of file diff --git a/samples/OAuthConsumer/Yammer.aspx.designer.cs b/samples/OAuthConsumer/Yammer.aspx.designer.cs new file mode 100644 index 0000000..57f6db5 --- /dev/null +++ b/samples/OAuthConsumer/Yammer.aspx.designer.cs @@ -0,0 +1,123 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthConsumer { + + + public partial class Yammer { + + /// <summary> + /// MultiView1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.MultiView MultiView1; + + /// <summary> + /// ClientRegistrationRequiredView control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.View ClientRegistrationRequiredView; + + /// <summary> + /// BeginAuthorizationView control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.View BeginAuthorizationView; + + /// <summary> + /// authorizationErrorLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label authorizationErrorLabel; + + /// <summary> + /// obtainAuthorizationButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button obtainAuthorizationButton; + + /// <summary> + /// CompleteAuthorizationView control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.View CompleteAuthorizationView; + + /// <summary> + /// yammerUserCode control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.TextBox yammerUserCode; + + /// <summary> + /// finishAuthorizationButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button finishAuthorizationButton; + + /// <summary> + /// AuthorizationCompleteView control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.View AuthorizationCompleteView; + + /// <summary> + /// accessTokenLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label accessTokenLabel; + + /// <summary> + /// getYammerMessagesButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button getYammerMessagesButton; + + /// <summary> + /// resultsPlaceholder control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.PlaceHolder resultsPlaceholder; + } +} diff --git a/samples/OAuthConsumer/favicon.ico b/samples/OAuthConsumer/favicon.ico Binary files differnew file mode 100644 index 0000000..e227dbe --- /dev/null +++ b/samples/OAuthConsumer/favicon.ico diff --git a/samples/OAuthConsumer/images/Sign-in-with-Twitter-darker.png b/samples/OAuthConsumer/images/Sign-in-with-Twitter-darker.png Binary files differnew file mode 100644 index 0000000..746b6b9 --- /dev/null +++ b/samples/OAuthConsumer/images/Sign-in-with-Twitter-darker.png diff --git a/samples/OAuthServiceProvider/Code/Constants.cs b/samples/OAuthServiceProvider/Code/Constants.cs new file mode 100644 index 0000000..3e629f0 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/Constants.cs @@ -0,0 +1,32 @@ +namespace OAuthServiceProvider.Code { + using System; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + + /// <summary> + /// Service Provider definitions. + /// </summary> + public static class Constants { + public static Uri WebRootUrl { get; set; } + + public static ServiceProviderDescription SelfDescription { + get { + ServiceProviderDescription description = new ServiceProviderDescription { + AccessTokenEndpoint = new MessageReceivingEndpoint(new Uri(WebRootUrl, "/OAuth.ashx"), HttpDeliveryMethods.PostRequest), + RequestTokenEndpoint = new MessageReceivingEndpoint(new Uri(WebRootUrl, "/OAuth.ashx"), HttpDeliveryMethods.PostRequest), + UserAuthorizationEndpoint = new MessageReceivingEndpoint(new Uri(WebRootUrl, "/OAuth.ashx"), HttpDeliveryMethods.PostRequest), + TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { + new HmacSha1SigningBindingElement(), + }, + }; + + return description; + } + } + + public static ServiceProvider CreateServiceProvider() { + return new ServiceProvider(SelfDescription, Global.TokenManager, Global.NonceStore); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/CustomOAuthTypeProvider.cs b/samples/OAuthServiceProvider/Code/CustomOAuthTypeProvider.cs new file mode 100644 index 0000000..67da17c --- /dev/null +++ b/samples/OAuthServiceProvider/Code/CustomOAuthTypeProvider.cs @@ -0,0 +1,34 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// A custom class that will cause the OAuth library to use our custom message types + /// where we have them. + /// </summary> + public class CustomOAuthMessageFactory : OAuthServiceProviderMessageFactory { + /// <summary> + /// Initializes a new instance of the <see cref="CustomOAuthMessageFactory"/> class. + /// </summary> + /// <param name="tokenManager">The token manager instance to use.</param> + public CustomOAuthMessageFactory(IServiceProviderTokenManager tokenManager) + : base(tokenManager) { + } + + public override IDirectedProtocolMessage GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary<string, string> fields) { + var message = base.GetNewRequestMessage(recipient, fields); + + // inject our own type here to replace the standard one + if (message is UnauthorizedTokenRequest) { + message = new RequestScopedTokenMessage(recipient, message.Version); + } + + return message; + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/DataClasses.dbml b/samples/OAuthServiceProvider/Code/DataClasses.dbml new file mode 100644 index 0000000..5522ec8 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/DataClasses.dbml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?><Database Name="Database" EntityNamespace="OAuthServiceProvider.Code" Class="DataClassesDataContext" xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007"> + <Connection Mode="WebSettings" ConnectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True" SettingsObjectName="System.Configuration.ConfigurationManager.ConnectionStrings" SettingsPropertyName="DatabaseConnectionString" Provider="System.Data.SqlClient" /> + <Table Name="dbo.[User]" Member="Users"> + <Type Name="User"> + <Column Name="UserId" Type="System.Int32" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" /> + <Column Name="OpenIDClaimedIdentifier" Type="System.String" DbType="NVarChar(150) NOT NULL" CanBeNull="false" /> + <Column Name="OpenIDFriendlyIdentifier" Type="System.String" DbType="NVarChar(150)" CanBeNull="true" /> + <Column Name="FullName" Type="System.String" DbType="NVarChar(150)" CanBeNull="false" /> + <Column Name="Age" Type="System.Int32" DbType="int" CanBeNull="true" /> + <Association Name="User_FavoriteSite" Member="FavoriteSites" ThisKey="UserId" OtherKey="UserId" Type="FavoriteSite" /> + <Association Name="User_OAuthToken" Member="OAuthTokens" ThisKey="UserId" OtherKey="UserId" Type="OAuthToken" /> + </Type> + </Table> + <Table Name="dbo.FavoriteSite" Member="FavoriteSites"> + <Type Name="FavoriteSite"> + <Column Name="FavoriteSiteId" Type="System.Int32" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" /> + <Column Name="UserId" Type="System.Int32" DbType="Int NOT NULL" CanBeNull="false" /> + <Column Name="SiteUrl" Type="System.String" DbType="NVarChar(255) NOT NULL" CanBeNull="false" /> + <Association Name="User_FavoriteSite" Member="User" ThisKey="UserId" OtherKey="UserId" Type="User" IsForeignKey="true" DeleteRule="CASCADE" DeleteOnNull="true" /> + </Type> + </Table> + <Table Name="dbo.OAuthConsumer" Member="OAuthConsumers"> + <Type Name="OAuthConsumer"> + <Column Name="ConsumerId" Type="System.Int32" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" /> + <Column Name="ConsumerKey" Type="System.String" DbType="NVarChar(50) NOT NULL" CanBeNull="false" /> + <Column Name="ConsumerSecret" Type="System.String" DbType="NVarChar(50) NOT NULL" CanBeNull="false" /> + <Column Name="Callback" Type="System.String" CanBeNull="true" /> + <Column Name="VerificationCodeFormat" Type="DotNetOpenAuth.OAuth.VerificationCodeFormat" CanBeNull="false" /> + <Column Name="VerificationCodeLength" Type="System.Int32" CanBeNull="false" /> + <Association Name="OAuthConsumer_OAuthToken" Member="OAuthTokens" ThisKey="ConsumerId" OtherKey="ConsumerId" Type="OAuthToken" /> + </Type> + </Table> + <Table Name="dbo.OAuthToken" Member="OAuthTokens"> + <Type Name="OAuthToken"> + <Column Name="TokenId" Type="System.Int32" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" /> + <Column Name="Token" Type="System.String" DbType="NVarChar(50) NOT NULL" CanBeNull="false" /> + <Column Name="TokenSecret" Type="System.String" DbType="NVarChar(50) NOT NULL" CanBeNull="false" /> + <Column Name="State" Type="OAuthServiceProvider.Code.TokenAuthorizationState" DbType="INT NOT NULL" CanBeNull="false" /> + <Column Name="IssueDate" Type="System.DateTime" DbType="DateTime NOT NULL" CanBeNull="false" /> + <Column Name="ConsumerId" Type="System.Int32" DbType="Int NOT NULL" CanBeNull="false" /> + <Column Name="UserId" Type="System.Int32" DbType="Int" CanBeNull="true" /> + <Column Name="Scope" Type="System.String" DbType="nvarchar(MAX)" CanBeNull="false" /> + <Column Name="RequestTokenVerifier" Type="System.String" CanBeNull="true" /> + <Column Name="RequestTokenCallback" Type="System.String" CanBeNull="true" /> + <Column Name="ConsumerVersion" Type="System.String" CanBeNull="true" /> + <Association Name="OAuthConsumer_OAuthToken" Member="OAuthConsumer" ThisKey="ConsumerId" OtherKey="ConsumerId" Type="OAuthConsumer" IsForeignKey="true" DeleteRule="CASCADE" DeleteOnNull="true" /> + <Association Name="User_OAuthToken" Member="User" ThisKey="UserId" OtherKey="UserId" Type="User" IsForeignKey="true" DeleteRule="CASCADE" /> + </Type> + </Table> + <Table Name="" Member="Nonces"> + <Type Name="Nonce"> + <Column Member="Context" Type="System.String" IsPrimaryKey="true" CanBeNull="false" /> + <Column Member="Code" Type="System.String" IsPrimaryKey="true" CanBeNull="false" /> + <Column Member="Timestamp" Type="System.DateTime" IsPrimaryKey="true" CanBeNull="false" /> + </Type> + </Table> +</Database>
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/DataClasses.dbml.layout b/samples/OAuthServiceProvider/Code/DataClasses.dbml.layout new file mode 100644 index 0000000..9b80443 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/DataClasses.dbml.layout @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<ordesignerObjectsDiagram dslVersion="1.0.0.0" absoluteBounds="0, 0, 11, 8.5" name="DataClasses"> + <DataContextMoniker Name="/DataClassesDataContext" /> + <nestedChildShapes> + <classShape Id="696d2c69-040e-411d-9257-bb664b743834" absoluteBounds="0.5, 0.5, 2.125, 1.7708968098958331"> + <DataClassMoniker Name="/DataClassesDataContext/User" /> + <nestedChildShapes> + <elementListCompartment Id="cd90aeff-476c-44a9-897f-a986e4a8305b" absoluteBounds="0.515, 0.96, 2.0949999999999998, 1.2108968098958333" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" /> + </nestedChildShapes> + </classShape> + <classShape Id="8a79b099-7f87-4766-907a-db2c3e1b5716" absoluteBounds="3.5, 0.625, 2, 1.3862939453125005"> + <DataClassMoniker Name="/DataClassesDataContext/FavoriteSite" /> + <nestedChildShapes> + <elementListCompartment Id="eba736b9-f9ec-484b-8083-c77155a49e4e" absoluteBounds="3.515, 1.085, 1.9700000000000002, 0.8262939453125" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" /> + </nestedChildShapes> + </classShape> + <classShape Id="f909becb-85b1-4fe6-bb16-3feb3e4fe3ee" absoluteBounds="0.625, 3.25, 2, 1.9631982421874996"> + <DataClassMoniker Name="/DataClassesDataContext/OAuthConsumer" /> + <nestedChildShapes> + <elementListCompartment Id="464308c4-d112-4448-b0c9-d9b82fb0ca4e" absoluteBounds="0.64, 3.71, 1.9700000000000002, 1.4031982421875" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" /> + </nestedChildShapes> + </classShape> + <classShape Id="895ebbc8-8352-4c04-9e53-b8e6c8302d36" absoluteBounds="3.5, 3.125, 2, 2.9247054036458326"> + <DataClassMoniker Name="/DataClassesDataContext/OAuthToken" /> + <nestedChildShapes> + <elementListCompartment Id="403126d0-3d2a-4af4-b0b8-c489a830bbd4" absoluteBounds="3.515, 3.585, 1.9700000000000002, 2.364705403645833" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" /> + </nestedChildShapes> + </classShape> + <associationConnector edgePoints="[(2.625 : 1.31814697265625); (3.5 : 1.31814697265625)]" fixedFrom="NotFixed" fixedTo="NotFixed"> + <AssociationMoniker Name="/DataClassesDataContext/User/User_FavoriteSite" /> + <nodes> + <classShapeMoniker Id="696d2c69-040e-411d-9257-bb664b743834" /> + <classShapeMoniker Id="8a79b099-7f87-4766-907a-db2c3e1b5716" /> + </nodes> + </associationConnector> + <associationConnector edgePoints="[(2.625 : 4.23159912109375); (3.5 : 4.23159912109375)]" fixedFrom="NotFixed" fixedTo="NotFixed"> + <AssociationMoniker Name="/DataClassesDataContext/OAuthConsumer/OAuthConsumer_OAuthToken" /> + <nodes> + <classShapeMoniker Id="f909becb-85b1-4fe6-bb16-3feb3e4fe3ee" /> + <classShapeMoniker Id="895ebbc8-8352-4c04-9e53-b8e6c8302d36" /> + </nodes> + </associationConnector> + <associationConnector edgePoints="[(0.53125 : 2.27089680989583); (0.53125 : 5.66270182291667); (3.5 : 5.66270182291667)]" fixedFrom="NotFixed" fixedTo="NotFixed"> + <AssociationMoniker Name="/DataClassesDataContext/User/User_OAuthToken" /> + <nodes> + <classShapeMoniker Id="696d2c69-040e-411d-9257-bb664b743834" /> + <classShapeMoniker Id="895ebbc8-8352-4c04-9e53-b8e6c8302d36" /> + </nodes> + </associationConnector> + <classShape Id="a63562a7-acf2-4ed9-9686-52a1ad85633e" absoluteBounds="1.375, 6.375, 2, 1.3862939453124996"> + <DataClassMoniker Name="/DataClassesDataContext/Nonce" /> + <nestedChildShapes> + <elementListCompartment Id="9e4514ef-bc7b-4179-88e6-05363bf6ee5e" absoluteBounds="1.39, 6.835, 1.9700000000000002, 0.8262939453125" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" /> + </nestedChildShapes> + </classShape> + </nestedChildShapes> +</ordesignerObjectsDiagram>
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/DataClasses.designer.cs b/samples/OAuthServiceProvider/Code/DataClasses.designer.cs new file mode 100644 index 0000000..3c0d936 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/DataClasses.designer.cs @@ -0,0 +1,1190 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthServiceProvider.Code +{ + using System.Data.Linq; + using System.Data.Linq.Mapping; + using System.Data; + using System.Collections.Generic; + using System.Reflection; + using System.Linq; + using System.Linq.Expressions; + using System.ComponentModel; + using System; + + + [global::System.Data.Linq.Mapping.DatabaseAttribute(Name="Database")] + public partial class DataClassesDataContext : System.Data.Linq.DataContext + { + + private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource(); + + #region Extensibility Method Definitions + partial void OnCreated(); + partial void InsertUser(User instance); + partial void UpdateUser(User instance); + partial void DeleteUser(User instance); + partial void InsertFavoriteSite(FavoriteSite instance); + partial void UpdateFavoriteSite(FavoriteSite instance); + partial void DeleteFavoriteSite(FavoriteSite instance); + partial void InsertOAuthConsumer(OAuthConsumer instance); + partial void UpdateOAuthConsumer(OAuthConsumer instance); + partial void DeleteOAuthConsumer(OAuthConsumer instance); + partial void InsertOAuthToken(OAuthToken instance); + partial void UpdateOAuthToken(OAuthToken instance); + partial void DeleteOAuthToken(OAuthToken instance); + partial void InsertNonce(Nonce instance); + partial void UpdateNonce(Nonce instance); + partial void DeleteNonce(Nonce instance); + #endregion + + public DataClassesDataContext() : + base(global::System.Configuration.ConfigurationManager.ConnectionStrings["DatabaseConnectionString"].ConnectionString, mappingSource) + { + OnCreated(); + } + + public DataClassesDataContext(string connection) : + base(connection, mappingSource) + { + OnCreated(); + } + + public DataClassesDataContext(System.Data.IDbConnection connection) : + base(connection, mappingSource) + { + OnCreated(); + } + + public DataClassesDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) : + base(connection, mappingSource) + { + OnCreated(); + } + + public DataClassesDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) : + base(connection, mappingSource) + { + OnCreated(); + } + + public System.Data.Linq.Table<User> Users + { + get + { + return this.GetTable<User>(); + } + } + + public System.Data.Linq.Table<FavoriteSite> FavoriteSites + { + get + { + return this.GetTable<FavoriteSite>(); + } + } + + public System.Data.Linq.Table<OAuthConsumer> OAuthConsumers + { + get + { + return this.GetTable<OAuthConsumer>(); + } + } + + public System.Data.Linq.Table<OAuthToken> OAuthTokens + { + get + { + return this.GetTable<OAuthToken>(); + } + } + + public System.Data.Linq.Table<Nonce> Nonces + { + get + { + return this.GetTable<Nonce>(); + } + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.[User]")] + public partial class User : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private int _UserId; + + private string _OpenIDClaimedIdentifier; + + private string _OpenIDFriendlyIdentifier; + + private string _FullName; + + private System.Nullable<int> _Age; + + private EntitySet<FavoriteSite> _FavoriteSites; + + private EntitySet<OAuthToken> _OAuthTokens; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnUserIdChanging(int value); + partial void OnUserIdChanged(); + partial void OnOpenIDClaimedIdentifierChanging(string value); + partial void OnOpenIDClaimedIdentifierChanged(); + partial void OnOpenIDFriendlyIdentifierChanging(string value); + partial void OnOpenIDFriendlyIdentifierChanged(); + partial void OnFullNameChanging(string value); + partial void OnFullNameChanged(); + partial void OnAgeChanging(System.Nullable<int> value); + partial void OnAgeChanged(); + #endregion + + public User() + { + this._FavoriteSites = new EntitySet<FavoriteSite>(new Action<FavoriteSite>(this.attach_FavoriteSites), new Action<FavoriteSite>(this.detach_FavoriteSites)); + this._OAuthTokens = new EntitySet<OAuthToken>(new Action<OAuthToken>(this.attach_OAuthTokens), new Action<OAuthToken>(this.detach_OAuthTokens)); + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_UserId", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] + public int UserId + { + get + { + return this._UserId; + } + set + { + if ((this._UserId != value)) + { + this.OnUserIdChanging(value); + this.SendPropertyChanging(); + this._UserId = value; + this.SendPropertyChanged("UserId"); + this.OnUserIdChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_OpenIDClaimedIdentifier", DbType="NVarChar(150) NOT NULL", CanBeNull=false)] + public string OpenIDClaimedIdentifier + { + get + { + return this._OpenIDClaimedIdentifier; + } + set + { + if ((this._OpenIDClaimedIdentifier != value)) + { + this.OnOpenIDClaimedIdentifierChanging(value); + this.SendPropertyChanging(); + this._OpenIDClaimedIdentifier = value; + this.SendPropertyChanged("OpenIDClaimedIdentifier"); + this.OnOpenIDClaimedIdentifierChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_OpenIDFriendlyIdentifier", DbType="NVarChar(150)")] + public string OpenIDFriendlyIdentifier + { + get + { + return this._OpenIDFriendlyIdentifier; + } + set + { + if ((this._OpenIDFriendlyIdentifier != value)) + { + this.OnOpenIDFriendlyIdentifierChanging(value); + this.SendPropertyChanging(); + this._OpenIDFriendlyIdentifier = value; + this.SendPropertyChanged("OpenIDFriendlyIdentifier"); + this.OnOpenIDFriendlyIdentifierChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_FullName", DbType="NVarChar(150)", CanBeNull=false)] + public string FullName + { + get + { + return this._FullName; + } + set + { + if ((this._FullName != value)) + { + this.OnFullNameChanging(value); + this.SendPropertyChanging(); + this._FullName = value; + this.SendPropertyChanged("FullName"); + this.OnFullNameChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Age", DbType="int")] + public System.Nullable<int> Age + { + get + { + return this._Age; + } + set + { + if ((this._Age != value)) + { + this.OnAgeChanging(value); + this.SendPropertyChanging(); + this._Age = value; + this.SendPropertyChanged("Age"); + this.OnAgeChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="User_FavoriteSite", Storage="_FavoriteSites", ThisKey="UserId", OtherKey="UserId")] + public EntitySet<FavoriteSite> FavoriteSites + { + get + { + return this._FavoriteSites; + } + set + { + this._FavoriteSites.Assign(value); + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="User_OAuthToken", Storage="_OAuthTokens", ThisKey="UserId", OtherKey="UserId")] + public EntitySet<OAuthToken> OAuthTokens + { + get + { + return this._OAuthTokens; + } + set + { + this._OAuthTokens.Assign(value); + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void attach_FavoriteSites(FavoriteSite entity) + { + this.SendPropertyChanging(); + entity.User = this; + } + + private void detach_FavoriteSites(FavoriteSite entity) + { + this.SendPropertyChanging(); + entity.User = null; + } + + private void attach_OAuthTokens(OAuthToken entity) + { + this.SendPropertyChanging(); + entity.User = this; + } + + private void detach_OAuthTokens(OAuthToken entity) + { + this.SendPropertyChanging(); + entity.User = null; + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.FavoriteSite")] + public partial class FavoriteSite : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private int _FavoriteSiteId; + + private int _UserId; + + private string _SiteUrl; + + private EntityRef<User> _User; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnFavoriteSiteIdChanging(int value); + partial void OnFavoriteSiteIdChanged(); + partial void OnUserIdChanging(int value); + partial void OnUserIdChanged(); + partial void OnSiteUrlChanging(string value); + partial void OnSiteUrlChanged(); + #endregion + + public FavoriteSite() + { + this._User = default(EntityRef<User>); + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_FavoriteSiteId", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] + public int FavoriteSiteId + { + get + { + return this._FavoriteSiteId; + } + set + { + if ((this._FavoriteSiteId != value)) + { + this.OnFavoriteSiteIdChanging(value); + this.SendPropertyChanging(); + this._FavoriteSiteId = value; + this.SendPropertyChanged("FavoriteSiteId"); + this.OnFavoriteSiteIdChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_UserId", DbType="Int NOT NULL")] + public int UserId + { + get + { + return this._UserId; + } + set + { + if ((this._UserId != value)) + { + if (this._User.HasLoadedOrAssignedValue) + { + throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException(); + } + this.OnUserIdChanging(value); + this.SendPropertyChanging(); + this._UserId = value; + this.SendPropertyChanged("UserId"); + this.OnUserIdChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_SiteUrl", DbType="NVarChar(255) NOT NULL", CanBeNull=false)] + public string SiteUrl + { + get + { + return this._SiteUrl; + } + set + { + if ((this._SiteUrl != value)) + { + this.OnSiteUrlChanging(value); + this.SendPropertyChanging(); + this._SiteUrl = value; + this.SendPropertyChanged("SiteUrl"); + this.OnSiteUrlChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="User_FavoriteSite", Storage="_User", ThisKey="UserId", OtherKey="UserId", IsForeignKey=true, DeleteOnNull=true, DeleteRule="CASCADE")] + public User User + { + get + { + return this._User.Entity; + } + set + { + User previousValue = this._User.Entity; + if (((previousValue != value) + || (this._User.HasLoadedOrAssignedValue == false))) + { + this.SendPropertyChanging(); + if ((previousValue != null)) + { + this._User.Entity = null; + previousValue.FavoriteSites.Remove(this); + } + this._User.Entity = value; + if ((value != null)) + { + value.FavoriteSites.Add(this); + this._UserId = value.UserId; + } + else + { + this._UserId = default(int); + } + this.SendPropertyChanged("User"); + } + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.OAuthConsumer")] + public partial class OAuthConsumer : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private int _ConsumerId; + + private string _ConsumerKey; + + private string _ConsumerSecret; + + private string _Callback; + + private DotNetOpenAuth.OAuth.VerificationCodeFormat _VerificationCodeFormat; + + private int _VerificationCodeLength; + + private EntitySet<OAuthToken> _OAuthTokens; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnConsumerIdChanging(int value); + partial void OnConsumerIdChanged(); + partial void OnConsumerKeyChanging(string value); + partial void OnConsumerKeyChanged(); + partial void OnConsumerSecretChanging(string value); + partial void OnConsumerSecretChanged(); + partial void OnCallbackChanging(string value); + partial void OnCallbackChanged(); + partial void OnVerificationCodeFormatChanging(DotNetOpenAuth.OAuth.VerificationCodeFormat value); + partial void OnVerificationCodeFormatChanged(); + partial void OnVerificationCodeLengthChanging(int value); + partial void OnVerificationCodeLengthChanged(); + #endregion + + public OAuthConsumer() + { + this._OAuthTokens = new EntitySet<OAuthToken>(new Action<OAuthToken>(this.attach_OAuthTokens), new Action<OAuthToken>(this.detach_OAuthTokens)); + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ConsumerId", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] + public int ConsumerId + { + get + { + return this._ConsumerId; + } + set + { + if ((this._ConsumerId != value)) + { + this.OnConsumerIdChanging(value); + this.SendPropertyChanging(); + this._ConsumerId = value; + this.SendPropertyChanged("ConsumerId"); + this.OnConsumerIdChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ConsumerKey", DbType="NVarChar(50) NOT NULL", CanBeNull=false)] + public string ConsumerKey + { + get + { + return this._ConsumerKey; + } + set + { + if ((this._ConsumerKey != value)) + { + this.OnConsumerKeyChanging(value); + this.SendPropertyChanging(); + this._ConsumerKey = value; + this.SendPropertyChanged("ConsumerKey"); + this.OnConsumerKeyChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ConsumerSecret", DbType="NVarChar(50) NOT NULL", CanBeNull=false)] + public string ConsumerSecret + { + get + { + return this._ConsumerSecret; + } + set + { + if ((this._ConsumerSecret != value)) + { + this.OnConsumerSecretChanging(value); + this.SendPropertyChanging(); + this._ConsumerSecret = value; + this.SendPropertyChanged("ConsumerSecret"); + this.OnConsumerSecretChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Callback")] + public string Callback + { + get + { + return this._Callback; + } + set + { + if ((this._Callback != value)) + { + this.OnCallbackChanging(value); + this.SendPropertyChanging(); + this._Callback = value; + this.SendPropertyChanged("Callback"); + this.OnCallbackChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_VerificationCodeFormat")] + public DotNetOpenAuth.OAuth.VerificationCodeFormat VerificationCodeFormat + { + get + { + return this._VerificationCodeFormat; + } + set + { + if ((this._VerificationCodeFormat != value)) + { + this.OnVerificationCodeFormatChanging(value); + this.SendPropertyChanging(); + this._VerificationCodeFormat = value; + this.SendPropertyChanged("VerificationCodeFormat"); + this.OnVerificationCodeFormatChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_VerificationCodeLength")] + public int VerificationCodeLength + { + get + { + return this._VerificationCodeLength; + } + set + { + if ((this._VerificationCodeLength != value)) + { + this.OnVerificationCodeLengthChanging(value); + this.SendPropertyChanging(); + this._VerificationCodeLength = value; + this.SendPropertyChanged("VerificationCodeLength"); + this.OnVerificationCodeLengthChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="OAuthConsumer_OAuthToken", Storage="_OAuthTokens", ThisKey="ConsumerId", OtherKey="ConsumerId")] + public EntitySet<OAuthToken> OAuthTokens + { + get + { + return this._OAuthTokens; + } + set + { + this._OAuthTokens.Assign(value); + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void attach_OAuthTokens(OAuthToken entity) + { + this.SendPropertyChanging(); + entity.OAuthConsumer = this; + } + + private void detach_OAuthTokens(OAuthToken entity) + { + this.SendPropertyChanging(); + entity.OAuthConsumer = null; + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.OAuthToken")] + public partial class OAuthToken : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private int _TokenId; + + private string _Token; + + private string _TokenSecret; + + private OAuthServiceProvider.Code.TokenAuthorizationState _State; + + private System.DateTime _IssueDate; + + private int _ConsumerId; + + private System.Nullable<int> _UserId; + + private string _Scope; + + private string _RequestTokenVerifier; + + private string _RequestTokenCallback; + + private string _ConsumerVersion; + + private EntityRef<OAuthConsumer> _OAuthConsumer; + + private EntityRef<User> _User; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnTokenIdChanging(int value); + partial void OnTokenIdChanged(); + partial void OnTokenChanging(string value); + partial void OnTokenChanged(); + partial void OnTokenSecretChanging(string value); + partial void OnTokenSecretChanged(); + partial void OnStateChanging(OAuthServiceProvider.Code.TokenAuthorizationState value); + partial void OnStateChanged(); + partial void OnIssueDateChanging(System.DateTime value); + partial void OnIssueDateChanged(); + partial void OnConsumerIdChanging(int value); + partial void OnConsumerIdChanged(); + partial void OnUserIdChanging(System.Nullable<int> value); + partial void OnUserIdChanged(); + partial void OnScopeChanging(string value); + partial void OnScopeChanged(); + partial void OnRequestTokenVerifierChanging(string value); + partial void OnRequestTokenVerifierChanged(); + partial void OnRequestTokenCallbackChanging(string value); + partial void OnRequestTokenCallbackChanged(); + partial void OnConsumerVersionChanging(string value); + partial void OnConsumerVersionChanged(); + #endregion + + public OAuthToken() + { + this._OAuthConsumer = default(EntityRef<OAuthConsumer>); + this._User = default(EntityRef<User>); + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_TokenId", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] + public int TokenId + { + get + { + return this._TokenId; + } + set + { + if ((this._TokenId != value)) + { + this.OnTokenIdChanging(value); + this.SendPropertyChanging(); + this._TokenId = value; + this.SendPropertyChanged("TokenId"); + this.OnTokenIdChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Token", DbType="NVarChar(50) NOT NULL", CanBeNull=false)] + public string Token + { + get + { + return this._Token; + } + set + { + if ((this._Token != value)) + { + this.OnTokenChanging(value); + this.SendPropertyChanging(); + this._Token = value; + this.SendPropertyChanged("Token"); + this.OnTokenChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_TokenSecret", DbType="NVarChar(50) NOT NULL", CanBeNull=false)] + public string TokenSecret + { + get + { + return this._TokenSecret; + } + set + { + if ((this._TokenSecret != value)) + { + this.OnTokenSecretChanging(value); + this.SendPropertyChanging(); + this._TokenSecret = value; + this.SendPropertyChanged("TokenSecret"); + this.OnTokenSecretChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_State", DbType="INT NOT NULL", CanBeNull=false)] + public OAuthServiceProvider.Code.TokenAuthorizationState State + { + get + { + return this._State; + } + set + { + if ((this._State != value)) + { + this.OnStateChanging(value); + this.SendPropertyChanging(); + this._State = value; + this.SendPropertyChanged("State"); + this.OnStateChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_IssueDate", DbType="DateTime NOT NULL")] + public System.DateTime IssueDate + { + get + { + return this._IssueDate; + } + set + { + if ((this._IssueDate != value)) + { + this.OnIssueDateChanging(value); + this.SendPropertyChanging(); + this._IssueDate = value; + this.SendPropertyChanged("IssueDate"); + this.OnIssueDateChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ConsumerId", DbType="Int NOT NULL")] + public int ConsumerId + { + get + { + return this._ConsumerId; + } + set + { + if ((this._ConsumerId != value)) + { + if (this._OAuthConsumer.HasLoadedOrAssignedValue) + { + throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException(); + } + this.OnConsumerIdChanging(value); + this.SendPropertyChanging(); + this._ConsumerId = value; + this.SendPropertyChanged("ConsumerId"); + this.OnConsumerIdChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_UserId", DbType="Int")] + public System.Nullable<int> UserId + { + get + { + return this._UserId; + } + set + { + if ((this._UserId != value)) + { + if (this._User.HasLoadedOrAssignedValue) + { + throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException(); + } + this.OnUserIdChanging(value); + this.SendPropertyChanging(); + this._UserId = value; + this.SendPropertyChanged("UserId"); + this.OnUserIdChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Scope", DbType="nvarchar(MAX)", CanBeNull=false)] + public string Scope + { + get + { + return this._Scope; + } + set + { + if ((this._Scope != value)) + { + this.OnScopeChanging(value); + this.SendPropertyChanging(); + this._Scope = value; + this.SendPropertyChanged("Scope"); + this.OnScopeChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_RequestTokenVerifier")] + public string RequestTokenVerifier + { + get + { + return this._RequestTokenVerifier; + } + set + { + if ((this._RequestTokenVerifier != value)) + { + this.OnRequestTokenVerifierChanging(value); + this.SendPropertyChanging(); + this._RequestTokenVerifier = value; + this.SendPropertyChanged("RequestTokenVerifier"); + this.OnRequestTokenVerifierChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_RequestTokenCallback")] + public string RequestTokenCallback + { + get + { + return this._RequestTokenCallback; + } + set + { + if ((this._RequestTokenCallback != value)) + { + this.OnRequestTokenCallbackChanging(value); + this.SendPropertyChanging(); + this._RequestTokenCallback = value; + this.SendPropertyChanged("RequestTokenCallback"); + this.OnRequestTokenCallbackChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ConsumerVersion")] + public string ConsumerVersion + { + get + { + return this._ConsumerVersion; + } + set + { + if ((this._ConsumerVersion != value)) + { + this.OnConsumerVersionChanging(value); + this.SendPropertyChanging(); + this._ConsumerVersion = value; + this.SendPropertyChanged("ConsumerVersion"); + this.OnConsumerVersionChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="OAuthConsumer_OAuthToken", Storage="_OAuthConsumer", ThisKey="ConsumerId", OtherKey="ConsumerId", IsForeignKey=true, DeleteOnNull=true, DeleteRule="CASCADE")] + public OAuthConsumer OAuthConsumer + { + get + { + return this._OAuthConsumer.Entity; + } + set + { + OAuthConsumer previousValue = this._OAuthConsumer.Entity; + if (((previousValue != value) + || (this._OAuthConsumer.HasLoadedOrAssignedValue == false))) + { + this.SendPropertyChanging(); + if ((previousValue != null)) + { + this._OAuthConsumer.Entity = null; + previousValue.OAuthTokens.Remove(this); + } + this._OAuthConsumer.Entity = value; + if ((value != null)) + { + value.OAuthTokens.Add(this); + this._ConsumerId = value.ConsumerId; + } + else + { + this._ConsumerId = default(int); + } + this.SendPropertyChanged("OAuthConsumer"); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="User_OAuthToken", Storage="_User", ThisKey="UserId", OtherKey="UserId", IsForeignKey=true, DeleteRule="CASCADE")] + public User User + { + get + { + return this._User.Entity; + } + set + { + User previousValue = this._User.Entity; + if (((previousValue != value) + || (this._User.HasLoadedOrAssignedValue == false))) + { + this.SendPropertyChanging(); + if ((previousValue != null)) + { + this._User.Entity = null; + previousValue.OAuthTokens.Remove(this); + } + this._User.Entity = value; + if ((value != null)) + { + value.OAuthTokens.Add(this); + this._UserId = value.UserId; + } + else + { + this._UserId = default(Nullable<int>); + } + this.SendPropertyChanged("User"); + } + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="")] + public partial class Nonce : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private string _Context; + + private string _Code; + + private System.DateTime _Timestamp; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnContextChanging(string value); + partial void OnContextChanged(); + partial void OnCodeChanging(string value); + partial void OnCodeChanged(); + partial void OnTimestampChanging(System.DateTime value); + partial void OnTimestampChanged(); + #endregion + + public Nonce() + { + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Context", CanBeNull=false, IsPrimaryKey=true)] + public string Context + { + get + { + return this._Context; + } + set + { + if ((this._Context != value)) + { + this.OnContextChanging(value); + this.SendPropertyChanging(); + this._Context = value; + this.SendPropertyChanged("Context"); + this.OnContextChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Code", CanBeNull=false, IsPrimaryKey=true)] + public string Code + { + get + { + return this._Code; + } + set + { + if ((this._Code != value)) + { + this.OnCodeChanging(value); + this.SendPropertyChanging(); + this._Code = value; + this.SendPropertyChanged("Code"); + this.OnCodeChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Timestamp", IsPrimaryKey=true)] + public System.DateTime Timestamp + { + get + { + return this._Timestamp; + } + set + { + if ((this._Timestamp != value)) + { + this.OnTimestampChanging(value); + this.SendPropertyChanging(); + this._Timestamp = value; + this.SendPropertyChanged("Timestamp"); + this.OnTimestampChanged(); + } + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + } +} +#pragma warning restore 1591 diff --git a/samples/OAuthServiceProvider/Code/DatabaseNonceStore.cs b/samples/OAuthServiceProvider/Code/DatabaseNonceStore.cs new file mode 100644 index 0000000..1f8f56e --- /dev/null +++ b/samples/OAuthServiceProvider/Code/DatabaseNonceStore.cs @@ -0,0 +1,55 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.Messaging.Bindings; + + /// <summary> + /// A database-persisted nonce store. + /// </summary> + public class DatabaseNonceStore : INonceStore { + /// <summary> + /// Initializes a new instance of the <see cref="DatabaseNonceStore"/> class. + /// </summary> + public DatabaseNonceStore() { + } + + #region INonceStore Members + + /// <summary> + /// Stores a given nonce and timestamp. + /// </summary> + /// <param name="context">The context, or namespace, within which the + /// <paramref name="nonce"/> must be unique. + /// The context SHOULD be treated as case-sensitive. + /// The value will never be <c>null</c> but may be the empty string.</param> + /// <param name="nonce">A series of random characters.</param> + /// <param name="timestampUtc">The UTC timestamp that together with the nonce string make it unique + /// within the given <paramref name="context"/>. + /// The timestamp may also be used by the data store to clear out old nonces.</param> + /// <returns> + /// True if the context+nonce+timestamp (combination) was not previously in the database. + /// False if the nonce was stored previously with the same timestamp and context. + /// </returns> + /// <remarks> + /// The nonce must be stored for no less than the maximum time window a message may + /// be processed within before being discarded as an expired message. + /// This maximum message age can be looked up via the + /// <see cref="DotNetOpenAuth.Configuration.MessagingElement.MaximumMessageLifetime"/> + /// property, accessible via the <see cref="DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration"/> + /// property. + /// </remarks> + public bool StoreNonce(string context, string nonce, DateTime timestampUtc) { + Global.DataContext.Nonces.InsertOnSubmit(new Nonce { Context = context, Code = nonce, Timestamp = timestampUtc }); + try { + Global.DataContext.SubmitChanges(); + return true; + } catch (System.Data.Linq.DuplicateKeyException) { + return false; + } + } + + #endregion + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/DatabaseTokenManager.cs b/samples/OAuthServiceProvider/Code/DatabaseTokenManager.cs new file mode 100644 index 0000000..ff586dc --- /dev/null +++ b/samples/OAuthServiceProvider/Code/DatabaseTokenManager.cs @@ -0,0 +1,163 @@ +//----------------------------------------------------------------------- +// <copyright file="DatabaseTokenManager.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + public class DatabaseTokenManager : IServiceProviderTokenManager { + #region IServiceProviderTokenManager + + public IConsumerDescription GetConsumer(string consumerKey) { + var consumerRow = Global.DataContext.OAuthConsumers.SingleOrDefault( + consumerCandidate => consumerCandidate.ConsumerKey == consumerKey); + if (consumerRow == null) { + throw new KeyNotFoundException(); + } + + return consumerRow; + } + + public IServiceProviderRequestToken GetRequestToken(string token) { + try { + return Global.DataContext.OAuthTokens.First(t => t.Token == token && t.State != TokenAuthorizationState.AccessToken); + } catch (InvalidOperationException ex) { + throw new KeyNotFoundException("Unrecognized token", ex); + } + } + + public IServiceProviderAccessToken GetAccessToken(string token) { + try { + return Global.DataContext.OAuthTokens.First(t => t.Token == token && t.State == TokenAuthorizationState.AccessToken); + } catch (InvalidOperationException ex) { + throw new KeyNotFoundException("Unrecognized token", ex); + } + } + + public void UpdateToken(IServiceProviderRequestToken token) { + // Nothing to do here, since we're using Linq To SQL, and + // We call LinqToSql's SubmitChanges method via our Global.Application_EndRequest method. + // This is a good pattern because we only save changes if the request didn't end up somehow failing. + // But if you DO want to save changes at this point, you could do it like so: + ////Global.DataContext.SubmitChanges(); + } + + #endregion + + #region ITokenManager Members + + public string GetTokenSecret(string token) { + var tokenRow = Global.DataContext.OAuthTokens.SingleOrDefault( + tokenCandidate => tokenCandidate.Token == token); + if (tokenRow == null) { + throw new ArgumentException(); + } + + return tokenRow.TokenSecret; + } + + public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response) { + RequestScopedTokenMessage scopedRequest = (RequestScopedTokenMessage)request; + var consumer = Global.DataContext.OAuthConsumers.Single(consumerRow => consumerRow.ConsumerKey == request.ConsumerKey); + string scope = scopedRequest.Scope; + OAuthToken newToken = new OAuthToken { + OAuthConsumer = consumer, + Token = response.Token, + TokenSecret = response.TokenSecret, + IssueDate = DateTime.UtcNow, + Scope = scope, + }; + + Global.DataContext.OAuthTokens.InsertOnSubmit(newToken); + Global.DataContext.SubmitChanges(); + } + + /// <summary> + /// Checks whether a given request token has already been authorized + /// by some user for use by the Consumer that requested it. + /// </summary> + /// <param name="requestToken">The Consumer's request token.</param> + /// <returns> + /// True if the request token has already been fully authorized by the user + /// who owns the relevant protected resources. False if the token has not yet + /// been authorized, has expired or does not exist. + /// </returns> + public bool IsRequestTokenAuthorized(string requestToken) { + var tokenFound = Global.DataContext.OAuthTokens.SingleOrDefault( + token => token.Token == requestToken && + token.State == TokenAuthorizationState.AuthorizedRequestToken); + return tokenFound != null; + } + + public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) { + var data = Global.DataContext; + var consumerRow = data.OAuthConsumers.Single(consumer => consumer.ConsumerKey == consumerKey); + var tokenRow = data.OAuthTokens.Single(token => token.Token == requestToken && token.OAuthConsumer == consumerRow); + Debug.Assert(tokenRow.State == TokenAuthorizationState.AuthorizedRequestToken, "The token should be authorized already!"); + + // Update the existing row to be an access token. + tokenRow.IssueDate = DateTime.UtcNow; + tokenRow.State = TokenAuthorizationState.AccessToken; + tokenRow.Token = accessToken; + tokenRow.TokenSecret = accessTokenSecret; + } + + /// <summary> + /// Classifies a token as a request token or an access token. + /// </summary> + /// <param name="token">The token to classify.</param> + /// <returns>Request or Access token, or invalid if the token is not recognized.</returns> + public TokenType GetTokenType(string token) { + var tokenRow = Global.DataContext.OAuthTokens.SingleOrDefault(tokenCandidate => tokenCandidate.Token == token); + if (tokenRow == null) { + return TokenType.InvalidToken; + } else if (tokenRow.State == TokenAuthorizationState.AccessToken) { + return TokenType.AccessToken; + } else { + return TokenType.RequestToken; + } + } + + #endregion + + public void AuthorizeRequestToken(string requestToken, User user) { + if (requestToken == null) { + throw new ArgumentNullException("requestToken"); + } + if (user == null) { + throw new ArgumentNullException("user"); + } + + var tokenRow = Global.DataContext.OAuthTokens.SingleOrDefault( + tokenCandidate => tokenCandidate.Token == requestToken && + tokenCandidate.State == TokenAuthorizationState.UnauthorizedRequestToken); + if (tokenRow == null) { + throw new ArgumentException(); + } + + tokenRow.State = TokenAuthorizationState.AuthorizedRequestToken; + tokenRow.User = user; + } + + public OAuthConsumer GetConsumerForToken(string token) { + if (String.IsNullOrEmpty(token)) { + throw new ArgumentNullException("requestToken"); + } + + var tokenRow = Global.DataContext.OAuthTokens.SingleOrDefault( + tokenCandidate => tokenCandidate.Token == token); + if (tokenRow == null) { + throw new ArgumentException(); + } + + return tokenRow.OAuthConsumer; + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/Global.cs b/samples/OAuthServiceProvider/Code/Global.cs new file mode 100644 index 0000000..60fed9f --- /dev/null +++ b/samples/OAuthServiceProvider/Code/Global.cs @@ -0,0 +1,135 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Linq; + using System.ServiceModel; + using System.Text; + using System.Web; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// The web application global events and properties. + /// </summary> + public class Global : HttpApplication { + /// <summary> + /// An application memory cache of recent log messages. + /// </summary> + public static StringBuilder LogMessages = new StringBuilder(); + + /// <summary> + /// The logger for this sample to use. + /// </summary> + public static log4net.ILog Logger = log4net.LogManager.GetLogger("DotNetOpenAuth.OAuthServiceProvider"); + + /// <summary> + /// Gets the transaction-protected database connection for the current request. + /// </summary> + public static DataClassesDataContext DataContext { + get { + DataClassesDataContext dataContext = dataContextSimple; + if (dataContext == null) { + dataContext = new DataClassesDataContext(); + dataContext.Connection.Open(); + dataContext.Transaction = dataContext.Connection.BeginTransaction(); + dataContextSimple = dataContext; + } + + return dataContext; + } + } + + public static DatabaseTokenManager TokenManager { get; set; } + + public static DatabaseNonceStore NonceStore { get; set; } + + public static User LoggedInUser { + get { return Global.DataContext.Users.SingleOrDefault(user => user.OpenIDClaimedIdentifier == HttpContext.Current.User.Identity.Name); } + } + + public static UserAuthorizationRequest PendingOAuthAuthorization { + get { return HttpContext.Current.Session["authrequest"] as UserAuthorizationRequest; } + set { HttpContext.Current.Session["authrequest"] = value; } + } + + private static DataClassesDataContext dataContextSimple { + get { + if (HttpContext.Current != null) { + return HttpContext.Current.Items["DataContext"] as DataClassesDataContext; + } else if (OperationContext.Current != null) { + object data; + if (OperationContext.Current.IncomingMessageProperties.TryGetValue("DataContext", out data)) { + return data as DataClassesDataContext; + } else { + return null; + } + } else { + throw new InvalidOperationException(); + } + } + + set { + if (HttpContext.Current != null) { + HttpContext.Current.Items["DataContext"] = value; + } else if (OperationContext.Current != null) { + OperationContext.Current.IncomingMessageProperties["DataContext"] = value; + } else { + throw new InvalidOperationException(); + } + } + } + + public static void AuthorizePendingRequestToken() { + ITokenContainingMessage tokenMessage = PendingOAuthAuthorization; + TokenManager.AuthorizeRequestToken(tokenMessage.Token, LoggedInUser); + PendingOAuthAuthorization = null; + } + + private static void CommitAndCloseDatabaseIfNecessary() { + var dataContext = dataContextSimple; + if (dataContext != null) { + dataContext.SubmitChanges(); + dataContext.Transaction.Commit(); + dataContext.Connection.Close(); + } + } + + private void Application_Start(object sender, EventArgs e) { + log4net.Config.XmlConfigurator.Configure(); + Logger.Info("Sample starting..."); + string appPath = HttpContext.Current.Request.ApplicationPath; + if (!appPath.EndsWith("/")) { + appPath += "/"; + } + + // This will break in IIS Integrated Pipeline mode, since applications + // start before the first incoming request context is available. + // TODO: fix this. + Constants.WebRootUrl = new Uri(HttpContext.Current.Request.Url, appPath); + Global.TokenManager = new DatabaseTokenManager(); + Global.NonceStore = new DatabaseNonceStore(); + } + + private void Application_End(object sender, EventArgs e) { + Logger.Info("Sample shutting down..."); + + // this would be automatic, but in partial trust scenarios it is not. + log4net.LogManager.Shutdown(); + } + + private void Application_Error(object sender, EventArgs e) { + Logger.Error("An unhandled exception occurred in ASP.NET processing: " + Server.GetLastError(), Server.GetLastError()); + + // In the event of an unhandled exception, reverse any changes that were made to the database to avoid any partial database updates. + var dataContext = dataContextSimple; + if (dataContext != null) { + dataContext.Transaction.Rollback(); + dataContext.Connection.Close(); + dataContext.Dispose(); + dataContextSimple = null; + } + } + + private void Application_EndRequest(object sender, EventArgs e) { + CommitAndCloseDatabaseIfNecessary(); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/IDataApi.cs b/samples/OAuthServiceProvider/Code/IDataApi.cs new file mode 100644 index 0000000..45853cd --- /dev/null +++ b/samples/OAuthServiceProvider/Code/IDataApi.cs @@ -0,0 +1,20 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Runtime.Serialization; + using System.ServiceModel; + using System.Text; + + [ServiceContract] + public interface IDataApi { + [OperationContract] + int? GetAge(); + + [OperationContract] + string GetName(); + + [OperationContract] + string[] GetFavoriteSites(); + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/OAuthAuthorizationManager.cs b/samples/OAuthServiceProvider/Code/OAuthAuthorizationManager.cs new file mode 100644 index 0000000..917a252 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/OAuthAuthorizationManager.cs @@ -0,0 +1,65 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.IdentityModel.Policy; + using System.Linq; + using System.Security.Principal; + using System.ServiceModel; + using System.ServiceModel.Channels; + using System.ServiceModel.Security; + using DotNetOpenAuth; + using DotNetOpenAuth.OAuth; + + /// <summary> + /// A WCF extension to authenticate incoming messages using OAuth. + /// </summary> + public class OAuthAuthorizationManager : ServiceAuthorizationManager { + public OAuthAuthorizationManager() { + } + + protected override bool CheckAccessCore(OperationContext operationContext) { + if (!base.CheckAccessCore(operationContext)) { + return false; + } + + HttpRequestMessageProperty httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; + Uri requestUri = operationContext.RequestContext.RequestMessage.Properties.Via; + ServiceProvider sp = Constants.CreateServiceProvider(); + try { + var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri); + if (auth != null) { + var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken); + + var principal = sp.CreatePrincipal(auth); + var policy = new OAuthPrincipalAuthorizationPolicy(principal); + var policies = new List<IAuthorizationPolicy> { + policy, + }; + + var securityContext = new ServiceSecurityContext(policies.AsReadOnly()); + if (operationContext.IncomingMessageProperties.Security != null) { + operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext; + } else { + operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty { + ServiceSecurityContext = securityContext, + }; + } + + securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> { + principal.Identity, + }; + + // Only allow this method call if the access token scope permits it. + string[] scopes = accessToken.Scope.Split('|'); + if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { + return true; + } + } + } catch (ProtocolException ex) { + Global.Logger.Error("Error processing OAuth messages.", ex); + } + + return false; + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/OAuthConsumer.cs b/samples/OAuthServiceProvider/Code/OAuthConsumer.cs new file mode 100644 index 0000000..d7dfc06 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/OAuthConsumer.cs @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthConsumer.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public partial class OAuthConsumer : IConsumerDescription { + #region IConsumerDescription Members + + string IConsumerDescription.Key { + get { return this.ConsumerKey; } + } + + string IConsumerDescription.Secret { + get { return this.ConsumerSecret; } + } + + System.Security.Cryptography.X509Certificates.X509Certificate2 IConsumerDescription.Certificate { + get { return null; } + } + + Uri IConsumerDescription.Callback { + get { return string.IsNullOrEmpty(this.Callback) ? null : new Uri(this.Callback); } + } + + DotNetOpenAuth.OAuth.VerificationCodeFormat IConsumerDescription.VerificationCodeFormat { + get { return this.VerificationCodeFormat; } + } + + int IConsumerDescription.VerificationCodeLength { + get { return this.VerificationCodeLength; } + } + + #endregion + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/OAuthPrincipalAuthorizationPolicy.cs b/samples/OAuthServiceProvider/Code/OAuthPrincipalAuthorizationPolicy.cs new file mode 100644 index 0000000..a25f4c5 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/OAuthPrincipalAuthorizationPolicy.cs @@ -0,0 +1,47 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.IdentityModel.Claims; + using System.IdentityModel.Policy; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public class OAuthPrincipalAuthorizationPolicy : IAuthorizationPolicy { + private readonly Guid uniqueId = Guid.NewGuid(); + private readonly OAuthPrincipal principal; + + /// <summary> + /// Initializes a new instance of the <see cref="OAuthPrincipalAuthorizationPolicy"/> class. + /// </summary> + /// <param name="principal">The principal.</param> + public OAuthPrincipalAuthorizationPolicy(OAuthPrincipal principal) { + this.principal = principal; + } + + #region IAuthorizationComponent Members + + /// <summary> + /// Gets a unique ID for this instance. + /// </summary> + public string Id { + get { return this.uniqueId.ToString(); } + } + + #endregion + + #region IAuthorizationPolicy Members + + public ClaimSet Issuer { + get { return ClaimSet.System; } + } + + public bool Evaluate(EvaluationContext evaluationContext, ref object state) { + evaluationContext.AddClaimSet(this, new DefaultClaimSet(Claim.CreateNameClaim(this.principal.Identity.Name))); + evaluationContext.Properties["Principal"] = this.principal; + return true; + } + + #endregion + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/OAuthToken.cs b/samples/OAuthServiceProvider/Code/OAuthToken.cs new file mode 100644 index 0000000..9099237 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/OAuthToken.cs @@ -0,0 +1,95 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthToken.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public partial class OAuthToken : IServiceProviderRequestToken, IServiceProviderAccessToken { + #region IServiceProviderRequestToken Members + + string IServiceProviderRequestToken.Token { + get { return this.Token; } + } + + string IServiceProviderRequestToken.ConsumerKey { + get { return this.OAuthConsumer.ConsumerKey; } + } + + DateTime IServiceProviderRequestToken.CreatedOn { + get { return this.IssueDate; } + } + + Uri IServiceProviderRequestToken.Callback { + get { return string.IsNullOrEmpty(this.RequestTokenCallback) ? null : new Uri(this.RequestTokenCallback); } + set { this.RequestTokenCallback = value.AbsoluteUri; } + } + + string IServiceProviderRequestToken.VerificationCode { + get { return this.RequestTokenVerifier; } + set { this.RequestTokenVerifier = value; } + } + + Version IServiceProviderRequestToken.ConsumerVersion { + get { return new Version(this.ConsumerVersion); } + set { this.ConsumerVersion = value.ToString(); } + } + + #endregion + + #region IServiceProviderAccessToken Members + + string IServiceProviderAccessToken.Token { + get { return this.Token; } + } + + DateTime? IServiceProviderAccessToken.ExpirationDate { + get { return null; } + } + + string IServiceProviderAccessToken.Username { + get { return this.User.OpenIDClaimedIdentifier; } + } + + string[] IServiceProviderAccessToken.Roles { + get { return this.Scope.Split('|'); } + } + + #endregion + + /// <summary> + /// Called by LinqToSql when the <see cref="IssueDate"/> property is about to change. + /// </summary> + /// <param name="value">The value.</param> + partial void OnIssueDateChanging(DateTime value) { + if (value.Kind == DateTimeKind.Unspecified) { + throw new ArgumentException("The DateTime.Kind cannot be Unspecified to ensure accurate timestamp checks."); + } + } + + /// <summary> + /// Called by LinqToSql when <see cref="IssueDate"/> has changed. + /// </summary> + partial void OnIssueDateChanged() { + if (this.IssueDate.Kind == DateTimeKind.Local) { + this._IssueDate = this.IssueDate.ToUniversalTime(); + } + } + + /// <summary> + /// Called by LinqToSql when a token instance is deserialized. + /// </summary> + partial void OnLoaded() { + if (this.IssueDate.Kind == DateTimeKind.Unspecified) { + // this detail gets lost in db storage, but must be reaffirmed so that expiratoin checks succeed. + this._IssueDate = DateTime.SpecifyKind(this.IssueDate, DateTimeKind.Utc); + } + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/RequestScopedTokenMessage.cs b/samples/OAuthServiceProvider/Code/RequestScopedTokenMessage.cs new file mode 100644 index 0000000..984d683 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/RequestScopedTokenMessage.cs @@ -0,0 +1,25 @@ +namespace OAuthServiceProvider.Code { + using System; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// A custom web app version of the message sent to request an unauthorized token. + /// </summary> + public class RequestScopedTokenMessage : UnauthorizedTokenRequest { + /// <summary> + /// Initializes a new instance of the <see cref="RequestScopedTokenMessage"/> class. + /// </summary> + /// <param name="endpoint">The endpoint that will receive the message.</param> + /// <param name="version">The OAuth version.</param> + public RequestScopedTokenMessage(MessageReceivingEndpoint endpoint, Version version) + : base(endpoint, version) { + } + + /// <summary> + /// Gets or sets the scope of the access being requested. + /// </summary> + [MessagePart("scope", IsRequired = true)] + public string Scope { get; set; } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/TokenAuthorizationState.cs b/samples/OAuthServiceProvider/Code/TokenAuthorizationState.cs new file mode 100644 index 0000000..a9cfa4e --- /dev/null +++ b/samples/OAuthServiceProvider/Code/TokenAuthorizationState.cs @@ -0,0 +1,26 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + + /// <summary> + /// Various states an OAuth token can be in. + /// </summary> + public enum TokenAuthorizationState : int { + /// <summary> + /// An unauthorized request token. + /// </summary> + UnauthorizedRequestToken = 0, + + /// <summary> + /// An authorized request token. + /// </summary> + AuthorizedRequestToken = 1, + + /// <summary> + /// An authorized access token. + /// </summary> + AccessToken = 2, + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/TracePageAppender.cs b/samples/OAuthServiceProvider/Code/TracePageAppender.cs new file mode 100644 index 0000000..8f97c89 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/TracePageAppender.cs @@ -0,0 +1,13 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.IO; + using System.Web; + + public class TracePageAppender : log4net.Appender.AppenderSkeleton { + protected override void Append(log4net.Core.LoggingEvent loggingEvent) { + StringWriter sw = new StringWriter(Global.LogMessages); + Layout.Format(sw, loggingEvent); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Code/Utilities.cs b/samples/OAuthServiceProvider/Code/Utilities.cs new file mode 100644 index 0000000..a225650 --- /dev/null +++ b/samples/OAuthServiceProvider/Code/Utilities.cs @@ -0,0 +1,28 @@ +namespace OAuthServiceProvider.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Principal; + using System.Web; + + /// <summary> + /// Extension methods and other helpful utility methods. + /// </summary> + public static class Utilities { + /// <summary> + /// Gets the database entity representing the user identified by a given <see cref="IIdentity"/> instance. + /// </summary> + /// <param name="identity">The identity of the user.</param> + /// <returns> + /// The database object for that user; or <c>null</c> if the user could not + /// be found or if <paramref name="identity"/> is <c>null</c> or represents an anonymous identity. + /// </returns> + public static User GetUser(this IIdentity identity) { + if (identity == null || !identity.IsAuthenticated) { + return null; + } + + return Global.DataContext.Users.SingleOrDefault(user => user.OpenIDClaimedIdentifier == identity.Name); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/DataApi.cs b/samples/OAuthServiceProvider/DataApi.cs new file mode 100644 index 0000000..9d531e6 --- /dev/null +++ b/samples/OAuthServiceProvider/DataApi.cs @@ -0,0 +1,34 @@ +namespace OAuthServiceProvider { + using System.Linq; + using System.ServiceModel; + using OAuthServiceProvider.Code; + + /// <summary> + /// The WCF service API. + /// </summary> + /// <remarks> + /// Note how there is no code here that is bound to OAuth or any other + /// credential/authorization scheme. That's all part of the channel/binding elsewhere. + /// And the reference to OperationContext.Current.ServiceSecurityContext.PrimaryIdentity + /// is the user being impersonated by the WCF client. + /// In the OAuth case, it is the user who authorized the OAuth access token that was used + /// to gain access to the service. + /// </remarks> + public class DataApi : IDataApi { + private User User { + get { return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.GetUser(); } + } + + public int? GetAge() { + return User.Age; + } + + public string GetName() { + return User.FullName; + } + + public string[] GetFavoriteSites() { + return User.FavoriteSites.Select(site => site.SiteUrl).ToArray(); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/DataApi.svc b/samples/OAuthServiceProvider/DataApi.svc new file mode 100644 index 0000000..50e952c --- /dev/null +++ b/samples/OAuthServiceProvider/DataApi.svc @@ -0,0 +1 @@ +<%@ ServiceHost Language="C#" Debug="true" Service="OAuthServiceProvider.DataApi" CodeBehind="DataApi.cs" %> diff --git a/samples/OAuthServiceProvider/Default.aspx b/samples/OAuthServiceProvider/Default.aspx new file mode 100644 index 0000000..3e5d820 --- /dev/null +++ b/samples/OAuthServiceProvider/Default.aspx @@ -0,0 +1,13 @@ +<%@ Page Title="DotNetOpenAuth Service Provider Sample" Language="C#" MasterPageFile="~/MasterPage.master" CodeBehind="~/Default.aspx.cs" Inherits="OAuthServiceProvider._Default" AutoEventWireup="True" %> + +<%@ Import Namespace="System.IO" %> +<%@ Import Namespace="System.Data.SqlClient" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <asp:Button ID="createDatabaseButton" runat="server" Text="(Re)create Database" OnClick="createDatabaseButton_Click" /> + <asp:Label runat="server" ID="databaseStatus" EnableViewState="false" Text="Database recreated!" + Visible="false" /> + <p>Note that to be useful, you really need to either modify the database to add an + account with data that will be accessed by this sample, or modify this very page + to inject that data into the database. </p> +</asp:Content> diff --git a/samples/OAuthServiceProvider/Default.aspx.cs b/samples/OAuthServiceProvider/Default.aspx.cs new file mode 100644 index 0000000..653046a --- /dev/null +++ b/samples/OAuthServiceProvider/Default.aspx.cs @@ -0,0 +1,49 @@ +namespace OAuthServiceProvider { + using System; + using System.Collections.Generic; + using System.Configuration; + using System.IO; + using System.Linq; + using System.Web; + using OAuthServiceProvider.Code; + + public partial class _Default : System.Web.UI.Page { + protected void createDatabaseButton_Click(object sender, EventArgs e) { + string databasePath = Path.Combine(Server.MapPath(Request.ApplicationPath), "App_Data"); + if (!Directory.Exists(databasePath)) { + Directory.CreateDirectory(databasePath); + } + string connectionString = ConfigurationManager.ConnectionStrings["DatabaseConnectionString"].ConnectionString.Replace("|DataDirectory|", databasePath); + var dc = new DataClassesDataContext(connectionString); + if (dc.DatabaseExists()) { + dc.DeleteDatabase(); + } + try { + dc.CreateDatabase(); + + // Fill with sample data. + dc.OAuthConsumers.InsertOnSubmit(new OAuthConsumer { + ConsumerKey = "sampleconsumer", + ConsumerSecret = "samplesecret", + }); + dc.Users.InsertOnSubmit(new User { + OpenIDFriendlyIdentifier = "=arnott", + OpenIDClaimedIdentifier = "=!9B72.7DD1.50A9.5CCD", + Age = 27, + FullName = "Andrew Arnott", + FavoriteSites = new System.Data.Linq.EntitySet<FavoriteSite> { + new FavoriteSite { SiteUrl = "http://www.microsoft.com" }, + new FavoriteSite { SiteUrl = "http://www.google.com" }, + }, + }); + + dc.SubmitChanges(); + this.databaseStatus.Visible = true; + } catch (System.Data.SqlClient.SqlException ex) { + foreach (System.Data.SqlClient.SqlError error in ex.Errors) { + Response.Write(error.Message); + } + } + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Default.aspx.designer.cs b/samples/OAuthServiceProvider/Default.aspx.designer.cs new file mode 100644 index 0000000..afa79c0 --- /dev/null +++ b/samples/OAuthServiceProvider/Default.aspx.designer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthServiceProvider { + + + public partial class _Default { + + /// <summary> + /// createDatabaseButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button createDatabaseButton; + + /// <summary> + /// databaseStatus control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label databaseStatus; + } +} diff --git a/samples/OAuthServiceProvider/Global.asax b/samples/OAuthServiceProvider/Global.asax new file mode 100644 index 0000000..3007bd3 --- /dev/null +++ b/samples/OAuthServiceProvider/Global.asax @@ -0,0 +1 @@ +<%@ Application Inherits="OAuthServiceProvider.Code.Global" CodeBehind="Code\Global.cs" %>
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Login.aspx b/samples/OAuthServiceProvider/Login.aspx new file mode 100644 index 0000000..4498ee0 --- /dev/null +++ b/samples/OAuthServiceProvider/Login.aspx @@ -0,0 +1,7 @@ +<%@ Page Title="Login" Language="C#" MasterPageFile="~/MasterPage.master" %> + +<%@ Register Assembly="DotNetOpenAuth.OpenId.RelyingParty.UI" Namespace="DotNetOpenAuth.OpenId.RelyingParty" TagPrefix="rp" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <rp:OpenIdLogin runat="server" TabIndex='1' /> +</asp:Content> diff --git a/samples/OAuthServiceProvider/MasterPage.master b/samples/OAuthServiceProvider/MasterPage.master new file mode 100644 index 0000000..136dfc9 --- /dev/null +++ b/samples/OAuthServiceProvider/MasterPage.master @@ -0,0 +1,23 @@ +<%@ Master Language="C#" %> + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<script runat="server"> + +</script> + +<html xmlns="http://www.w3.org/1999/xhtml"> +<head runat="server"> + <title>DotNetOpenAuth Service Provider sample</title> + <asp:ContentPlaceHolder ID="head" runat="server"/> +</head> +<body> + <form id="form1" runat="server"> + <h1>DotNetOpenAuth Service Provider sample</h1> + <div> + <asp:ContentPlaceHolder ID="Body" runat="server"> + </asp:ContentPlaceHolder> + </div> + </form> +</body> +</html> diff --git a/samples/OAuthServiceProvider/Members/Authorize.aspx b/samples/OAuthServiceProvider/Members/Authorize.aspx new file mode 100644 index 0000000..b3e2c6a --- /dev/null +++ b/samples/OAuthServiceProvider/Members/Authorize.aspx @@ -0,0 +1,58 @@ +<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" Inherits="OAuthServiceProvider.Authorize" Codebehind="Authorize.aspx.cs" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <asp:MultiView runat="server" ActiveViewIndex="0" ID="multiView"> + <asp:View runat="server"> + <div style="background-color: Yellow"> + <b>Warning</b>: Never give your login credentials to another web site or application. + </div> + <asp:HiddenField runat="server" ID="OAuthAuthorizationSecToken" EnableViewState="false" /> + <p>The client web site or application <asp:Label ID="consumerLabel" Font-Bold="true" + runat="server" Text="[consumer]" /> wants access to your <asp:Label ID="desiredAccessLabel" + Font-Bold="true" runat="server" Text="[protected resource]" />. </p> + <p>Do you want to allow this? </p> + <div style="display: none" id="responseButtonsDiv"> + <asp:Button ID="allowAccessButton" runat="server" Text="Yes" OnClick="allowAccessButton_Click" /> + <asp:Button ID="denyAccessButton" runat="server" Text="No" OnClick="denyAccessButton_Click" /> + </div> + <div id="javascriptDisabled"> + <b>Javascript appears to be disabled in your browser. </b>This page requires Javascript + to be enabled to better protect your security. + </div> + <p>If you grant access now, you can revoke it at any time by returning to this page. + </p> + <asp:Panel runat="server" BackColor="Red" ForeColor="White" Font-Bold="true" Visible="false" ID="OAuth10ConsumerWarning"> + This website is registered with service_PROVIDER_DOMAIN_NAME to make authorization requests, but has not been configured to send requests securely. If you grant access but you did not initiate this request at consumer_DOMAIN_NAME, it may be possible for other users of consumer_DOMAIN_NAME to access your data. We recommend you deny access unless you are certain that you initiated this request directly with consumer_DOMAIN_NAME. + </asp:Panel> + <script language="javascript" type="text/javascript"> + //<![CDATA[ + // we use HTML to hide the action buttons and Javascript to show them + // to protect against click-jacking in an iframe whose javascript is disabled. + document.getElementById('responseButtonsDiv').style.display = 'block'; + document.getElementById('javascriptDisabled').style.display = 'none'; + + // Frame busting code (to protect us from being hosted in an iframe). + // This protects us from click-jacking. + if (document.location !== window.top.location) { + window.top.location = document.location; + } + //]]> + </script> + </asp:View> + <asp:View runat="server"> + <p>Authorization has been granted.</p> + <asp:MultiView runat="server" ID="verifierMultiView" ActiveViewIndex="0"> + <asp:View runat="server"> + <p>You must enter this verification code at the Consumer: <asp:Label runat="server" + ID="verificationCodeLabel" /> </p> + </asp:View> + <asp:View ID="View1" runat="server"> + <p>You may now close this window and return to the Consumer. </p> + </asp:View> + </asp:MultiView> + </asp:View> + <asp:View runat="server"> + <p>Authorization has been denied. You're free to do whatever now. </p> + </asp:View> + </asp:MultiView> +</asp:Content> diff --git a/samples/OAuthServiceProvider/Members/Authorize.aspx.cs b/samples/OAuthServiceProvider/Members/Authorize.aspx.cs new file mode 100644 index 0000000..faa2147 --- /dev/null +++ b/samples/OAuthServiceProvider/Members/Authorize.aspx.cs @@ -0,0 +1,80 @@ +namespace OAuthServiceProvider { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Cryptography; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + using DotNetOpenAuth; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.Messages; + using OAuthServiceProvider.Code; + + /// <summary> + /// Conducts the user through a Consumer authorization process. + /// </summary> + public partial class Authorize : System.Web.UI.Page { + private static readonly RandomNumberGenerator CryptoRandomDataGenerator = new RNGCryptoServiceProvider(); + + private string AuthorizationSecret { + get { return Session["OAuthAuthorizationSecret"] as string; } + set { Session["OAuthAuthorizationSecret"] = value; } + } + + protected void Page_Load(object sender, EventArgs e) { + if (!IsPostBack) { + if (Global.PendingOAuthAuthorization == null) { + Response.Redirect("~/Members/AuthorizedConsumers.aspx"); + } else { + ITokenContainingMessage pendingToken = Global.PendingOAuthAuthorization; + var token = Global.DataContext.OAuthTokens.Single(t => t.Token == pendingToken.Token); + this.desiredAccessLabel.Text = token.Scope; + this.consumerLabel.Text = Global.TokenManager.GetConsumerForToken(token.Token).ConsumerKey; + + // Generate an unpredictable secret that goes to the user agent and must come back + // with authorization to guarantee the user interacted with this page rather than + // being scripted by an evil Consumer. + byte[] randomData = new byte[8]; + CryptoRandomDataGenerator.GetBytes(randomData); + this.AuthorizationSecret = Convert.ToBase64String(randomData); + this.OAuthAuthorizationSecToken.Value = this.AuthorizationSecret; + + this.OAuth10ConsumerWarning.Visible = Global.PendingOAuthAuthorization.IsUnsafeRequest; + } + } + } + + protected void allowAccessButton_Click(object sender, EventArgs e) { + if (this.AuthorizationSecret != this.OAuthAuthorizationSecToken.Value) { + throw new ArgumentException(); // probably someone trying to hack in. + } + this.AuthorizationSecret = null; // clear one time use secret + var pending = Global.PendingOAuthAuthorization; + Global.AuthorizePendingRequestToken(); + this.multiView.ActiveViewIndex = 1; + + ServiceProvider sp = new ServiceProvider(Constants.SelfDescription, Global.TokenManager); + var response = sp.PrepareAuthorizationResponse(pending); + if (response != null) { + sp.Channel.Send(response); + } else { + if (pending.IsUnsafeRequest) { + this.verifierMultiView.ActiveViewIndex = 1; + } else { + string verifier = ServiceProvider.CreateVerificationCode(VerificationCodeFormat.AlphaNumericNoLookAlikes, 10); + this.verificationCodeLabel.Text = verifier; + ITokenContainingMessage requestTokenMessage = pending; + var requestToken = Global.TokenManager.GetRequestToken(requestTokenMessage.Token); + requestToken.VerificationCode = verifier; + Global.TokenManager.UpdateToken(requestToken); + } + } + } + + protected void denyAccessButton_Click(object sender, EventArgs e) { + // erase the request token. + this.multiView.ActiveViewIndex = 2; + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Members/Authorize.aspx.designer.cs b/samples/OAuthServiceProvider/Members/Authorize.aspx.designer.cs new file mode 100644 index 0000000..8aaf94d --- /dev/null +++ b/samples/OAuthServiceProvider/Members/Authorize.aspx.designer.cs @@ -0,0 +1,105 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthServiceProvider { + + + public partial class Authorize { + + /// <summary> + /// multiView control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.MultiView multiView; + + /// <summary> + /// OAuthAuthorizationSecToken control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.HiddenField OAuthAuthorizationSecToken; + + /// <summary> + /// consumerLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label consumerLabel; + + /// <summary> + /// desiredAccessLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label desiredAccessLabel; + + /// <summary> + /// allowAccessButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button allowAccessButton; + + /// <summary> + /// denyAccessButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button denyAccessButton; + + /// <summary> + /// OAuth10ConsumerWarning control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Panel OAuth10ConsumerWarning; + + /// <summary> + /// verifierMultiView control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.MultiView verifierMultiView; + + /// <summary> + /// verificationCodeLabel control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Label verificationCodeLabel; + + /// <summary> + /// View1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.View View1; + } +} diff --git a/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx b/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx new file mode 100644 index 0000000..3506eb9 --- /dev/null +++ b/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx @@ -0,0 +1,6 @@ +<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" Inherits="OAuthServiceProvider.AuthorizedConsumers" Codebehind="AuthorizedConsumers.aspx.cs" %> + +<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server"> + <h2>The following consumers have access to your data</h2> + <p>TODO</p> +</asp:Content> diff --git a/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx.cs b/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx.cs new file mode 100644 index 0000000..fe647a8 --- /dev/null +++ b/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx.cs @@ -0,0 +1,17 @@ +namespace OAuthServiceProvider { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + + /// <summary> + /// Lists the consumers that have active request or access tokens + /// and provides a mechanism for the user to revoke permissions. + /// </summary> + public partial class AuthorizedConsumers : System.Web.UI.Page { + protected void Page_Load(object sender, EventArgs e) { + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx.designer.cs b/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx.designer.cs new file mode 100644 index 0000000..419c114 --- /dev/null +++ b/samples/OAuthServiceProvider/Members/AuthorizedConsumers.aspx.designer.cs @@ -0,0 +1,15 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthServiceProvider { + + + public partial class AuthorizedConsumers { + } +} diff --git a/samples/OAuthServiceProvider/Members/Logoff.aspx b/samples/OAuthServiceProvider/Members/Logoff.aspx new file mode 100644 index 0000000..afa9dd9 --- /dev/null +++ b/samples/OAuthServiceProvider/Members/Logoff.aspx @@ -0,0 +1,8 @@ +<%@ Page Title="Log off" Language="C#" MasterPageFile="~/MasterPage.master" %> + +<script runat="server"> + private void Page_Load(object sender, EventArgs e) { + FormsAuthentication.SignOut(); + Response.Redirect("~/"); + } +</script> diff --git a/samples/OAuthServiceProvider/Members/Web.config b/samples/OAuthServiceProvider/Members/Web.config new file mode 100644 index 0000000..50fab27 --- /dev/null +++ b/samples/OAuthServiceProvider/Members/Web.config @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<configuration> + <system.web> + <authorization> + <deny users="?"/> + </authorization> + </system.web> +</configuration> diff --git a/samples/OAuthServiceProvider/OAuth.ashx b/samples/OAuthServiceProvider/OAuth.ashx new file mode 100644 index 0000000..8a74926 --- /dev/null +++ b/samples/OAuthServiceProvider/OAuth.ashx @@ -0,0 +1,42 @@ +<%@ WebHandler Language="C#" Class="OAuth" %> + +using System; +using System.Linq; +using System.Web; +using System.Web.SessionState; +using DotNetOpenAuth.OAuth; +using DotNetOpenAuth.OAuth.ChannelElements; +using DotNetOpenAuth.OAuth.Messages; +using DotNetOpenAuth.Messaging; +using OAuthServiceProvider.Code; + +public class OAuth : IHttpHandler, IRequiresSessionState { + ServiceProvider sp; + + public OAuth() { + sp = new ServiceProvider(Constants.SelfDescription, Global.TokenManager, new CustomOAuthMessageFactory(Global.TokenManager)); + } + + public void ProcessRequest(HttpContext context) { + IProtocolMessage request = sp.ReadRequest(); + RequestScopedTokenMessage requestToken; + UserAuthorizationRequest requestAuth; + AuthorizedTokenRequest requestAccessToken; + if ((requestToken = request as RequestScopedTokenMessage) != null) { + var response = sp.PrepareUnauthorizedTokenMessage(requestToken); + sp.Channel.Send(response); + } else if ((requestAuth = request as UserAuthorizationRequest) != null) { + Global.PendingOAuthAuthorization = requestAuth; + HttpContext.Current.Response.Redirect("~/Members/Authorize.aspx"); + } else if ((requestAccessToken = request as AuthorizedTokenRequest) != null) { + var response = sp.PrepareAccessTokenMessage(requestAccessToken); + sp.Channel.Send(response); + } else { + throw new InvalidOperationException(); + } + } + + public bool IsReusable { + get { return true; } + } +} diff --git a/samples/OAuthServiceProvider/OAuthServiceProvider.csproj b/samples/OAuthServiceProvider/OAuthServiceProvider.csproj new file mode 100644 index 0000000..850ae26 --- /dev/null +++ b/samples/OAuthServiceProvider/OAuthServiceProvider.csproj @@ -0,0 +1,202 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))\EnlistmentInfo.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))' != '' " /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion> + </ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{CAA2408C-6918-4902-A512-58BCD62216C3}</ProjectGuid> + <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>OAuthServiceProvider</RootNamespace> + <AssemblyName>OAuthServiceProvider</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <UseIISExpress>false</UseIISExpress> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="log4net"> + <HintPath>..\..\lib\log4net.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Core" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Data.Linq" /> + <Reference Include="System.IdentityModel" /> + <Reference Include="System.ServiceModel" /> + <Reference Include="System.Web.Extensions" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Web" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Configuration" /> + <Reference Include="System.Web.Services" /> + <Reference Include="System.EnterpriseServices" /> + <Reference Include="System.Web.Mobile" /> + </ItemGroup> + <ItemGroup> + <Content Include="DataApi.svc" /> + <Content Include="Default.aspx" /> + <Content Include="favicon.ico" /> + <Content Include="Global.asax" /> + <Content Include="Login.aspx" /> + <Content Include="Members\Authorize.aspx" /> + <Content Include="Members\AuthorizedConsumers.aspx" /> + <Content Include="Members\Logoff.aspx" /> + <Content Include="TracePage.aspx" /> + <Content Include="Web.config" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Code\DatabaseNonceStore.cs" /> + <Compile Include="Default.aspx.designer.cs"> + <DependentUpon>Default.aspx</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="DataApi.cs"> + <DependentUpon>DataApi.svc</DependentUpon> + </Compile> + <Compile Include="Members\Authorize.aspx.designer.cs"> + <DependentUpon>Authorize.aspx</DependentUpon> + </Compile> + <Compile Include="Members\AuthorizedConsumers.aspx.designer.cs"> + <DependentUpon>AuthorizedConsumers.aspx</DependentUpon> + </Compile> + <Compile Include="Code\Constants.cs" /> + <Compile Include="Code\CustomOAuthTypeProvider.cs" /> + <Compile Include="Code\DatabaseTokenManager.cs" /> + <Compile Include="Code\Global.cs" /> + <Compile Include="Code\IDataApi.cs" /> + <Compile Include="Code\OAuthAuthorizationManager.cs" /> + <Compile Include="Code\OAuthConsumer.cs" /> + <Compile Include="Code\OAuthPrincipalAuthorizationPolicy.cs" /> + <Compile Include="Code\OAuthToken.cs" /> + <Compile Include="Code\RequestScopedTokenMessage.cs" /> + <Compile Include="Code\TokenAuthorizationState.cs" /> + <Compile Include="Code\TracePageAppender.cs" /> + <Compile Include="Code\Utilities.cs" /> + <Compile Include="Code\DataClasses.designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>DataClasses.dbml</DependentUpon> + </Compile> + <Compile Include="Default.aspx.cs"> + <DependentUpon>Default.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="Members\Authorize.aspx.cs"> + <DependentUpon>Authorize.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="Members\AuthorizedConsumers.aspx.cs"> + <DependentUpon>AuthorizedConsumers.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="TracePage.aspx.cs"> + <DependentUpon>TracePage.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="TracePage.aspx.designer.cs"> + <DependentUpon>TracePage.aspx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <Folder Include="App_Data\" /> + </ItemGroup> + <ItemGroup> + <Content Include="OAuth.ashx" /> + </ItemGroup> + <ItemGroup> + <Content Include="MasterPage.master" /> + </ItemGroup> + <ItemGroup> + <None Include="Code\DataClasses.dbml"> + <Generator>MSLinqToSQLGenerator</Generator> + <LastGenOutput>DataClasses.designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </None> + <Content Include="Members\Web.config" /> + </ItemGroup> + <ItemGroup> + <None Include="Code\DataClasses.dbml.layout"> + <DependentUpon>DataClasses.dbml</DependentUpon> + </None> + </ItemGroup> + <ItemGroup> + <Service Include="{3259AA49-8AA1-44D3-9025-A0B520596A8C}" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\src\DotNetOpenAuth.Core\DotNetOpenAuth.Core.csproj"> + <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> + <Name>DotNetOpenAuth.Core</Name> + </ProjectReference> + <ProjectReference Include="..\..\src\DotNetOpenAuth.OAuth.ServiceProvider\DotNetOpenAuth.OAuth.ServiceProvider.csproj"> + <Project>{FED1923A-6D70-49B5-A37A-FB744FEC1C86}</Project> + <Name>DotNetOpenAuth.OAuth.ServiceProvider</Name> + </ProjectReference> + <ProjectReference Include="..\..\src\DotNetOpenAuth.OAuth\DotNetOpenAuth.OAuth.csproj"> + <Project>{A288FCC8-6FCF-46DA-A45E-5F9281556361}</Project> + <Name>DotNetOpenAuth.OAuth</Name> + </ProjectReference> + <ProjectReference Include="..\..\src\DotNetOpenAuth.OpenId.RelyingParty.UI\DotNetOpenAuth.OpenId.RelyingParty.UI.csproj"> + <Project>{1ED8D424-F8AB-4050-ACEB-F27F4F909484}</Project> + <Name>DotNetOpenAuth.OpenId.RelyingParty.UI</Name> + </ProjectReference> + <ProjectReference Include="..\..\src\DotNetOpenAuth.OpenId.RelyingParty\DotNetOpenAuth.OpenId.RelyingParty.csproj"> + <Project>{F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}</Project> + <Name>DotNetOpenAuth.OpenId.RelyingParty</Name> + </ProjectReference> + <ProjectReference Include="..\..\src\DotNetOpenAuth.OpenId\DotNetOpenAuth.OpenId.csproj"> + <Project>{3896A32A-E876-4C23-B9B8-78E17D134CD3}</Project> + <Name>DotNetOpenAuth.OpenId</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> + <ProjectExtensions> + <VisualStudio> + <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> + <WebProjectProperties> + <UseIIS>False</UseIIS> + <AutoAssignPort>False</AutoAssignPort> + <DevelopmentServerPort>65169</DevelopmentServerPort> + <DevelopmentServerVPath>/</DevelopmentServerVPath> + <IISUrl> + </IISUrl> + <NTLMAuthentication>False</NTLMAuthentication> + <UseCustomServer>False</UseCustomServer> + <CustomServerUrl> + </CustomServerUrl> + <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> + </WebProjectProperties> + </FlavorProperties> + </VisualStudio> + </ProjectExtensions> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " /> +</Project>
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/Properties/AssemblyInfo.cs b/samples/OAuthServiceProvider/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..09d299c --- /dev/null +++ b/samples/OAuthServiceProvider/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OAuthServiceProvider")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OAuthServiceProvider")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("B6206451-6557-4568-8D25-84AF93EC8B7B")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/OAuthServiceProvider/Settings.StyleCop b/samples/OAuthServiceProvider/Settings.StyleCop new file mode 100644 index 0000000..7f55ce6 --- /dev/null +++ b/samples/OAuthServiceProvider/Settings.StyleCop @@ -0,0 +1 @@ +<StyleCopSettings Version="4.3" />
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/TracePage.aspx b/samples/OAuthServiceProvider/TracePage.aspx new file mode 100644 index 0000000..e83adc3 --- /dev/null +++ b/samples/OAuthServiceProvider/TracePage.aspx @@ -0,0 +1,18 @@ +<%@ Page Language="C#" AutoEventWireup="true" Inherits="OAuthServiceProvider.TracePage" Codebehind="TracePage.aspx.cs" %> + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head runat="server"> + <title></title> +</head> +<body> + <form id="form1" runat="server"> + <p align="right"> + <asp:Button runat="server" Text="Clear log" ID="clearLogButton" OnClick="clearLogButton_Click" /> + </p> + <pre> + <asp:PlaceHolder runat="server" ID="placeHolder1" /> + </pre> + </form> +</body> +</html> diff --git a/samples/OAuthServiceProvider/TracePage.aspx.cs b/samples/OAuthServiceProvider/TracePage.aspx.cs new file mode 100644 index 0000000..fcfade5 --- /dev/null +++ b/samples/OAuthServiceProvider/TracePage.aspx.cs @@ -0,0 +1,24 @@ +namespace OAuthServiceProvider { + using System; + using System.Collections.Generic; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + using OAuthServiceProvider.Code; + + /// <summary> + /// A page to display recent log messages. + /// </summary> + public partial class TracePage : System.Web.UI.Page { + protected void Page_Load(object sender, EventArgs e) { + this.placeHolder1.Controls.Add(new Label { Text = HttpUtility.HtmlEncode(Global.LogMessages.ToString()) }); + } + + protected void clearLogButton_Click(object sender, EventArgs e) { + Global.LogMessages.Length = 0; + + // clear the page immediately, and allow for F5 without a Postback warning. + Response.Redirect(Request.Url.AbsoluteUri); + } + } +}
\ No newline at end of file diff --git a/samples/OAuthServiceProvider/TracePage.aspx.designer.cs b/samples/OAuthServiceProvider/TracePage.aspx.designer.cs new file mode 100644 index 0000000..3cd04be --- /dev/null +++ b/samples/OAuthServiceProvider/TracePage.aspx.designer.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OAuthServiceProvider { + + + public partial class TracePage { + + /// <summary> + /// form1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + + /// <summary> + /// clearLogButton control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.Button clearLogButton; + + /// <summary> + /// placeHolder1 control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.WebControls.PlaceHolder placeHolder1; + } +} diff --git a/samples/OAuthServiceProvider/Web.config b/samples/OAuthServiceProvider/Web.config new file mode 100644 index 0000000..60a4d86 --- /dev/null +++ b/samples/OAuthServiceProvider/Web.config @@ -0,0 +1,180 @@ +<?xml version="1.0"?> +<configuration> + <configSections> + <section name="uri" type="System.Configuration.UriSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> + <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler" requirePermission="false"/> + <sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth.Core"> + <section name="oauth" type="DotNetOpenAuth.Configuration.OAuthElement, DotNetOpenAuth.OAuth" requirePermission="false" allowLocation="true" /> + <section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" /> + <section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" /> + </sectionGroup> + <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> + <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> + <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> + <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> + <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/> + <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> + <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> + <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> + </sectionGroup> + </sectionGroup> + </sectionGroup> + </configSections> + + <!-- The uri section is necessary to turn on .NET 3.5 support for IDN (international domain names), + which is necessary for OpenID urls with unicode characters in the domain/host name. + It is also required to put the Uri class into RFC 3986 escaping mode, which OpenID and OAuth require. --> + <uri> + <idn enabled="All"/> + <iriParsing enabled="true"/> + </uri> + + <system.net> + <defaultProxy enabled="true" /> + <settings> + <!-- This setting causes .NET to check certificate revocation lists (CRL) + before trusting HTTPS certificates. But this setting tends to not + be allowed in shared hosting environments. --> + <!--<servicePointManager checkCertificateRevocationList="true"/>--> + </settings> + </system.net> + + <!-- this is an optional configuration section where aspects of dotnetopenauth can be customized --> + <dotNetOpenAuth> + <!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. --> + <reporting enabled="true" /> + <messaging> + <untrustedWebRequest> + <whitelistHosts> + <add name="localhost"/> + </whitelistHosts> + </untrustedWebRequest> + </messaging> + </dotNetOpenAuth> + + <appSettings/> + <connectionStrings> + <add name="DatabaseConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True" + providerName="System.Data.SqlClient" /> + </connectionStrings> + + <system.web> + <!-- + Set compilation debug="true" to insert debugging + symbols into the compiled page. Because this + affects performance, set this value to true only + during development. + --> + <compilation debug="true"> + <assemblies> + <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> + </assemblies> + </compilation> + <authentication mode="Forms"> + <forms name="oauthSP" /> + </authentication> + <pages> + <controls> + <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + </controls> + </pages> + <httpHandlers> + <remove verb="*" path="*.asmx"/> + <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/> + </httpHandlers> + <httpModules> + <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + </httpModules> + </system.web> + <system.codedom> + <compilers> + <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <providerOption name="CompilerVersion" value="v3.5"/> + <providerOption name="WarnAsError" value="false"/> + </compiler> + <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <providerOption name="CompilerVersion" value="v3.5"/> + <providerOption name="OptionInfer" value="true"/> + <providerOption name="WarnAsError" value="false"/> + </compiler> + </compilers> + </system.codedom> + <!-- + The system.webServer section is required for running ASP.NET AJAX under Internet + Information Services 7.0. It is not necessary for previous version of IIS. + --> + <system.webServer> + <validation validateIntegratedModeConfiguration="false"/> + <modules> + <remove name="ScriptModule"/> + <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + </modules> + <handlers> + <remove name="WebServiceHandlerFactory-Integrated"/> + <remove name="ScriptHandlerFactory"/> + <remove name="ScriptHandlerFactoryAppServices"/> + <remove name="ScriptResource"/> + <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> + </handlers> + </system.webServer> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/> + <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/> + <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/> + </dependentAssembly> + </assemblyBinding> + </runtime> + <log4net> + <appender name="TracePageAppender" type="OAuthServiceProvider.Code.TracePageAppender, OAuthServiceProvider"> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date (GMT%date{%z}) [%thread] %-5level %logger - %message%newline"/> + </layout> + </appender> + <!-- Setup the root category, add the appenders and set the default level --> + <root> + <level value="INFO"/> + <!--<appender-ref ref="RollingFileAppender" />--> + <appender-ref ref="TracePageAppender"/> + </root> + <!-- Specify the level for some specific categories --> + <logger name="DotNetOpenAuth"> + <level value="ALL"/> + </logger> + </log4net> + <system.serviceModel> + <behaviors> + <serviceBehaviors> + <behavior name="DataApiBehavior"> + <serviceMetadata httpGetEnabled="true"/> + <serviceDebug includeExceptionDetailInFaults="true"/> + <serviceAuthorization serviceAuthorizationManagerType="OAuthServiceProvider.Code.OAuthAuthorizationManager, OAuthServiceProvider" principalPermissionMode="Custom"/> + </behavior> + </serviceBehaviors> + </behaviors> + <services> + <service behaviorConfiguration="DataApiBehavior" name="OAuthServiceProvider.DataApi"> + <endpoint address="" binding="wsHttpBinding" contract="OAuthServiceProvider.Code.IDataApi"> + <identity> + <dns value="localhost"/> + </identity> + </endpoint> + <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> + </service> + </services> + </system.serviceModel> +</configuration> diff --git a/samples/OAuthServiceProvider/favicon.ico b/samples/OAuthServiceProvider/favicon.ico Binary files differnew file mode 100644 index 0000000..e227dbe --- /dev/null +++ b/samples/OAuthServiceProvider/favicon.ico diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln index 505ce7e..708a9b0 100644 --- a/src/DotNetOpenAuth.sln +++ b/src/DotNetOpenAuth.sln @@ -202,6 +202,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Combinations", "Combination EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenIdInfoCard.UI", "DotNetOpenAuth.OpenIdInfoCard.UI\DotNetOpenAuth.OpenIdInfoCard.UI.csproj", "{3A8347E8-59A5-4092-8842-95C75D7D2F36}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OAuth1", "OAuth1", "{2DA24D4F-6918-43CF-973C-BC9D818F8E90}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthConsumer", "..\samples\OAuthConsumer\OAuthConsumer.csproj", "{2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthServiceProvider", "..\samples\OAuthServiceProvider\OAuthServiceProvider.csproj", "{CAA2408C-6918-4902-A512-58BCD62216C3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution CodeAnalysis|Any CPU = CodeAnalysis|Any CPU @@ -529,6 +535,22 @@ Global {3A8347E8-59A5-4092-8842-95C75D7D2F36}.Release|Any CPU.Build.0 = Release|Any CPU {3A8347E8-59A5-4092-8842-95C75D7D2F36}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU {3A8347E8-59A5-4092-8842-95C75D7D2F36}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.Release|Any CPU.Build.0 = Release|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.Release|Any CPU.Build.0 = Release|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -539,6 +561,7 @@ Global {1E2CBAA5-60A3-4AED-912E-541F5753CDC6} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} {8A5CEDB9-7F8A-4BE2-A1B9-97130F453277} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} {AA78D112-D889-414B-A7D4-467B34C7B663} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} + {2DA24D4F-6918-43CF-973C-BC9D818F8E90} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} {2A59DE0A-B76A-4B42-9A33-04D34548353D} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} {AEA29D4D-396F-47F6-BC81-B58D4B855245} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} @@ -583,5 +606,7 @@ Global {A1A3150A-7B0E-4A34-8E35-045296CD3C76} = {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B} = {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} {3A8347E8-59A5-4092-8842-95C75D7D2F36} = {57A7DD35-666C-4FA3-9A1B-38961E50CA27} + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D} = {2DA24D4F-6918-43CF-973C-BC9D818F8E90} + {CAA2408C-6918-4902-A512-58BCD62216C3} = {2DA24D4F-6918-43CF-973C-BC9D818F8E90} EndGlobalSection EndGlobal |