summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2008-10-06 08:04:30 -0700
committerAndrew <andrewarnott@gmail.com>2008-10-06 08:04:30 -0700
commitf367f68a81e06dcab56348c85f7c09526123c916 (patch)
treec06ead228b7eb588ab783025ed05f816f5af5ee4
parent5e8d26c757a32e3c0237b447d142a3de071fa992 (diff)
downloadDotNetOpenAuth-f367f68a81e06dcab56348c85f7c09526123c916.zip
DotNetOpenAuth-f367f68a81e06dcab56348c85f7c09526123c916.tar.gz
DotNetOpenAuth-f367f68a81e06dcab56348c85f7c09526123c916.tar.bz2
WCF OAuth sample now has 'real' database and login.
-rw-r--r--.gitignore1
-rw-r--r--samples/Consumer/App_WebReferences/SampleServiceProvider/DataApi1.xsd2
-rw-r--r--samples/Consumer/SampleWcf.aspx.cs4
-rw-r--r--samples/ServiceProvider/App_Code/Constants.cs4
-rw-r--r--samples/ServiceProvider/App_Code/DataApi.cs15
-rw-r--r--samples/ServiceProvider/App_Code/DataClasses.dbml44
-rw-r--r--samples/ServiceProvider/App_Code/DataClasses.dbml.layout51
-rw-r--r--samples/ServiceProvider/App_Code/DataClasses.designer.cs899
-rw-r--r--samples/ServiceProvider/App_Code/DatabaseTokenManager.cs115
-rw-r--r--samples/ServiceProvider/App_Code/Global.cs112
-rw-r--r--samples/ServiceProvider/App_Code/IDataApi.cs2
-rw-r--r--samples/ServiceProvider/App_Code/InMemoryTokenManager.cs91
-rw-r--r--samples/ServiceProvider/App_Code/Logging.cs20
-rw-r--r--samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs5
-rw-r--r--samples/ServiceProvider/App_Code/TokenAuthorizationState.cs13
-rw-r--r--samples/ServiceProvider/App_Code/TracePageAppender.cs2
-rw-r--r--samples/ServiceProvider/App_Data/Database.mdfbin0 -> 1769472 bytes
-rw-r--r--samples/ServiceProvider/Authorize.aspx20
-rw-r--r--samples/ServiceProvider/Authorize.aspx.cs17
-rw-r--r--samples/ServiceProvider/AuthorizedConsumers.aspx5
-rw-r--r--samples/ServiceProvider/Global.asax37
-rw-r--r--samples/ServiceProvider/Login.aspx6
-rw-r--r--samples/ServiceProvider/Members/Authorize.aspx32
-rw-r--r--samples/ServiceProvider/Members/Authorize.aspx.cs38
-rw-r--r--samples/ServiceProvider/Members/AuthorizedConsumers.aspx7
-rw-r--r--samples/ServiceProvider/Members/AuthorizedConsumers.aspx.cs (renamed from samples/ServiceProvider/AuthorizedConsumers.aspx.cs)0
-rw-r--r--samples/ServiceProvider/Members/Logoff.aspx8
-rw-r--r--samples/ServiceProvider/Members/Web.config8
-rw-r--r--samples/ServiceProvider/OAuth.ashx9
-rw-r--r--samples/ServiceProvider/TracePage.aspx.cs4
-rw-r--r--samples/ServiceProvider/Web.config28
-rw-r--r--src/DotNetOAuth/ChannelElements/ITokenManager.cs6
32 files changed, 1373 insertions, 232 deletions
diff --git a/.gitignore b/.gitignore
index 5a7177b..6acd1eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ TestResult.xml
drops
*.VisualState.xml
StyleCop.Cache
+*.LDF
diff --git a/samples/Consumer/App_WebReferences/SampleServiceProvider/DataApi1.xsd b/samples/Consumer/App_WebReferences/SampleServiceProvider/DataApi1.xsd
index 43c8d9b..3d653c3 100644
--- a/samples/Consumer/App_WebReferences/SampleServiceProvider/DataApi1.xsd
+++ b/samples/Consumer/App_WebReferences/SampleServiceProvider/DataApi1.xsd
@@ -8,7 +8,7 @@
<xs:element name="GetAgeResponse">
<xs:complexType>
<xs:sequence>
- <xs:element minOccurs="0" name="GetAgeResult" type="xs:int" />
+ <xs:element minOccurs="0" name="GetAgeResult" nillable="true" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
diff --git a/samples/Consumer/SampleWcf.aspx.cs b/samples/Consumer/SampleWcf.aspx.cs
index 1e03669..c1e0209 100644
--- a/samples/Consumer/SampleWcf.aspx.cs
+++ b/samples/Consumer/SampleWcf.aspx.cs
@@ -35,8 +35,8 @@ public partial class SampleWcf : System.Web.UI.Page {
}
protected void getAgeButton_Click(object sender, EventArgs e) {
- int age = CallService(client => client.GetAge());
- ageLabel.Text = age.ToString(CultureInfo.CurrentCulture);
+ int? age = CallService(client => client.GetAge());
+ ageLabel.Text = age.HasValue ? age.Value.ToString(CultureInfo.CurrentCulture) : "not available";
}
private T CallService<T>(Func<DataApiClient, T> predicate) {
diff --git a/samples/ServiceProvider/App_Code/Constants.cs b/samples/ServiceProvider/App_Code/Constants.cs
index 7965dc0..8ab6729 100644
--- a/samples/ServiceProvider/App_Code/Constants.cs
+++ b/samples/ServiceProvider/App_Code/Constants.cs
@@ -7,8 +7,6 @@ using DotNetOAuth.Messaging;
/// Service Provider definitions.
/// </summary>
public static class Constants {
- public static InMemoryTokenManager TokenManager { get; set; }
-
public static Uri WebRootUrl { get; set; }
public static ServiceProviderDescription SelfDescription {
@@ -27,6 +25,6 @@ public static class Constants {
}
public static ServiceProvider CreateServiceProvider() {
- return new ServiceProvider(SelfDescription, TokenManager);
+ return new ServiceProvider(SelfDescription, Global.TokenManager);
}
}
diff --git a/samples/ServiceProvider/App_Code/DataApi.cs b/samples/ServiceProvider/App_Code/DataApi.cs
index 1a7555c..43f402a 100644
--- a/samples/ServiceProvider/App_Code/DataApi.cs
+++ b/samples/ServiceProvider/App_Code/DataApi.cs
@@ -1,14 +1,17 @@
-using System.Globalization;
+using System.Linq;
+using System.Globalization;
using System.ServiceModel;
public class DataApi : IDataApi {
- public int GetAge() {
- return 5;
+ public int? GetAge() {
+ return AccessToken.User.Age;
}
public string GetName() {
- string consumerKey = OperationContext.Current.IncomingMessageProperties["OAuthConsumerKey"] as string;
- string accessToken = OperationContext.Current.IncomingMessageProperties["OAuthAccessToken"] as string;
- return string.Format(CultureInfo.InvariantCulture, "Andrew_{0}_{1}", consumerKey.Substring(0, 1), accessToken.Substring(0, 1));
+ return AccessToken.User.FullName;
+ }
+
+ private static OAuthToken AccessToken {
+ get { return OperationContext.Current.IncomingMessageProperties["OAuthAccessToken"] as OAuthToken; }
}
}
diff --git a/samples/ServiceProvider/App_Code/DataClasses.dbml b/samples/ServiceProvider/App_Code/DataClasses.dbml
new file mode 100644
index 0000000..8fac02c
--- /dev/null
+++ b/samples/ServiceProvider/App_Code/DataClasses.dbml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Database Name="Database" 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" />
+ <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="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" />
+ <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>
+</Database> \ No newline at end of file
diff --git a/samples/ServiceProvider/App_Code/DataClasses.dbml.layout b/samples/ServiceProvider/App_Code/DataClasses.dbml.layout
new file mode 100644
index 0000000..50eafa2
--- /dev/null
+++ b/samples/ServiceProvider/App_Code/DataClasses.dbml.layout
@@ -0,0 +1,51 @@
+<?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.3862939453124998">
+ <DataClassMoniker Name="/DataClassesDataContext/OAuthConsumer" />
+ <nestedChildShapes>
+ <elementListCompartment Id="464308c4-d112-4448-b0c9-d9b82fb0ca4e" absoluteBounds="0.64, 3.71, 1.9700000000000002, 0.8262939453125" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" />
+ </nestedChildShapes>
+ </classShape>
+ <classShape Id="895ebbc8-8352-4c04-9e53-b8e6c8302d36" absoluteBounds="3.5, 3.125, 2, 2.1554996744791666">
+ <DataClassMoniker Name="/DataClassesDataContext/OAuthToken" />
+ <nestedChildShapes>
+ <elementListCompartment Id="403126d0-3d2a-4af4-b0b8-c489a830bbd4" absoluteBounds="3.515, 3.585, 1.9700000000000002, 1.5954996744791665" 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 : 3.94314697265625); (3.5 : 3.94314697265625)]" 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 : 4.98964680989583); (3.5 : 4.98964680989583)]" 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>
+ </nestedChildShapes>
+</ordesignerObjectsDiagram> \ No newline at end of file
diff --git a/samples/ServiceProvider/App_Code/DataClasses.designer.cs b/samples/ServiceProvider/App_Code/DataClasses.designer.cs
new file mode 100644
index 0000000..b465471
--- /dev/null
+++ b/samples/ServiceProvider/App_Code/DataClasses.designer.cs
@@ -0,0 +1,899 @@
+#pragma warning disable 1591
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.3053
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Data.Linq;
+using System.Data.Linq.Mapping;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+
+
+[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);
+ #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>();
+ }
+ }
+}
+
+[Table(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();
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Association(Name="User_FavoriteSite", Storage="_FavoriteSites", ThisKey="UserId", OtherKey="UserId")]
+ public EntitySet<FavoriteSite> FavoriteSites
+ {
+ get
+ {
+ return this._FavoriteSites;
+ }
+ set
+ {
+ this._FavoriteSites.Assign(value);
+ }
+ }
+
+ [Association(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;
+ }
+}
+
+[Table(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();
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Association(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));
+ }
+ }
+}
+
+[Table(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 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();
+ #endregion
+
+ public OAuthConsumer()
+ {
+ this._OAuthTokens = new EntitySet<OAuthToken>(new Action<OAuthToken>(this.attach_OAuthTokens), new Action<OAuthToken>(this.detach_OAuthTokens));
+ OnCreated();
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Association(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;
+ }
+}
+
+[Table(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 TokenAuthorizationState _State;
+
+ private System.DateTime _IssueDate;
+
+ private int _ConsumerId;
+
+ private System.Nullable<int> _UserId;
+
+ 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(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();
+ #endregion
+
+ public OAuthToken()
+ {
+ this._OAuthConsumer = default(EntityRef<OAuthConsumer>);
+ this._User = default(EntityRef<User>);
+ OnCreated();
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(Storage="_State", DbType="Int NOT NULL", CanBeNull=false)]
+ public TokenAuthorizationState State
+ {
+ get
+ {
+ return this._State;
+ }
+ set
+ {
+ if ((this._State != value))
+ {
+ this.OnStateChanging(value);
+ this.SendPropertyChanging();
+ this._State = value;
+ this.SendPropertyChanged("State");
+ this.OnStateChanged();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Column(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();
+ }
+ }
+ }
+
+ [Association(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");
+ }
+ }
+ }
+
+ [Association(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));
+ }
+ }
+}
+#pragma warning restore 1591
diff --git a/samples/ServiceProvider/App_Code/DatabaseTokenManager.cs b/samples/ServiceProvider/App_Code/DatabaseTokenManager.cs
new file mode 100644
index 0000000..468687d
--- /dev/null
+++ b/samples/ServiceProvider/App_Code/DatabaseTokenManager.cs
@@ -0,0 +1,115 @@
+//-----------------------------------------------------------------------
+// <copyright file="DatabaseTokenManager.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+using System;
+using System.Linq;
+using System.Data.Linq;
+using System.Collections.Generic;
+using System.Diagnostics;
+using DotNetOAuth.ChannelElements;
+
+public class DatabaseTokenManager : ITokenManager {
+ #region ITokenManager Members
+
+ public string GetConsumerSecret(string consumerKey) {
+ var consumerRow = Global.DataContext.OAuthConsumers.SingleOrDefault(
+ consumerCandidate => consumerCandidate.ConsumerKey == consumerKey);
+ if (consumerRow == null) {
+ throw new ArgumentException();
+ }
+
+ return consumerRow.ConsumerSecret;
+ }
+
+ 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(string consumerKey, string requestToken, string requestTokenSecret, IDictionary<string, string> parameters) {
+ var consumer = Global.DataContext.OAuthConsumers.Single(consumerRow => consumerRow.ConsumerKey == consumerKey);
+ OAuthToken newToken = new OAuthToken {
+ OAuthConsumer = consumer,
+ Token = requestToken,
+ TokenSecret = requestTokenSecret,
+ IssueDate = DateTime.UtcNow,
+ };
+
+ Global.DataContext.OAuthTokens.InsertOnSubmit(newToken);
+ }
+
+ /// <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;
+ }
+}
diff --git a/samples/ServiceProvider/App_Code/Global.cs b/samples/ServiceProvider/App_Code/Global.cs
new file mode 100644
index 0000000..fdef34c
--- /dev/null
+++ b/samples/ServiceProvider/App_Code/Global.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Text;
+using System.ServiceModel;
+using DotNetOAuth.Messages;
+
+/// <summary>
+/// Summary description for Global
+/// </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("DotNetOAuth.ConsumerSample");
+
+ 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();
+ }
+ }
+ }
+
+ /// <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 User LoggedInUser {
+ get { return Global.DataContext.Users.SingleOrDefault(user => user.OpenIDClaimedIdentifier == HttpContext.Current.User.Identity.Name); }
+ }
+
+ public static DirectUserToServiceProviderMessage PendingOAuthAuthorization {
+ get { return HttpContext.Current.Session["authrequest"] as DirectUserToServiceProviderMessage; }
+ set { HttpContext.Current.Session["authrequest"] = value; }
+ }
+
+ 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...");
+ Constants.WebRootUrl = new Uri(HttpContext.Current.Request.Url, "/");
+ var tokenManager = new DatabaseTokenManager();
+ Global.TokenManager = tokenManager;
+ }
+
+ 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());
+ }
+
+ private void Application_EndRequest(object sender, EventArgs e) {
+ CommitAndCloseDatabaseIfNecessary();
+ }
+
+ public static void AuthorizePendingRequestToken() {
+ TokenManager.AuthorizeRequestToken(PendingOAuthAuthorization.RequestToken, LoggedInUser);
+ PendingOAuthAuthorization = null;
+ }
+}
diff --git a/samples/ServiceProvider/App_Code/IDataApi.cs b/samples/ServiceProvider/App_Code/IDataApi.cs
index 895dda1..22acde0 100644
--- a/samples/ServiceProvider/App_Code/IDataApi.cs
+++ b/samples/ServiceProvider/App_Code/IDataApi.cs
@@ -8,7 +8,7 @@ using System.Text;
[ServiceContract]
public interface IDataApi {
[OperationContract]
- int GetAge();
+ int? GetAge();
[OperationContract]
string GetName();
diff --git a/samples/ServiceProvider/App_Code/InMemoryTokenManager.cs b/samples/ServiceProvider/App_Code/InMemoryTokenManager.cs
deleted file mode 100644
index 540fd81..0000000
--- a/samples/ServiceProvider/App_Code/InMemoryTokenManager.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="InMemoryTokenManager.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using DotNetOAuth.ChannelElements;
-
-public class InMemoryTokenManager : ITokenManager {
- private Dictionary<string, string> consumersAndSecrets = new Dictionary<string, string>();
- private Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>();
-
- /// <summary>
- /// Request tokens that have been issued, and whether they have been authorized yet.
- /// </summary>
- private Dictionary<string, bool> requestTokens = new Dictionary<string, bool>();
-
- /// <summary>
- /// Access tokens that have been issued and have not yet expired.
- /// </summary>
- private List<string> accessTokens = new List<string>();
-
- #region ITokenManager Members
-
- public string GetConsumerSecret(string consumerKey) {
- return this.consumersAndSecrets[consumerKey];
- }
-
- public string GetTokenSecret(string token) {
- return this.tokensAndSecrets[token];
- }
-
- public void StoreNewRequestToken(string consumerKey, string requestToken, string requestTokenSecret, IDictionary<string, string> parameters) {
- this.tokensAndSecrets[requestToken] = requestTokenSecret;
- this.requestTokens.Add(requestToken, false);
- }
-
- /// <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) {
- return this.requestTokens[requestToken];
- }
-
- public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) {
- Debug.Assert(this.requestTokens[requestToken], "Unauthorized token should not be exchanged for access token.");
- this.requestTokens.Remove(requestToken);
- this.accessTokens.Add(accessToken);
- this.tokensAndSecrets.Remove(requestToken);
- this.tokensAndSecrets[accessToken] = 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) {
- if (this.requestTokens.ContainsKey(token)) {
- return TokenType.RequestToken;
- } else if (this.accessTokens.Contains(token)) {
- return TokenType.AccessToken;
- } else {
- return TokenType.InvalidToken;
- }
- }
-
- #endregion
-
- public void AddConsumer(string key, string secret) {
- this.consumersAndSecrets.Add(key, secret);
- }
-
- public void AuthorizeRequestToken(string requestToken) {
- if (requestToken == null) {
- throw new ArgumentNullException("requestToken");
- }
-
- this.requestTokens[requestToken] = true;
- }
-}
diff --git a/samples/ServiceProvider/App_Code/Logging.cs b/samples/ServiceProvider/App_Code/Logging.cs
deleted file mode 100644
index cba9b4e..0000000
--- a/samples/ServiceProvider/App_Code/Logging.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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("DotNetOAuth.ConsumerSample");
-}
diff --git a/samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs b/samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs
index a53e6b9..2b4e06b 100644
--- a/samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs
+++ b/samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using DotNetOAuth;
@@ -20,8 +21,8 @@ public class OAuthAuthorizationManager : ServiceAuthorizationManager {
ServiceProvider sp = Constants.CreateServiceProvider();
var auth = sp.GetProtectedResourceAuthorization(httpDetails, requestUri);
if (auth != null) {
- operationContext.IncomingMessageProperties["OAuthConsumerKey"] = auth.ConsumerKey;
- operationContext.IncomingMessageProperties["OAuthAccessToken"] = auth.AccessToken;
+ var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken);
+ operationContext.IncomingMessageProperties["OAuthAccessToken"] = accessToken;
return true;
}
diff --git a/samples/ServiceProvider/App_Code/TokenAuthorizationState.cs b/samples/ServiceProvider/App_Code/TokenAuthorizationState.cs
new file mode 100644
index 0000000..bb959c6
--- /dev/null
+++ b/samples/ServiceProvider/App_Code/TokenAuthorizationState.cs
@@ -0,0 +1,13 @@
+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 {
+ UnauthorizedRequestToken = 0,
+ AuthorizedRequestToken = 1,
+ AccessToken = 2,
+}
diff --git a/samples/ServiceProvider/App_Code/TracePageAppender.cs b/samples/ServiceProvider/App_Code/TracePageAppender.cs
index b3b539a..9f536cd 100644
--- a/samples/ServiceProvider/App_Code/TracePageAppender.cs
+++ b/samples/ServiceProvider/App_Code/TracePageAppender.cs
@@ -5,7 +5,7 @@ using System.Web;
public class TracePageAppender : log4net.Appender.AppenderSkeleton {
protected override void Append(log4net.Core.LoggingEvent loggingEvent) {
- StringWriter sw = new StringWriter(Logging.LogMessages);
+ StringWriter sw = new StringWriter(Global.LogMessages);
Layout.Format(sw, loggingEvent);
}
}
diff --git a/samples/ServiceProvider/App_Data/Database.mdf b/samples/ServiceProvider/App_Data/Database.mdf
new file mode 100644
index 0000000..afdba5c
--- /dev/null
+++ b/samples/ServiceProvider/App_Data/Database.mdf
Binary files differ
diff --git a/samples/ServiceProvider/Authorize.aspx b/samples/ServiceProvider/Authorize.aspx
deleted file mode 100644
index 63774e9..0000000
--- a/samples/ServiceProvider/Authorize.aspx
+++ /dev/null
@@ -1,20 +0,0 @@
-<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
- CodeFile="Authorize.aspx.cs" Inherits="Authorize" %>
-
-<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="Server">
- <div style="background-color: Yellow">
- <b>Warning</b>: Never give your login credentials to another web site or application.
- </div>
- <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>
- <asp:Button ID="allowAccessButton" runat="server" Text="Yes" />
- <asp:Button ID="denyAccessButton" runat="server" Text="No" />
- </div>
- <p>If you grant access now, you can revoke it at any time by returning to this page.
- </p>
-</asp:Content>
diff --git a/samples/ServiceProvider/Authorize.aspx.cs b/samples/ServiceProvider/Authorize.aspx.cs
deleted file mode 100644
index aecd831..0000000
--- a/samples/ServiceProvider/Authorize.aspx.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.UI;
-using System.Web.UI.WebControls;
-
-/// <summary>
-/// Conducts the user through a Consumer authorization process.
-/// </summary>
-public partial class Authorize : System.Web.UI.Page {
- protected void Page_Load(object sender, EventArgs e) {
- if (!IsPostBack && false) {
- Response.Redirect("~/AuthorizedConsumers.aspx");
- }
- }
-}
diff --git a/samples/ServiceProvider/AuthorizedConsumers.aspx b/samples/ServiceProvider/AuthorizedConsumers.aspx
deleted file mode 100644
index 13d0f68..0000000
--- a/samples/ServiceProvider/AuthorizedConsumers.aspx
+++ /dev/null
@@ -1,5 +0,0 @@
-<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="AuthorizedConsumers.aspx.cs" Inherits="AuthorizedConsumers" %>
-
-<asp:Content ID="Content2" ContentPlaceHolderID="Body" Runat="Server">
-</asp:Content>
-
diff --git a/samples/ServiceProvider/Global.asax b/samples/ServiceProvider/Global.asax
index ab1280b..e9ae062 100644
--- a/samples/ServiceProvider/Global.asax
+++ b/samples/ServiceProvider/Global.asax
@@ -1,36 +1 @@
-<%@ Application Language="C#" %>
-
-<script RunAt="server">
- void Application_Start(object sender, EventArgs e) {
- log4net.Config.XmlConfigurator.Configure();
- Logging.Logger.Info("Sample starting...");
- Constants.WebRootUrl = new Uri(HttpContext.Current.Request.Url, "/");
- var tokenManager = new InMemoryTokenManager();
- tokenManager.AddConsumer("sampleconsumer", "samplesecret");
- Constants.TokenManager = tokenManager;
- }
-
- 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();
- }
-
- void Application_Error(object sender, EventArgs e) {
- // Code that runs when an unhandled error occurs
-
- }
-
- void Session_Start(object sender, EventArgs e) {
- // Code that runs when a new session is started
-
- }
-
- 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.
-
- }
-</script>
+<%@ Application Inherits="Global" CodeBehind="App_Code\Global.cs" %> \ No newline at end of file
diff --git a/samples/ServiceProvider/Login.aspx b/samples/ServiceProvider/Login.aspx
new file mode 100644
index 0000000..b2d6f6d
--- /dev/null
+++ b/samples/ServiceProvider/Login.aspx
@@ -0,0 +1,6 @@
+<%@ Page Title="Login" Language="C#" MasterPageFile="~/MasterPage.master" %>
+<%@ Register Assembly="DotNetOpenId" Namespace="DotNetOpenId.RelyingParty" TagPrefix="rp" %>
+
+<asp:Content ID="Content2" ContentPlaceHolderID="Body" Runat="Server">
+ <rp:OpenIdLogin runat="server" TabIndex='1' />
+</asp:Content>
diff --git a/samples/ServiceProvider/Members/Authorize.aspx b/samples/ServiceProvider/Members/Authorize.aspx
new file mode 100644
index 0000000..067645d
--- /dev/null
+++ b/samples/ServiceProvider/Members/Authorize.aspx
@@ -0,0 +1,32 @@
+<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
+ CodeFile="Authorize.aspx.cs" Inherits="Authorize" %>
+
+<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>
+ <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>
+ <asp:Button ID="allowAccessButton" runat="server" Text="Yes" OnClick="allowAccessButton_Click" />
+ <asp:Button ID="denyAccessButton" runat="server" Text="No"
+ onclick="denyAccessButton_Click" />
+ </div>
+ <p>If you grant access now, you can revoke it at any time by returning to this page.
+ </p>
+ </asp:View>
+ <asp:View runat="server">
+ <p>Authorization has been granted. Please inform the consumer application or web site
+ of this. </p>
+ </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/ServiceProvider/Members/Authorize.aspx.cs b/samples/ServiceProvider/Members/Authorize.aspx.cs
new file mode 100644
index 0000000..02834cb
--- /dev/null
+++ b/samples/ServiceProvider/Members/Authorize.aspx.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using DotNetOAuth;
+
+/// <summary>
+/// Conducts the user through a Consumer authorization process.
+/// </summary>
+public partial class Authorize : System.Web.UI.Page {
+ protected void Page_Load(object sender, EventArgs e) {
+ if (!IsPostBack) {
+ if (Global.PendingOAuthAuthorization == null) {
+ Response.Redirect("~/Members/AuthorizedConsumers.aspx");
+ } else {
+ desiredAccessLabel.Text = "name and age";
+ }
+ }
+ }
+
+ protected void allowAccessButton_Click(object sender, EventArgs e) {
+ var pending = Global.PendingOAuthAuthorization;
+ Global.AuthorizePendingRequestToken();
+ multiView.ActiveViewIndex = 1;
+
+ ServiceProvider sp = new ServiceProvider(Constants.SelfDescription, Global.TokenManager);
+ var response = sp.SendAuthorizationResponse(pending);
+ if (response != null) {
+ response.Send();
+ }
+ }
+ protected void denyAccessButton_Click(object sender, EventArgs e) {
+ // erase the request token.
+ multiView.ActiveViewIndex = 2;
+ }
+}
diff --git a/samples/ServiceProvider/Members/AuthorizedConsumers.aspx b/samples/ServiceProvider/Members/AuthorizedConsumers.aspx
new file mode 100644
index 0000000..fb59ccf
--- /dev/null
+++ b/samples/ServiceProvider/Members/AuthorizedConsumers.aspx
@@ -0,0 +1,7 @@
+<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
+ CodeFile="AuthorizedConsumers.aspx.cs" Inherits="AuthorizedConsumers" %>
+
+<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/ServiceProvider/AuthorizedConsumers.aspx.cs b/samples/ServiceProvider/Members/AuthorizedConsumers.aspx.cs
index 1fb4e95..1fb4e95 100644
--- a/samples/ServiceProvider/AuthorizedConsumers.aspx.cs
+++ b/samples/ServiceProvider/Members/AuthorizedConsumers.aspx.cs
diff --git a/samples/ServiceProvider/Members/Logoff.aspx b/samples/ServiceProvider/Members/Logoff.aspx
new file mode 100644
index 0000000..77aa2e5
--- /dev/null
+++ b/samples/ServiceProvider/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/ServiceProvider/Members/Web.config b/samples/ServiceProvider/Members/Web.config
new file mode 100644
index 0000000..3e43df5
--- /dev/null
+++ b/samples/ServiceProvider/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/ServiceProvider/OAuth.ashx b/samples/ServiceProvider/OAuth.ashx
index f6694bc..55cd10c 100644
--- a/samples/ServiceProvider/OAuth.ashx
+++ b/samples/ServiceProvider/OAuth.ashx
@@ -1,6 +1,7 @@
<%@ WebHandler Language="C#" Class="OAuth" %>
using System;
+using System.Linq;
using System.Web;
using System.Web.SessionState;
using DotNetOAuth;
@@ -12,7 +13,7 @@ public class OAuth : IHttpHandler, IRequiresSessionState {
ServiceProvider sp;
public OAuth() {
- sp = new ServiceProvider(Constants.SelfDescription, Constants.TokenManager);
+ sp = new ServiceProvider(Constants.SelfDescription, Global.TokenManager);
}
public void ProcessRequest(HttpContext context) {
@@ -23,10 +24,8 @@ public class OAuth : IHttpHandler, IRequiresSessionState {
if ((requestToken = request as RequestTokenMessage) != null) {
sp.SendUnauthorizedTokenResponse(requestToken, null).Send();
} else if ((requestAuth = request as DirectUserToServiceProviderMessage) != null) {
- HttpContext.Current.Session["authrequest"] = requestAuth;
- //HttpContext.Current.Response.Redirect("~/authorize.aspx");
- Constants.TokenManager.AuthorizeRequestToken(requestAuth.RequestToken);
- sp.SendAuthorizationResponse(requestAuth).Send();
+ Global.PendingOAuthAuthorization = requestAuth;
+ HttpContext.Current.Response.Redirect("~/Members/Authorize.aspx");
} else if ((requestAccessToken = request as RequestAccessTokenMessage) != null) {
sp.SendAccessToken(requestAccessToken, null).Send();
} else {
diff --git a/samples/ServiceProvider/TracePage.aspx.cs b/samples/ServiceProvider/TracePage.aspx.cs
index 47e217b..d1b0231 100644
--- a/samples/ServiceProvider/TracePage.aspx.cs
+++ b/samples/ServiceProvider/TracePage.aspx.cs
@@ -9,11 +9,11 @@ using System.Web.UI.WebControls;
/// </summary>
public partial class TracePage : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
- placeHolder1.Controls.Add(new Label { Text = Logging.LogMessages.ToString() });
+ placeHolder1.Controls.Add(new Label { Text = Global.LogMessages.ToString() });
}
protected void clearLogButton_Click(object sender, EventArgs e) {
- Logging.LogMessages.Length = 0;
+ Global.LogMessages.Length = 0;
// clear the page immediately, and allow for F5 without a Postback warning.
Response.Redirect(Request.Url.AbsoluteUri);
diff --git a/samples/ServiceProvider/Web.config b/samples/ServiceProvider/Web.config
index 01abfbd..af86e8c 100644
--- a/samples/ServiceProvider/Web.config
+++ b/samples/ServiceProvider/Web.config
@@ -15,7 +15,10 @@
</sectionGroup>
</configSections>
<appSettings/>
- <connectionStrings/>
+ <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
@@ -29,26 +32,11 @@
<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"/>
- </assemblies>
+ <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/></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>
- -->
+ <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"/>
diff --git a/src/DotNetOAuth/ChannelElements/ITokenManager.cs b/src/DotNetOAuth/ChannelElements/ITokenManager.cs
index 9c61bc4..db1766d 100644
--- a/src/DotNetOAuth/ChannelElements/ITokenManager.cs
+++ b/src/DotNetOAuth/ChannelElements/ITokenManager.cs
@@ -19,6 +19,11 @@ namespace DotNetOAuth.ChannelElements {
/// </summary>
/// <param name="consumerKey">The Consumer Key.</param>
/// <returns>The Consumer Secret.</returns>
+ /// <exception cref="ArgumentException">Thrown if the consumer key cannot be found.</exception>
+ /// <remarks>
+ /// TODO: In the case of RSA hashing, the consumer may not have a secret
+ /// like this. What to do in that case?
+ /// </remarks>
string GetConsumerSecret(string consumerKey);
/// <summary>
@@ -37,6 +42,7 @@ namespace DotNetOAuth.ChannelElements {
/// <param name="requestToken">The token to store.</param>
/// <param name="requestTokenSecret">The secret to store as associated with the request token.</param>
/// <param name="parameters">The optional application-specific parameters of this request.</param>
+ /// <exception cref="ArgumentException">Thrown if the consumer key is not registered, or a required parameter was not found in the parameters collection.</exception>
void StoreNewRequestToken(string consumerKey, string requestToken, string requestTokenSecret, IDictionary<string, string> parameters);
/// <summary>