summaryrefslogtreecommitdiffstats
path: root/projecttemplates/RelyingPartyLogic
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-11-13 17:04:21 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2009-11-13 17:04:21 -0800
commite778892f1d9bf964c30ba6a10e50aedf12c2e857 (patch)
tree73ef8790efd0348348fb64e6cf8d438932635016 /projecttemplates/RelyingPartyLogic
parent888abd61a54576ff244533693df77f174f03c2bb (diff)
downloadDotNetOpenAuth-e778892f1d9bf964c30ba6a10e50aedf12c2e857.zip
DotNetOpenAuth-e778892f1d9bf964c30ba6a10e50aedf12c2e857.tar.gz
DotNetOpenAuth-e778892f1d9bf964c30ba6a10e50aedf12c2e857.tar.bz2
Moved all the project template logic that would be common between MVC and web forms web sites into its own library.
Diffstat (limited to 'projecttemplates/RelyingPartyLogic')
-rw-r--r--projecttemplates/RelyingPartyLogic/CreateDatabase.sql197
-rw-r--r--projecttemplates/RelyingPartyLogic/DataRoleProvider.cs123
-rw-r--r--projecttemplates/RelyingPartyLogic/Database.cs150
-rw-r--r--projecttemplates/RelyingPartyLogic/Model.AuthenticationToken.cs21
-rw-r--r--projecttemplates/RelyingPartyLogic/Model.Consumer.cs40
-rw-r--r--projecttemplates/RelyingPartyLogic/Model.Designer.cs1168
-rw-r--r--projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs58
-rw-r--r--projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs56
-rw-r--r--projecttemplates/RelyingPartyLogic/Model.User.cs19
-rw-r--r--projecttemplates/RelyingPartyLogic/Model.edmx404
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs78
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs67
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs48
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs53
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs120
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs112
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthTokenManager.cs143
-rw-r--r--projecttemplates/RelyingPartyLogic/Policies.cs23
-rw-r--r--projecttemplates/RelyingPartyLogic/Properties/AssemblyInfo.cs36
-rw-r--r--projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj131
-rw-r--r--projecttemplates/RelyingPartyLogic/Utilities.cs64
21 files changed, 3111 insertions, 0 deletions
diff --git a/projecttemplates/RelyingPartyLogic/CreateDatabase.sql b/projecttemplates/RelyingPartyLogic/CreateDatabase.sql
new file mode 100644
index 0000000..52ca669
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/CreateDatabase.sql
@@ -0,0 +1,197 @@
+SET ANSI_NULLS ON
+GO
+SET QUOTED_IDENTIFIER ON
+GO
+CREATE TABLE [dbo].[Consumer](
+ [ConsumerId] [int] IDENTITY(1,1) NOT NULL,
+ [ConsumerKey] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL,
+ [ConsumerSecret] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ [X509Certificate] [image] NULL,
+ [Callback] [nvarchar](2048) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ [VerificationCodeFormat] [int] NOT NULL,
+ [VerificationCodeLength] [int] NOT NULL,
+ [Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ CONSTRAINT [PK_Consumer] PRIMARY KEY CLUSTERED
+(
+ [ConsumerId] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
+GO
+CREATE UNIQUE NONCLUSTERED INDEX [IX_Consumer] ON [dbo].[Consumer]
+(
+ [ConsumerKey] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+GO
+SET ANSI_NULLS ON
+GO
+SET QUOTED_IDENTIFIER ON
+GO
+CREATE TABLE [dbo].[User](
+ [Id] [int] IDENTITY(1,1) NOT NULL,
+ [FirstName] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ [LastName] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ [EmailAddress] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ [EmailAddressVerified] [bit] NOT NULL,
+ CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
+(
+ [Id] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+) ON [PRIMARY]
+GO
+SET ANSI_NULLS ON
+GO
+SET QUOTED_IDENTIFIER ON
+GO
+CREATE TABLE [dbo].[Role](
+ [Id] [int] IDENTITY(1,1) NOT NULL,
+ [Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
+ CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED
+(
+ [Id] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+) ON [PRIMARY]
+GO
+SET ANSI_NULLS ON
+GO
+SET QUOTED_IDENTIFIER ON
+GO
+SET ANSI_PADDING ON
+GO
+CREATE TABLE [dbo].[IssuedToken](
+ [TokenId] [int] IDENTITY(1,1) NOT NULL,
+ [ConsumerId] [int] NOT NULL,
+ [UserId] [int] NULL,
+ [Token] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL,
+ [TokenSecret] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL,
+ [CreatedOn] [datetime] NOT NULL,
+ [Callback] [nvarchar](2048) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ [VerificationCode] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ [ConsumerVersion] [varchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ [ExpirationDate] [datetime] NULL,
+ [IsAccessToken] [bit] NOT NULL,
+ [Scope] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ CONSTRAINT [PK_IssuedToken] PRIMARY KEY CLUSTERED
+(
+ [TokenId] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+) ON [PRIMARY]
+GO
+SET ANSI_PADDING OFF
+GO
+CREATE UNIQUE NONCLUSTERED INDEX [IX_IssuedToken] ON [dbo].[IssuedToken]
+(
+ [Token] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+GO
+SET ANSI_NULLS ON
+GO
+SET QUOTED_IDENTIFIER ON
+GO
+CREATE TABLE [dbo].[UserRole](
+ [UserId] [int] NOT NULL,
+ [RoleId] [int] NOT NULL,
+ CONSTRAINT [PK_UserRole] PRIMARY KEY CLUSTERED
+(
+ [UserId] ASC,
+ [RoleId] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+) ON [PRIMARY]
+GO
+SET ANSI_NULLS ON
+GO
+SET QUOTED_IDENTIFIER ON
+GO
+CREATE TABLE [dbo].[AuthenticationToken](
+ [Id] [int] IDENTITY(1,1) NOT NULL,
+ [UserId] [int] NOT NULL,
+ [OpenIdClaimedIdentifier] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL,
+ [OpenIdFriendlyIdentifier] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
+ CONSTRAINT [PK_AuthenticationToken] PRIMARY KEY CLUSTERED
+(
+ [Id] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+) ON [PRIMARY]
+GO
+SET ANSI_NULLS ON
+GO
+SET QUOTED_IDENTIFIER ON
+GO
+CREATE PROCEDURE [dbo].[AddUser]
+ (
+ @firstName nvarchar(50),
+ @lastName nvarchar(50),
+ @openid nvarchar(255),
+ @role nvarchar(255)
+ )
+AS
+ DECLARE
+ @roleid int,
+ @userid int
+
+ BEGIN TRANSACTION
+
+ INSERT INTO [dbo].[User] (FirstName, LastName) VALUES (@firstName, @lastName)
+ SET @userid = (SELECT @@IDENTITY)
+
+ IF (SELECT COUNT(*) FROM dbo.Role WHERE [Name] = @role) = 0
+ BEGIN
+ INSERT INTO dbo.Role (Name) VALUES (@role)
+ SET @roleid = (SELECT @@IDENTITY)
+ END
+ ELSE
+ BEGIN
+ SET @roleid = (SELECT Id FROM dbo.Role WHERE [Name] = @role)
+ END
+
+ INSERT INTO dbo.UserRole (UserId, RoleId) VALUES (@userId, @roleid)
+
+ INSERT INTO dbo.AuthenticationToken
+ (UserId, OpenIdClaimedIdentifier, OpenIdFriendlyIdentifier)
+ VALUES
+ (@userid, @openid, @openid)
+
+ COMMIT TRANSACTION
+
+ RETURN @userid
+GO
+ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_EmailAddressVerified] DEFAULT ((0)) FOR [EmailAddressVerified]
+GO
+ALTER TABLE [dbo].[IssuedToken] ADD CONSTRAINT [DF_IssuedToken_CreatedOn] DEFAULT (getdate()) FOR [CreatedOn]
+GO
+ALTER TABLE [dbo].[IssuedToken] ADD CONSTRAINT [DF_IssuedToken_IsAccessToken] DEFAULT ((0)) FOR [IsAccessToken]
+GO
+ALTER TABLE [dbo].[IssuedToken] WITH CHECK ADD CONSTRAINT [FK_IssuedToken_Consumer] FOREIGN KEY([ConsumerId])
+REFERENCES [dbo].[Consumer] ([ConsumerId])
+ON UPDATE CASCADE
+ON DELETE CASCADE
+GO
+ALTER TABLE [dbo].[IssuedToken] CHECK CONSTRAINT [FK_IssuedToken_Consumer]
+GO
+ALTER TABLE [dbo].[IssuedToken] WITH CHECK ADD CONSTRAINT [FK_IssuedToken_User] FOREIGN KEY([UserId])
+REFERENCES [dbo].[User] ([Id])
+ON UPDATE CASCADE
+ON DELETE CASCADE
+GO
+ALTER TABLE [dbo].[IssuedToken] CHECK CONSTRAINT [FK_IssuedToken_User]
+GO
+ALTER TABLE [dbo].[UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_Role] FOREIGN KEY([RoleId])
+REFERENCES [dbo].[Role] ([Id])
+ON UPDATE CASCADE
+ON DELETE CASCADE
+GO
+ALTER TABLE [dbo].[UserRole] CHECK CONSTRAINT [FK_UserRole_Role]
+GO
+ALTER TABLE [dbo].[UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_User] FOREIGN KEY([UserId])
+REFERENCES [dbo].[User] ([Id])
+ON UPDATE CASCADE
+ON DELETE CASCADE
+GO
+ALTER TABLE [dbo].[UserRole] CHECK CONSTRAINT [FK_UserRole_User]
+GO
+ALTER TABLE [dbo].[AuthenticationToken] WITH CHECK ADD CONSTRAINT [FK_AuthenticationToken_User] FOREIGN KEY([UserId])
+REFERENCES [dbo].[User] ([Id])
+ON UPDATE CASCADE
+ON DELETE CASCADE
+GO
+ALTER TABLE [dbo].[AuthenticationToken] CHECK CONSTRAINT [FK_AuthenticationToken_User]
+GO
diff --git a/projecttemplates/RelyingPartyLogic/DataRoleProvider.cs b/projecttemplates/RelyingPartyLogic/DataRoleProvider.cs
new file mode 100644
index 0000000..1171646
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/DataRoleProvider.cs
@@ -0,0 +1,123 @@
+//-----------------------------------------------------------------------
+// <copyright file="DataRoleProvider.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using System.Web.Security;
+
+ public class DataRoleProvider : RoleProvider {
+ public override string ApplicationName {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+
+ public override void AddUsersToRoles(string[] usernames, string[] roleNames) {
+ var users = from token in Database.DataContext.AuthenticationToken
+ where usernames.Contains(token.ClaimedIdentifier)
+ select token.User;
+ var roles = from role in Database.DataContext.Role
+ where roleNames.Contains(role.Name, StringComparer.OrdinalIgnoreCase)
+ select role;
+ foreach (User user in users) {
+ foreach (Role role in roles) {
+ user.Roles.Add(role);
+ }
+ }
+ }
+
+ public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) {
+ var users = from token in Database.DataContext.AuthenticationToken
+ where usernames.Contains(token.ClaimedIdentifier)
+ select token.User;
+ var roles = from role in Database.DataContext.Role
+ where roleNames.Contains(role.Name, StringComparer.OrdinalIgnoreCase)
+ select role;
+ foreach (User user in users) {
+ foreach (Role role in roles) {
+ user.Roles.Remove(role);
+ }
+ }
+ }
+
+ public override void CreateRole(string roleName) {
+ Database.DataContext.AddToRole(new Role { Name = roleName });
+ }
+
+ /// <summary>
+ /// Removes a role from the data source for the configured applicationName.
+ /// </summary>
+ /// <param name="roleName">The name of the role to delete.</param>
+ /// <param name="throwOnPopulatedRole">If true, throw an exception if <paramref name="roleName"/> has one or more members and do not delete <paramref name="roleName"/>.</param>
+ /// <returns>
+ /// true if the role was successfully deleted; otherwise, false.
+ /// </returns>
+ public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) {
+ Role role = Database.DataContext.Role.SingleOrDefault(r => r.Name == roleName);
+ if (role == null) {
+ return false;
+ }
+
+ if (throwOnPopulatedRole && role.Users.Count > 0) {
+ throw new InvalidOperationException();
+ }
+
+ Database.DataContext.DeleteObject(roleName);
+ return true;
+ }
+
+ /// <summary>
+ /// Gets an array of user names in a role where the user name contains the specified user name to match.
+ /// </summary>
+ /// <param name="roleName">The role to search in.</param>
+ /// <param name="usernameToMatch">The user name to search for.</param>
+ /// <returns>
+ /// A string array containing the names of all the users where the user name matches <paramref name="usernameToMatch"/> and the user is a member of the specified role.
+ /// </returns>
+ public override string[] FindUsersInRole(string roleName, string usernameToMatch) {
+ return (from role in Database.DataContext.Role
+ where role.Name == roleName
+ from user in role.Users
+ from authTokens in user.AuthenticationTokens
+ where authTokens.ClaimedIdentifier == usernameToMatch
+ select authTokens.ClaimedIdentifier).ToArray();
+ }
+
+ public override string[] GetAllRoles() {
+ return Database.DataContext.Role.Select(role => role.Name).ToArray();
+ }
+
+ public override string[] GetRolesForUser(string username) {
+ return (from authToken in Database.DataContext.AuthenticationToken
+ where authToken.ClaimedIdentifier == username
+ from role in authToken.User.Roles
+ select role.Name).ToArray();
+ }
+
+ public override string[] GetUsersInRole(string roleName) {
+ return (from role in Database.DataContext.Role
+ where string.Equals(role.Name, roleName, StringComparison.OrdinalIgnoreCase)
+ from user in role.Users
+ from token in user.AuthenticationTokens
+ select token.ClaimedIdentifier).ToArray();
+ }
+
+ public override bool IsUserInRole(string username, string roleName) {
+ Role role = Database.DataContext.Role.SingleOrDefault(r => string.Equals(r.Name, roleName, StringComparison.OrdinalIgnoreCase));
+ if (role != null) {
+ return role.Users.Any(user => user.AuthenticationTokens.Any(token => token.ClaimedIdentifier == username));
+ }
+
+ return false;
+ }
+
+ public override bool RoleExists(string roleName) {
+ return Database.DataContext.Role.Any(role => string.Equals(role.Name, roleName, StringComparison.OrdinalIgnoreCase));
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Database.cs b/projecttemplates/RelyingPartyLogic/Database.cs
new file mode 100644
index 0000000..a1e17a6
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Database.cs
@@ -0,0 +1,150 @@
+//-----------------------------------------------------------------------
+// <copyright file="Database.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Data;
+ using System.Data.SqlClient;
+ using System.Linq;
+ using System.ServiceModel;
+ using System.Text;
+ using System.Web;
+
+ public class Database : IHttpModule, IDisposable {
+ private const string DataContextKey = "DataContext";
+
+ private const string DataContextTransactionKey = "DataContextTransaction";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Database"/> class.
+ /// </summary>
+ public Database() {
+ }
+
+ public static User LoggedInUser {
+ get { return DataContext.AuthenticationToken.Where(token => token.ClaimedIdentifier == HttpContext.Current.User.Identity.Name).Select(token => token.User).FirstOrDefault(); }
+ }
+
+ /// <summary>
+ /// Gets the transaction-protected database connection for the current request.
+ /// </summary>
+ public static DatabaseEntities DataContext {
+ get {
+ DatabaseEntities dataContext = DataContextSimple;
+ if (dataContext == null) {
+ dataContext = new DatabaseEntities();
+ try {
+ dataContext.Connection.Open();
+ } catch (EntityException entityEx) {
+ var sqlEx = entityEx.InnerException as SqlException;
+ if (sqlEx != null) {
+ if (sqlEx.Class == 14 && sqlEx.Number == 15350) {
+ // Most likely the database schema hasn't been created yet.
+ HttpContext.Current.Response.Redirect("~/Setup.aspx");
+ }
+ }
+
+ throw;
+ }
+
+ DataContextTransactionSimple = dataContext.Connection.BeginTransaction();
+ DataContextSimple = dataContext;
+ }
+
+ return dataContext;
+ }
+ }
+
+ private static DatabaseEntities DataContextSimple {
+ get {
+ if (HttpContext.Current != null) {
+ return HttpContext.Current.Items[DataContextKey] as DatabaseEntities;
+ } else if (OperationContext.Current != null) {
+ object data;
+ if (OperationContext.Current.IncomingMessageProperties.TryGetValue(DataContextKey, out data)) {
+ return data as DatabaseEntities;
+ } else {
+ return null;
+ }
+ } else {
+ throw new InvalidOperationException();
+ }
+ }
+
+ set {
+ if (HttpContext.Current != null) {
+ HttpContext.Current.Items[DataContextKey] = value;
+ } else if (OperationContext.Current != null) {
+ OperationContext.Current.IncomingMessageProperties[DataContextKey] = value;
+ } else {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+ private static IDbTransaction DataContextTransactionSimple {
+ get {
+ if (HttpContext.Current != null) {
+ return HttpContext.Current.Items[DataContextTransactionKey] as IDbTransaction;
+ } else if (OperationContext.Current != null) {
+ object data;
+ if (OperationContext.Current.IncomingMessageProperties.TryGetValue(DataContextTransactionKey, out data)) {
+ return data as IDbTransaction;
+ } else {
+ return null;
+ }
+ } else {
+ throw new InvalidOperationException();
+ }
+ }
+
+ set {
+ if (HttpContext.Current != null) {
+ HttpContext.Current.Items[DataContextTransactionKey] = value;
+ } else if (OperationContext.Current != null) {
+ OperationContext.Current.IncomingMessageProperties[DataContextTransactionKey] = value;
+ } else {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+ public void Dispose() {
+ }
+
+ void IHttpModule.Init(HttpApplication context) {
+ context.EndRequest += this.Application_EndRequest;
+ context.Error += this.Application_Error;
+ }
+
+ protected void Application_EndRequest(object sender, EventArgs e) {
+ CommitAndCloseDatabaseIfNecessary();
+ }
+
+ protected void Application_Error(object sender, EventArgs e) {
+ if (DataContextTransactionSimple != null) {
+ DataContextTransactionSimple.Rollback();
+ DataContextTransactionSimple.Dispose();
+ DataContextTransactionSimple = null;
+ }
+ }
+
+ private static void CommitAndCloseDatabaseIfNecessary() {
+ var dataContext = DataContextSimple;
+ if (dataContext != null) {
+ dataContext.SaveChanges();
+ if (DataContextTransactionSimple != null) {
+ DataContextTransactionSimple.Commit();
+ DataContextTransactionSimple.Dispose();
+ }
+
+ dataContext.Dispose();
+ DataContextSimple = null;
+ }
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Model.AuthenticationToken.cs b/projecttemplates/RelyingPartyLogic/Model.AuthenticationToken.cs
new file mode 100644
index 0000000..e44fd83
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Model.AuthenticationToken.cs
@@ -0,0 +1,21 @@
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+
+ public partial class AuthenticationToken {
+ public bool IsInfoCard {
+ get { return this.ClaimedIdentifier.StartsWith(UriPrefixForInfoCard); }
+ }
+
+ private static string UriPrefixForInfoCard {
+ get { return new Uri(Utilities.ApplicationRoot, "infocard/").AbsoluteUri; }
+ }
+
+ public static string SynthesizeClaimedIdentifierFromInfoCard(string uniqueId) {
+ string synthesizedClaimedId = UriPrefixForInfoCard + Uri.EscapeDataString(uniqueId);
+ return synthesizedClaimedId;
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Model.Consumer.cs b/projecttemplates/RelyingPartyLogic/Model.Consumer.cs
new file mode 100644
index 0000000..a09029a
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Model.Consumer.cs
@@ -0,0 +1,40 @@
+//-----------------------------------------------------------------------
+// <copyright file="Model.Consumer.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Security.Cryptography.X509Certificates;
+ using System.Web;
+ using DotNetOpenAuth.OAuth;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ public partial class Consumer : IConsumerDescription {
+ public VerificationCodeFormat VerificationCodeFormat {
+ get { return (VerificationCodeFormat)this.VerificationCodeFormatAsInt; }
+ set { this.VerificationCodeFormatAsInt = (int)value; }
+ }
+
+ public X509Certificate2 Certificate {
+ get { return this.X509CertificateAsBinary != null ? new X509Certificate2(this.X509CertificateAsBinary) : null; }
+ set { this.X509CertificateAsBinary = value != null ? value.RawData : null; }
+ }
+
+ public Uri Callback {
+ get { return this.CallbackAsString != null ? new Uri(this.CallbackAsString) : null; }
+ set { this.CallbackAsString = value != null ? value.AbsoluteUri : null; }
+ }
+
+ string IConsumerDescription.Secret {
+ get { return this.ConsumerSecret; }
+ }
+
+ string IConsumerDescription.Key {
+ get { return this.ConsumerKey; }
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Model.Designer.cs b/projecttemplates/RelyingPartyLogic/Model.Designer.cs
new file mode 100644
index 0000000..d19d305
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Model.Designer.cs
@@ -0,0 +1,1168 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.4927
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+[assembly: global::System.Data.Objects.DataClasses.EdmSchemaAttribute()]
+[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "UserRole", "Role", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.Role), "User", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.User))]
+[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "UserAuthenticationToken", "User", global::System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(RelyingPartyLogic.User), "AuthenticationToken", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.AuthenticationToken))]
+[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "Consumer", global::System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(RelyingPartyLogic.Consumer), "IssuedTokens", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.IssuedToken))]
+[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "FK_IssuedToken_User", "User", global::System.Data.Metadata.Edm.RelationshipMultiplicity.ZeroOrOne, typeof(RelyingPartyLogic.User), "IssuedTokens", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.IssuedToken))]
+
+// Original file name:
+// Generation date: 11/13/2009 4:45:45 PM
+namespace RelyingPartyLogic
+{
+
+ /// <summary>
+ /// There are no comments for DatabaseEntities in the schema.
+ /// </summary>
+ public partial class DatabaseEntities : global::System.Data.Objects.ObjectContext
+ {
+ /// <summary>
+ /// Initializes a new DatabaseEntities object using the connection string found in the 'DatabaseEntities' section of the application configuration file.
+ /// </summary>
+ public DatabaseEntities() :
+ base("name=DatabaseEntities", "DatabaseEntities")
+ {
+ this.OnContextCreated();
+ }
+ /// <summary>
+ /// Initialize a new DatabaseEntities object.
+ /// </summary>
+ public DatabaseEntities(string connectionString) :
+ base(connectionString, "DatabaseEntities")
+ {
+ this.OnContextCreated();
+ }
+ /// <summary>
+ /// Initialize a new DatabaseEntities object.
+ /// </summary>
+ public DatabaseEntities(global::System.Data.EntityClient.EntityConnection connection) :
+ base(connection, "DatabaseEntities")
+ {
+ this.OnContextCreated();
+ }
+ partial void OnContextCreated();
+ /// <summary>
+ /// There are no comments for Role in the schema.
+ /// </summary>
+ public global::System.Data.Objects.ObjectQuery<Role> Role
+ {
+ get
+ {
+ if ((this._Role == null))
+ {
+ this._Role = base.CreateQuery<Role>("[Role]");
+ }
+ return this._Role;
+ }
+ }
+ private global::System.Data.Objects.ObjectQuery<Role> _Role;
+ /// <summary>
+ /// There are no comments for User in the schema.
+ /// </summary>
+ public global::System.Data.Objects.ObjectQuery<User> User
+ {
+ get
+ {
+ if ((this._User == null))
+ {
+ this._User = base.CreateQuery<User>("[User]");
+ }
+ return this._User;
+ }
+ }
+ private global::System.Data.Objects.ObjectQuery<User> _User;
+ /// <summary>
+ /// There are no comments for AuthenticationToken in the schema.
+ /// </summary>
+ public global::System.Data.Objects.ObjectQuery<AuthenticationToken> AuthenticationToken
+ {
+ get
+ {
+ if ((this._AuthenticationToken == null))
+ {
+ this._AuthenticationToken = base.CreateQuery<AuthenticationToken>("[AuthenticationToken]");
+ }
+ return this._AuthenticationToken;
+ }
+ }
+ private global::System.Data.Objects.ObjectQuery<AuthenticationToken> _AuthenticationToken;
+ /// <summary>
+ /// There are no comments for Consumer in the schema.
+ /// </summary>
+ public global::System.Data.Objects.ObjectQuery<Consumer> Consumer
+ {
+ get
+ {
+ if ((this._Consumer == null))
+ {
+ this._Consumer = base.CreateQuery<Consumer>("[Consumer]");
+ }
+ return this._Consumer;
+ }
+ }
+ private global::System.Data.Objects.ObjectQuery<Consumer> _Consumer;
+ /// <summary>
+ /// There are no comments for IssuedToken in the schema.
+ /// </summary>
+ public global::System.Data.Objects.ObjectQuery<IssuedToken> IssuedToken
+ {
+ get
+ {
+ if ((this._IssuedToken == null))
+ {
+ this._IssuedToken = base.CreateQuery<IssuedToken>("[IssuedToken]");
+ }
+ return this._IssuedToken;
+ }
+ }
+ private global::System.Data.Objects.ObjectQuery<IssuedToken> _IssuedToken;
+ /// <summary>
+ /// There are no comments for Role in the schema.
+ /// </summary>
+ public void AddToRole(Role role)
+ {
+ base.AddObject("Role", role);
+ }
+ /// <summary>
+ /// There are no comments for User in the schema.
+ /// </summary>
+ public void AddToUser(User user)
+ {
+ base.AddObject("User", user);
+ }
+ /// <summary>
+ /// There are no comments for AuthenticationToken in the schema.
+ /// </summary>
+ public void AddToAuthenticationToken(AuthenticationToken authenticationToken)
+ {
+ base.AddObject("AuthenticationToken", authenticationToken);
+ }
+ /// <summary>
+ /// There are no comments for Consumer in the schema.
+ /// </summary>
+ public void AddToConsumer(Consumer consumer)
+ {
+ base.AddObject("Consumer", consumer);
+ }
+ /// <summary>
+ /// There are no comments for IssuedToken in the schema.
+ /// </summary>
+ public void AddToIssuedToken(IssuedToken issuedToken)
+ {
+ base.AddObject("IssuedToken", issuedToken);
+ }
+ }
+ /// <summary>
+ /// There are no comments for DatabaseModel.AuthenticationToken in the schema.
+ /// </summary>
+ /// <KeyProperties>
+ /// Id
+ /// </KeyProperties>
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="AuthenticationToken")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ public partial class AuthenticationToken : global::System.Data.Objects.DataClasses.EntityObject
+ {
+ /// <summary>
+ /// Create a new AuthenticationToken object.
+ /// </summary>
+ /// <param name="id">Initial value of Id.</param>
+ /// <param name="claimedIdentifier">Initial value of ClaimedIdentifier.</param>
+ public static AuthenticationToken CreateAuthenticationToken(int id, string claimedIdentifier)
+ {
+ AuthenticationToken authenticationToken = new AuthenticationToken();
+ authenticationToken.Id = id;
+ authenticationToken.ClaimedIdentifier = claimedIdentifier;
+ return authenticationToken;
+ }
+ /// <summary>
+ /// There are no comments for Property Id in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public int Id
+ {
+ get
+ {
+ return this._Id;
+ }
+ set
+ {
+ this.OnIdChanging(value);
+ this.ReportPropertyChanging("Id");
+ this._Id = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("Id");
+ this.OnIdChanged();
+ }
+ }
+ private int _Id;
+ partial void OnIdChanging(int value);
+ partial void OnIdChanged();
+ /// <summary>
+ /// There are no comments for Property ClaimedIdentifier in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string ClaimedIdentifier
+ {
+ get
+ {
+ return this._ClaimedIdentifier;
+ }
+ set
+ {
+ this.OnClaimedIdentifierChanging(value);
+ this.ReportPropertyChanging("ClaimedIdentifier");
+ this._ClaimedIdentifier = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false);
+ this.ReportPropertyChanged("ClaimedIdentifier");
+ this.OnClaimedIdentifierChanged();
+ }
+ }
+ private string _ClaimedIdentifier;
+ partial void OnClaimedIdentifierChanging(string value);
+ partial void OnClaimedIdentifierChanged();
+ /// <summary>
+ /// There are no comments for Property FriendlyIdentifier in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string FriendlyIdentifier
+ {
+ get
+ {
+ return this._FriendlyIdentifier;
+ }
+ set
+ {
+ this.OnFriendlyIdentifierChanging(value);
+ this.ReportPropertyChanging("FriendlyIdentifier");
+ this._FriendlyIdentifier = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("FriendlyIdentifier");
+ this.OnFriendlyIdentifierChanged();
+ }
+ }
+ private string _FriendlyIdentifier;
+ partial void OnFriendlyIdentifierChanging(string value);
+ partial void OnFriendlyIdentifierChanged();
+ /// <summary>
+ /// There are no comments for User in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "UserAuthenticationToken", "User")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public User User
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.UserAuthenticationToken", "User").Value;
+ }
+ set
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.UserAuthenticationToken", "User").Value = value;
+ }
+ }
+ /// <summary>
+ /// There are no comments for User in the schema.
+ /// </summary>
+ [global::System.ComponentModel.BrowsableAttribute(false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityReference<User> UserReference
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.UserAuthenticationToken", "User");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<User>("DatabaseModel.UserAuthenticationToken", "User", value);
+ }
+ }
+ }
+ }
+ /// <summary>
+ /// There are no comments for DatabaseModel.Role in the schema.
+ /// </summary>
+ /// <KeyProperties>
+ /// Id
+ /// </KeyProperties>
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="Role")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ public partial class Role : global::System.Data.Objects.DataClasses.EntityObject
+ {
+ /// <summary>
+ /// Create a new Role object.
+ /// </summary>
+ /// <param name="id">Initial value of Id.</param>
+ /// <param name="name">Initial value of Name.</param>
+ public static Role CreateRole(int id, string name)
+ {
+ Role role = new Role();
+ role.Id = id;
+ role.Name = name;
+ return role;
+ }
+ /// <summary>
+ /// There are no comments for Property Id in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public int Id
+ {
+ get
+ {
+ return this._Id;
+ }
+ private set
+ {
+ this.OnIdChanging(value);
+ this.ReportPropertyChanging("Id");
+ this._Id = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("Id");
+ this.OnIdChanged();
+ }
+ }
+ private int _Id;
+ partial void OnIdChanging(int value);
+ partial void OnIdChanged();
+ /// <summary>
+ /// There are no comments for Property Name in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string Name
+ {
+ get
+ {
+ return this._Name;
+ }
+ set
+ {
+ this.OnNameChanging(value);
+ this.ReportPropertyChanging("Name");
+ this._Name = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false);
+ this.ReportPropertyChanged("Name");
+ this.OnNameChanged();
+ }
+ }
+ private string _Name;
+ partial void OnNameChanging(string value);
+ partial void OnNameChanged();
+ /// <summary>
+ /// There are no comments for Users in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "UserRole", "User")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityCollection<User> Users
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<User>("DatabaseModel.UserRole", "User");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<User>("DatabaseModel.UserRole", "User", value);
+ }
+ }
+ }
+ }
+ /// <summary>
+ /// There are no comments for DatabaseModel.User in the schema.
+ /// </summary>
+ /// <KeyProperties>
+ /// Id
+ /// </KeyProperties>
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="User")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ public partial class User : global::System.Data.Objects.DataClasses.EntityObject
+ {
+ /// <summary>
+ /// Create a new User object.
+ /// </summary>
+ /// <param name="id">Initial value of Id.</param>
+ /// <param name="emailAddressVerified">Initial value of EmailAddressVerified.</param>
+ public static User CreateUser(int id, bool emailAddressVerified)
+ {
+ User user = new User();
+ user.Id = id;
+ user.EmailAddressVerified = emailAddressVerified;
+ return user;
+ }
+ /// <summary>
+ /// There are no comments for Property Id in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public int Id
+ {
+ get
+ {
+ return this._Id;
+ }
+ private set
+ {
+ this.OnIdChanging(value);
+ this.ReportPropertyChanging("Id");
+ this._Id = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("Id");
+ this.OnIdChanged();
+ }
+ }
+ private int _Id;
+ partial void OnIdChanging(int value);
+ partial void OnIdChanged();
+ /// <summary>
+ /// There are no comments for Property FirstName in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string FirstName
+ {
+ get
+ {
+ return this._FirstName;
+ }
+ set
+ {
+ this.OnFirstNameChanging(value);
+ this.ReportPropertyChanging("FirstName");
+ this._FirstName = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("FirstName");
+ this.OnFirstNameChanged();
+ }
+ }
+ private string _FirstName;
+ partial void OnFirstNameChanging(string value);
+ partial void OnFirstNameChanged();
+ /// <summary>
+ /// There are no comments for Property LastName in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string LastName
+ {
+ get
+ {
+ return this._LastName;
+ }
+ set
+ {
+ this.OnLastNameChanging(value);
+ this.ReportPropertyChanging("LastName");
+ this._LastName = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("LastName");
+ this.OnLastNameChanged();
+ }
+ }
+ private string _LastName;
+ partial void OnLastNameChanging(string value);
+ partial void OnLastNameChanged();
+ /// <summary>
+ /// The email address claimed to be controlled by the user. Whether it is actually owned by the user is indicated by the EmailAddressVerified property.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string EmailAddress
+ {
+ get
+ {
+ return this._EmailAddress;
+ }
+ set
+ {
+ this.OnEmailAddressChanging(value);
+ this.ReportPropertyChanging("EmailAddress");
+ this._EmailAddress = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("EmailAddress");
+ this.OnEmailAddressChanged();
+ }
+ }
+ private string _EmailAddress;
+ partial void OnEmailAddressChanging(string value);
+ partial void OnEmailAddressChanged();
+ /// <summary>
+ /// A value indicating whether the email address has been verified as actually owned by this user.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public bool EmailAddressVerified
+ {
+ get
+ {
+ return this._EmailAddressVerified;
+ }
+ set
+ {
+ this.OnEmailAddressVerifiedChanging(value);
+ this.ReportPropertyChanging("EmailAddressVerified");
+ this._EmailAddressVerified = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("EmailAddressVerified");
+ this.OnEmailAddressVerifiedChanged();
+ }
+ }
+ private bool _EmailAddressVerified;
+ partial void OnEmailAddressVerifiedChanging(bool value);
+ partial void OnEmailAddressVerifiedChanged();
+ /// <summary>
+ /// There are no comments for Roles in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "UserRole", "Role")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityCollection<Role> Roles
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<Role>("DatabaseModel.UserRole", "Role");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<Role>("DatabaseModel.UserRole", "Role", value);
+ }
+ }
+ }
+ /// <summary>
+ /// There are no comments for AuthenticationTokens in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "UserAuthenticationToken", "AuthenticationToken")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityCollection<AuthenticationToken> AuthenticationTokens
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<AuthenticationToken>("DatabaseModel.UserAuthenticationToken", "AuthenticationToken");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<AuthenticationToken>("DatabaseModel.UserAuthenticationToken", "AuthenticationToken", value);
+ }
+ }
+ }
+ /// <summary>
+ /// There are no comments for IssuedToken in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_User", "IssuedTokens")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityCollection<IssuedToken> IssuedToken
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_User", "IssuedTokens");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_User", "IssuedTokens", value);
+ }
+ }
+ }
+ }
+ /// <summary>
+ /// There are no comments for DatabaseModel.Consumer in the schema.
+ /// </summary>
+ /// <KeyProperties>
+ /// ConsumerId
+ /// </KeyProperties>
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="Consumer")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ public partial class Consumer : global::System.Data.Objects.DataClasses.EntityObject
+ {
+ /// <summary>
+ /// Create a new Consumer object.
+ /// </summary>
+ /// <param name="consumerKey">Initial value of ConsumerKey.</param>
+ /// <param name="verificationCodeLength">Initial value of VerificationCodeLength.</param>
+ /// <param name="consumerId">Initial value of ConsumerId.</param>
+ public static Consumer CreateConsumer(string consumerKey, int verificationCodeLength, int consumerId)
+ {
+ Consumer consumer = new Consumer();
+ consumer.ConsumerKey = consumerKey;
+ consumer.VerificationCodeLength = verificationCodeLength;
+ consumer.ConsumerId = consumerId;
+ return consumer;
+ }
+ /// <summary>
+ /// There are no comments for Property ConsumerKey in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string ConsumerKey
+ {
+ get
+ {
+ return this._ConsumerKey;
+ }
+ set
+ {
+ this.OnConsumerKeyChanging(value);
+ this.ReportPropertyChanging("ConsumerKey");
+ this._ConsumerKey = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false);
+ this.ReportPropertyChanged("ConsumerKey");
+ this.OnConsumerKeyChanged();
+ }
+ }
+ private string _ConsumerKey;
+ partial void OnConsumerKeyChanging(string value);
+ partial void OnConsumerKeyChanged();
+ /// <summary>
+ /// There are no comments for Property ConsumerSecret in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string ConsumerSecret
+ {
+ get
+ {
+ return this._ConsumerSecret;
+ }
+ set
+ {
+ this.OnConsumerSecretChanging(value);
+ this.ReportPropertyChanging("ConsumerSecret");
+ this._ConsumerSecret = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("ConsumerSecret");
+ this.OnConsumerSecretChanged();
+ }
+ }
+ private string _ConsumerSecret;
+ partial void OnConsumerSecretChanging(string value);
+ partial void OnConsumerSecretChanged();
+ /// <summary>
+ /// There are no comments for Property X509CertificateAsBinary in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ private byte[] X509CertificateAsBinary
+ {
+ get
+ {
+ return global::System.Data.Objects.DataClasses.StructuralObject.GetValidValue(this._X509CertificateAsBinary);
+ }
+ set
+ {
+ this.OnX509CertificateAsBinaryChanging(value);
+ this.ReportPropertyChanging("X509CertificateAsBinary");
+ this._X509CertificateAsBinary = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("X509CertificateAsBinary");
+ this.OnX509CertificateAsBinaryChanged();
+ }
+ }
+ private byte[] _X509CertificateAsBinary;
+ partial void OnX509CertificateAsBinaryChanging(byte[] value);
+ partial void OnX509CertificateAsBinaryChanged();
+ /// <summary>
+ /// There are no comments for Property CallbackAsString in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string CallbackAsString
+ {
+ get
+ {
+ return this._CallbackAsString;
+ }
+ set
+ {
+ this.OnCallbackAsStringChanging(value);
+ this.ReportPropertyChanging("CallbackAsString");
+ this._CallbackAsString = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("CallbackAsString");
+ this.OnCallbackAsStringChanged();
+ }
+ }
+ private string _CallbackAsString;
+ partial void OnCallbackAsStringChanging(string value);
+ partial void OnCallbackAsStringChanged();
+ /// <summary>
+ /// There are no comments for Property VerificationCodeFormatAsInt in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ private int VerificationCodeFormatAsInt
+ {
+ get
+ {
+ return this._VerificationCodeFormatAsInt;
+ }
+ set
+ {
+ this.OnVerificationCodeFormatAsIntChanging(value);
+ this.ReportPropertyChanging("VerificationCodeFormatAsInt");
+ this._VerificationCodeFormatAsInt = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("VerificationCodeFormatAsInt");
+ this.OnVerificationCodeFormatAsIntChanged();
+ }
+ }
+ private int _VerificationCodeFormatAsInt;
+ partial void OnVerificationCodeFormatAsIntChanging(int value);
+ partial void OnVerificationCodeFormatAsIntChanged();
+ /// <summary>
+ /// There are no comments for Property VerificationCodeLength in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public int VerificationCodeLength
+ {
+ get
+ {
+ return this._VerificationCodeLength;
+ }
+ set
+ {
+ this.OnVerificationCodeLengthChanging(value);
+ this.ReportPropertyChanging("VerificationCodeLength");
+ this._VerificationCodeLength = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("VerificationCodeLength");
+ this.OnVerificationCodeLengthChanged();
+ }
+ }
+ private int _VerificationCodeLength;
+ partial void OnVerificationCodeLengthChanging(int value);
+ partial void OnVerificationCodeLengthChanged();
+ /// <summary>
+ /// There are no comments for Property ConsumerId in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public int ConsumerId
+ {
+ get
+ {
+ return this._ConsumerId;
+ }
+ set
+ {
+ this.OnConsumerIdChanging(value);
+ this.ReportPropertyChanging("ConsumerId");
+ this._ConsumerId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("ConsumerId");
+ this.OnConsumerIdChanged();
+ }
+ }
+ private int _ConsumerId;
+ partial void OnConsumerIdChanging(int value);
+ partial void OnConsumerIdChanged();
+ /// <summary>
+ /// There are no comments for Property Name in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string Name
+ {
+ get
+ {
+ return this._Name;
+ }
+ set
+ {
+ this.OnNameChanging(value);
+ this.ReportPropertyChanging("Name");
+ this._Name = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("Name");
+ this.OnNameChanged();
+ }
+ }
+ private string _Name;
+ partial void OnNameChanging(string value);
+ partial void OnNameChanged();
+ /// <summary>
+ /// There are no comments for IssuedToken in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "IssuedTokens")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityCollection<IssuedToken> IssuedToken
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_Consumer", "IssuedTokens");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_Consumer", "IssuedTokens", value);
+ }
+ }
+ }
+ }
+ /// <summary>
+ /// There are no comments for DatabaseModel.IssuedToken in the schema.
+ /// </summary>
+ /// <KeyProperties>
+ /// TokenId
+ /// </KeyProperties>
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="IssuedToken")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ [global::System.Runtime.Serialization.KnownTypeAttribute(typeof(global::RelyingPartyLogic.IssuedRequestToken))]
+ [global::System.Runtime.Serialization.KnownTypeAttribute(typeof(global::RelyingPartyLogic.IssuedAccessToken))]
+ public abstract partial class IssuedToken : global::System.Data.Objects.DataClasses.EntityObject
+ {
+ /// <summary>
+ /// There are no comments for Property TokenId in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public int TokenId
+ {
+ get
+ {
+ return this._TokenId;
+ }
+ set
+ {
+ this.OnTokenIdChanging(value);
+ this.ReportPropertyChanging("TokenId");
+ this._TokenId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("TokenId");
+ this.OnTokenIdChanged();
+ }
+ }
+ private int _TokenId;
+ partial void OnTokenIdChanging(int value);
+ partial void OnTokenIdChanged();
+ /// <summary>
+ /// There are no comments for Property Token in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string Token
+ {
+ get
+ {
+ return this._Token;
+ }
+ set
+ {
+ this.OnTokenChanging(value);
+ this.ReportPropertyChanging("Token");
+ this._Token = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false);
+ this.ReportPropertyChanged("Token");
+ this.OnTokenChanged();
+ }
+ }
+ private string _Token;
+ partial void OnTokenChanging(string value);
+ partial void OnTokenChanged();
+ /// <summary>
+ /// There are no comments for Property TokenSecret in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string TokenSecret
+ {
+ get
+ {
+ return this._TokenSecret;
+ }
+ set
+ {
+ this.OnTokenSecretChanging(value);
+ this.ReportPropertyChanging("TokenSecret");
+ this._TokenSecret = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false);
+ this.ReportPropertyChanged("TokenSecret");
+ this.OnTokenSecretChanged();
+ }
+ }
+ private string _TokenSecret;
+ partial void OnTokenSecretChanging(string value);
+ partial void OnTokenSecretChanged();
+ /// <summary>
+ /// There are no comments for Property CreatedOn in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.DateTime CreatedOn
+ {
+ get
+ {
+ return this._CreatedOn;
+ }
+ set
+ {
+ this.OnCreatedOnChanging(value);
+ this.ReportPropertyChanging("CreatedOn");
+ this._CreatedOn = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("CreatedOn");
+ this.OnCreatedOnChanged();
+ }
+ }
+ private global::System.DateTime _CreatedOn;
+ partial void OnCreatedOnChanging(global::System.DateTime value);
+ partial void OnCreatedOnChanged();
+ /// <summary>
+ /// There are no comments for Property Scope in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string Scope
+ {
+ get
+ {
+ return this._Scope;
+ }
+ set
+ {
+ this.OnScopeChanging(value);
+ this.ReportPropertyChanging("Scope");
+ this._Scope = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("Scope");
+ this.OnScopeChanged();
+ }
+ }
+ private string _Scope;
+ partial void OnScopeChanging(string value);
+ partial void OnScopeChanged();
+ /// <summary>
+ /// There are no comments for Consumer in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "Consumer")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public Consumer Consumer
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer", "Consumer").Value;
+ }
+ set
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer", "Consumer").Value = value;
+ }
+ }
+ /// <summary>
+ /// There are no comments for Consumer in the schema.
+ /// </summary>
+ [global::System.ComponentModel.BrowsableAttribute(false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityReference<Consumer> ConsumerReference
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer", "Consumer");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer", "Consumer", value);
+ }
+ }
+ }
+ /// <summary>
+ /// There are no comments for User in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_User", "User")]
+ [global::System.Xml.Serialization.XmlIgnoreAttribute()]
+ [global::System.Xml.Serialization.SoapIgnoreAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public User User
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User").Value;
+ }
+ set
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User").Value = value;
+ }
+ }
+ /// <summary>
+ /// There are no comments for User in the schema.
+ /// </summary>
+ [global::System.ComponentModel.BrowsableAttribute(false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Data.Objects.DataClasses.EntityReference<User> UserReference
+ {
+ get
+ {
+ return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User");
+ }
+ set
+ {
+ if ((value != null))
+ {
+ ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User", value);
+ }
+ }
+ }
+ }
+ /// <summary>
+ /// There are no comments for DatabaseModel.IssuedRequestToken in the schema.
+ /// </summary>
+ /// <KeyProperties>
+ /// TokenId
+ /// </KeyProperties>
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="IssuedRequestToken")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ public partial class IssuedRequestToken : IssuedToken
+ {
+ /// <summary>
+ /// Create a new IssuedRequestToken object.
+ /// </summary>
+ /// <param name="tokenId">Initial value of TokenId.</param>
+ /// <param name="token">Initial value of Token.</param>
+ /// <param name="tokenSecret">Initial value of TokenSecret.</param>
+ /// <param name="createdOn">Initial value of CreatedOn.</param>
+ public static IssuedRequestToken CreateIssuedRequestToken(int tokenId, string token, string tokenSecret, global::System.DateTime createdOn)
+ {
+ IssuedRequestToken issuedRequestToken = new IssuedRequestToken();
+ issuedRequestToken.TokenId = tokenId;
+ issuedRequestToken.Token = token;
+ issuedRequestToken.TokenSecret = tokenSecret;
+ issuedRequestToken.CreatedOn = createdOn;
+ return issuedRequestToken;
+ }
+ /// <summary>
+ /// There are no comments for Property ConsumerVersionAsString in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ private string ConsumerVersionAsString
+ {
+ get
+ {
+ return this._ConsumerVersionAsString;
+ }
+ set
+ {
+ this.OnConsumerVersionAsStringChanging(value);
+ this.ReportPropertyChanging("ConsumerVersionAsString");
+ this._ConsumerVersionAsString = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false);
+ this.ReportPropertyChanged("ConsumerVersionAsString");
+ this.OnConsumerVersionAsStringChanged();
+ }
+ }
+ private string _ConsumerVersionAsString;
+ partial void OnConsumerVersionAsStringChanging(string value);
+ partial void OnConsumerVersionAsStringChanged();
+ /// <summary>
+ /// There are no comments for Property VerificationCode in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public string VerificationCode
+ {
+ get
+ {
+ return this._VerificationCode;
+ }
+ set
+ {
+ this.OnVerificationCodeChanging(value);
+ this.ReportPropertyChanging("VerificationCode");
+ this._VerificationCode = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("VerificationCode");
+ this.OnVerificationCodeChanged();
+ }
+ }
+ private string _VerificationCode;
+ partial void OnVerificationCodeChanging(string value);
+ partial void OnVerificationCodeChanged();
+ /// <summary>
+ /// There are no comments for Property CallbackAsString in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ private string CallbackAsString
+ {
+ get
+ {
+ return this._CallbackAsString;
+ }
+ set
+ {
+ this.OnCallbackAsStringChanging(value);
+ this.ReportPropertyChanging("CallbackAsString");
+ this._CallbackAsString = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true);
+ this.ReportPropertyChanged("CallbackAsString");
+ this.OnCallbackAsStringChanged();
+ }
+ }
+ private string _CallbackAsString;
+ partial void OnCallbackAsStringChanging(string value);
+ partial void OnCallbackAsStringChanged();
+ }
+ /// <summary>
+ /// There are no comments for DatabaseModel.IssuedAccessToken in the schema.
+ /// </summary>
+ /// <KeyProperties>
+ /// TokenId
+ /// </KeyProperties>
+ [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="IssuedAccessToken")]
+ [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
+ [global::System.Serializable()]
+ public partial class IssuedAccessToken : IssuedToken
+ {
+ /// <summary>
+ /// Create a new IssuedAccessToken object.
+ /// </summary>
+ /// <param name="tokenId">Initial value of TokenId.</param>
+ /// <param name="token">Initial value of Token.</param>
+ /// <param name="tokenSecret">Initial value of TokenSecret.</param>
+ /// <param name="createdOn">Initial value of CreatedOn.</param>
+ public static IssuedAccessToken CreateIssuedAccessToken(int tokenId, string token, string tokenSecret, global::System.DateTime createdOn)
+ {
+ IssuedAccessToken issuedAccessToken = new IssuedAccessToken();
+ issuedAccessToken.TokenId = tokenId;
+ issuedAccessToken.Token = token;
+ issuedAccessToken.TokenSecret = tokenSecret;
+ issuedAccessToken.CreatedOn = createdOn;
+ return issuedAccessToken;
+ }
+ /// <summary>
+ /// There are no comments for Property ExpirationDate in the schema.
+ /// </summary>
+ [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ public global::System.Nullable<global::System.DateTime> ExpirationDate
+ {
+ get
+ {
+ return this._ExpirationDate;
+ }
+ set
+ {
+ this.OnExpirationDateChanging(value);
+ this.ReportPropertyChanging("ExpirationDate");
+ this._ExpirationDate = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
+ this.ReportPropertyChanged("ExpirationDate");
+ this.OnExpirationDateChanged();
+ }
+ }
+ private global::System.Nullable<global::System.DateTime> _ExpirationDate;
+ partial void OnExpirationDateChanging(global::System.Nullable<global::System.DateTime> value);
+ partial void OnExpirationDateChanged();
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs b/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs
new file mode 100644
index 0000000..fff27af
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs
@@ -0,0 +1,58 @@
+//-----------------------------------------------------------------------
+// <copyright file="Model.IssuedAccessToken.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ public partial class IssuedAccessToken : IServiceProviderAccessToken {
+ /// <summary>
+ /// Gets the roles that the OAuth principal should belong to.
+ /// </summary>
+ /// <value>
+ /// The roles that the user belongs to, or a subset of these according to the rights
+ /// granted when the user authorized the request token.
+ /// </value>
+ string[] IServiceProviderAccessToken.Roles {
+ get {
+ List<string> roles = new List<string>();
+
+ // Include the roles the user who authorized this OAuth token has.
+ roles.AddRange(this.User.Roles.Select(r => r.Name));
+
+ // Always add an extra role to indicate this is an OAuth-authorized request.
+ // This allows us to deny access to account management pages to OAuth requests.
+ roles.Add("delegated");
+
+ return roles.ToArray();
+ }
+ }
+
+ /// <summary>
+ /// Gets the username of the principal that will be impersonated by this access token.
+ /// </summary>
+ /// <value>
+ /// The name of the user who authorized the OAuth request token originally.
+ /// </value>
+ string IServiceProviderAccessToken.Username {
+ get {
+ // We don't really have the concept of a single username, but we
+ // can use any of the authentication tokens instead since that
+ // is what the rest of the web site expects.
+ if (!this.UserReference.IsLoaded) {
+ this.UserReference.Load();
+ }
+ if (!this.User.AuthenticationTokens.IsLoaded) {
+ this.User.AuthenticationTokens.Load();
+ }
+ return this.User.AuthenticationTokens.First().ClaimedIdentifier;
+ }
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs b/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs
new file mode 100644
index 0000000..c62f5c4
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="Model.IssuedRequestToken.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ public partial class IssuedRequestToken : IServiceProviderRequestToken {
+ /// <summary>
+ /// Gets or sets the callback associated specifically with this token, if any.
+ /// </summary>
+ /// <value>
+ /// The callback URI; or <c>null</c> if no callback was specifically assigned to this token.
+ /// </value>
+ public Uri Callback {
+ get { return this.CallbackAsString != null ? new Uri(this.CallbackAsString) : null; }
+ set { this.CallbackAsString = value != null ? value.AbsoluteUri : null; }
+ }
+
+ /// <summary>
+ /// Gets or sets the version of the Consumer that requested this token.
+ /// </summary>
+ /// <remarks>
+ /// This property is used to determine whether a <see cref="VerificationCode"/> must be
+ /// generated when the user authorizes the Consumer or not.
+ /// </remarks>
+ Version IServiceProviderRequestToken.ConsumerVersion {
+ get { return this.ConsumerVersionAsString != null ? new Version(this.ConsumerVersionAsString) : null; }
+ set { this.ConsumerVersionAsString = value != null ? value.ToString() : null; }
+ }
+
+ /// <summary>
+ /// Gets the consumer key that requested this token.
+ /// </summary>
+ string IServiceProviderRequestToken.ConsumerKey {
+ get { return this.Consumer.ConsumerKey; }
+ }
+
+ /// <summary>
+ /// Authorizes this request token to allow exchange for an access token.
+ /// </summary>
+ /// <remarks>
+ /// Call this method when the user has completed web-based authorization.
+ /// </remarks>
+ public void Authorize() {
+ this.User = Database.LoggedInUser;
+ Database.DataContext.SaveChanges();
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Model.User.cs b/projecttemplates/RelyingPartyLogic/Model.User.cs
new file mode 100644
index 0000000..16980e2
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Model.User.cs
@@ -0,0 +1,19 @@
+//-----------------------------------------------------------------------
+// <copyright file="Model.User.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+
+ public partial class User {
+ partial void OnEmailAddressChanged() {
+ // Whenever the email address is changed, we must reset its verified status.
+ this.EmailAddressVerified = false;
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Model.edmx b/projecttemplates/RelyingPartyLogic/Model.edmx
new file mode 100644
index 0000000..f37aa6c
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Model.edmx
@@ -0,0 +1,404 @@
+<?xml version="1.0" encoding="utf-8"?>
+<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
+ <!-- EF Runtime content -->
+ <edmx:Runtime>
+ <!-- SSDL content -->
+ <edmx:StorageModels>
+ <Schema Namespace="DatabaseModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
+ <EntityContainer Name="DatabaseModelStoreContainer">
+ <EntitySet Name="AuthenticationToken" EntityType="DatabaseModel.Store.AuthenticationToken" store:Type="Tables" Schema="dbo" />
+ <EntitySet Name="Consumer" EntityType="DatabaseModel.Store.Consumer" store:Type="Tables" Schema="dbo" />
+ <EntitySet Name="IssuedToken" EntityType="DatabaseModel.Store.IssuedToken" store:Type="Tables" Schema="dbo" />
+ <EntitySet Name="Role" EntityType="DatabaseModel.Store.Role" store:Type="Tables" Schema="dbo" />
+ <EntitySet Name="User" EntityType="DatabaseModel.Store.User" store:Type="Tables" Schema="dbo" />
+ <EntitySet Name="UserRole" EntityType="DatabaseModel.Store.UserRole" store:Type="Tables" Schema="dbo" />
+ <AssociationSet Name="FK_AuthenticationToken_User" Association="DatabaseModel.Store.FK_AuthenticationToken_User">
+ <End Role="User" EntitySet="User" />
+ <End Role="AuthenticationToken" EntitySet="AuthenticationToken" />
+ </AssociationSet>
+ <AssociationSet Name="FK_IssuedToken_Consumer" Association="DatabaseModel.Store.FK_IssuedToken_Consumer">
+ <End Role="Consumer" EntitySet="Consumer" />
+ <End Role="IssuedToken" EntitySet="IssuedToken" />
+ </AssociationSet>
+ <AssociationSet Name="FK_IssuedToken_User" Association="DatabaseModel.Store.FK_IssuedToken_User">
+ <End Role="User" EntitySet="User" />
+ <End Role="IssuedToken" EntitySet="IssuedToken" />
+ </AssociationSet>
+ <AssociationSet Name="FK_UserRole_Role" Association="DatabaseModel.Store.FK_UserRole_Role">
+ <End Role="Role" EntitySet="Role" />
+ <End Role="UserRole" EntitySet="UserRole" />
+ </AssociationSet>
+ <AssociationSet Name="FK_UserRole_User" Association="DatabaseModel.Store.FK_UserRole_User">
+ <End Role="User" EntitySet="User" />
+ <End Role="UserRole" EntitySet="UserRole" />
+ </AssociationSet>
+ </EntityContainer>
+ <EntityType Name="AuthenticationToken">
+ <Key>
+ <PropertyRef Name="Id" />
+ </Key>
+ <Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
+ <Property Name="UserId" Type="int" Nullable="false" />
+ <Property Name="OpenIdClaimedIdentifier" Type="nvarchar" Nullable="false" MaxLength="250" />
+ <Property Name="OpenIdFriendlyIdentifier" Type="nvarchar" MaxLength="250" />
+ </EntityType>
+ <EntityType Name="Consumer">
+ <Key>
+ <PropertyRef Name="ConsumerId" />
+ </Key>
+ <Property Name="ConsumerId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
+ <Property Name="ConsumerKey" Type="nvarchar" Nullable="false" MaxLength="255" />
+ <Property Name="ConsumerSecret" Type="nvarchar" MaxLength="255" />
+ <Property Name="X509Certificate" Type="image" />
+ <Property Name="Callback" Type="nvarchar" MaxLength="2048" />
+ <Property Name="VerificationCodeFormat" Type="int" Nullable="false" />
+ <Property Name="VerificationCodeLength" Type="int" Nullable="false" />
+ <Property Name="Name" Type="nvarchar" MaxLength="50" />
+ </EntityType>
+ <EntityType Name="IssuedToken">
+ <Key>
+ <PropertyRef Name="TokenId" />
+ </Key>
+ <Property Name="TokenId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
+ <Property Name="ConsumerId" Type="int" Nullable="false" />
+ <Property Name="UserId" Type="int" />
+ <Property Name="Token" Type="nvarchar" Nullable="false" MaxLength="255" />
+ <Property Name="TokenSecret" Type="nvarchar" Nullable="false" MaxLength="255" />
+ <Property Name="CreatedOn" Type="datetime" Nullable="false" />
+ <Property Name="Callback" Type="nvarchar" MaxLength="2048" />
+ <Property Name="VerificationCode" Type="nvarchar" MaxLength="255" />
+ <Property Name="ConsumerVersion" Type="varchar" MaxLength="10" />
+ <Property Name="ExpirationDate" Type="datetime" />
+ <Property Name="IsAccessToken" Type="bit" Nullable="false" />
+ <Property Name="Scope" Type="nvarchar" MaxLength="255" />
+ </EntityType>
+ <EntityType Name="Role">
+ <Key>
+ <PropertyRef Name="Id" />
+ </Key>
+ <Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
+ <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" />
+ </EntityType>
+ <EntityType Name="User">
+ <Key>
+ <PropertyRef Name="Id" />
+ </Key>
+ <Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
+ <Property Name="FirstName" Type="nvarchar" MaxLength="50" />
+ <Property Name="LastName" Type="nvarchar" MaxLength="50" />
+ <Property Name="EmailAddress" Type="nvarchar" MaxLength="100" />
+ <Property Name="EmailAddressVerified" Type="bit" Nullable="false" />
+ </EntityType>
+ <EntityType Name="UserRole">
+ <Key>
+ <PropertyRef Name="UserId" />
+ <PropertyRef Name="RoleId" />
+ </Key>
+ <Property Name="UserId" Type="int" Nullable="false" />
+ <Property Name="RoleId" Type="int" Nullable="false" />
+ </EntityType>
+ <Association Name="FK_AuthenticationToken_User">
+ <End Role="User" Type="DatabaseModel.Store.User" Multiplicity="1">
+ <OnDelete Action="Cascade" />
+ </End>
+ <End Role="AuthenticationToken" Type="DatabaseModel.Store.AuthenticationToken" Multiplicity="*" />
+ <ReferentialConstraint>
+ <Principal Role="User">
+ <PropertyRef Name="Id" />
+ </Principal>
+ <Dependent Role="AuthenticationToken">
+ <PropertyRef Name="UserId" />
+ </Dependent>
+ </ReferentialConstraint>
+ </Association>
+ <Association Name="FK_IssuedToken_Consumer">
+ <End Role="Consumer" Type="DatabaseModel.Store.Consumer" Multiplicity="1">
+ <OnDelete Action="Cascade" />
+ </End>
+ <End Role="IssuedToken" Type="DatabaseModel.Store.IssuedToken" Multiplicity="*" />
+ <ReferentialConstraint>
+ <Principal Role="Consumer">
+ <PropertyRef Name="ConsumerId" />
+ </Principal>
+ <Dependent Role="IssuedToken">
+ <PropertyRef Name="ConsumerId" />
+ </Dependent>
+ </ReferentialConstraint>
+ </Association>
+ <Association Name="FK_IssuedToken_User">
+ <End Role="User" Type="DatabaseModel.Store.User" Multiplicity="0..1">
+ <OnDelete Action="Cascade" />
+ </End>
+ <End Role="IssuedToken" Type="DatabaseModel.Store.IssuedToken" Multiplicity="*" />
+ <ReferentialConstraint>
+ <Principal Role="User">
+ <PropertyRef Name="Id" />
+ </Principal>
+ <Dependent Role="IssuedToken">
+ <PropertyRef Name="UserId" />
+ </Dependent>
+ </ReferentialConstraint>
+ </Association>
+ <Association Name="FK_UserRole_Role">
+ <End Role="Role" Type="DatabaseModel.Store.Role" Multiplicity="1">
+ <OnDelete Action="Cascade" />
+ </End>
+ <End Role="UserRole" Type="DatabaseModel.Store.UserRole" Multiplicity="*" />
+ <ReferentialConstraint>
+ <Principal Role="Role">
+ <PropertyRef Name="Id" />
+ </Principal>
+ <Dependent Role="UserRole">
+ <PropertyRef Name="RoleId" />
+ </Dependent>
+ </ReferentialConstraint>
+ </Association>
+ <Association Name="FK_UserRole_User">
+ <End Role="User" Type="DatabaseModel.Store.User" Multiplicity="1">
+ <OnDelete Action="Cascade" />
+ </End>
+ <End Role="UserRole" Type="DatabaseModel.Store.UserRole" Multiplicity="*" />
+ <ReferentialConstraint>
+ <Principal Role="User">
+ <PropertyRef Name="Id" />
+ </Principal>
+ <Dependent Role="UserRole">
+ <PropertyRef Name="UserId" />
+ </Dependent>
+ </ReferentialConstraint>
+ </Association>
+ </Schema></edmx:StorageModels>
+ <!-- CSDL content -->
+ <edmx:ConceptualModels>
+ <Schema Namespace="DatabaseModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
+ <EntityContainer Name="DatabaseEntities">
+ <EntitySet Name="Role" EntityType="DatabaseModel.Role" />
+ <EntitySet Name="User" EntityType="DatabaseModel.User" />
+ <AssociationSet Name="UserRole" Association="DatabaseModel.UserRole">
+ <End Role="Role" EntitySet="Role" />
+ <End Role="User" EntitySet="User" />
+ </AssociationSet>
+ <EntitySet Name="AuthenticationToken" EntityType="DatabaseModel.AuthenticationToken" />
+ <AssociationSet Name="UserAuthenticationToken" Association="DatabaseModel.UserAuthenticationToken">
+ <End Role="User" EntitySet="User" />
+ <End Role="AuthenticationToken" EntitySet="AuthenticationToken" /></AssociationSet>
+ <EntitySet Name="Consumer" EntityType="DatabaseModel.Consumer" />
+ <EntitySet Name="IssuedToken" EntityType="DatabaseModel.IssuedToken" />
+ <AssociationSet Name="FK_IssuedToken_Consumer" Association="DatabaseModel.FK_IssuedToken_Consumer">
+ <End Role="Consumer" EntitySet="Consumer" />
+ <End Role="IssuedTokens" EntitySet="IssuedToken" /></AssociationSet>
+ <AssociationSet Name="FK_IssuedToken_User" Association="DatabaseModel.FK_IssuedToken_User">
+ <End Role="User" EntitySet="User" />
+ <End Role="IssuedTokens" EntitySet="IssuedToken" /></AssociationSet>
+ </EntityContainer>
+ <EntityType Name="AuthenticationToken" Abstract="false">
+ <Key>
+ <PropertyRef Name="Id" /></Key>
+ <Property Name="Id" Type="Int32" Nullable="false" a:SetterAccess="Public" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" />
+ <NavigationProperty Name="User" Relationship="DatabaseModel.UserAuthenticationToken" FromRole="AuthenticationToken" ToRole="User" />
+ <Property Name="ClaimedIdentifier" Type="String" Nullable="false" />
+ <Property Name="FriendlyIdentifier" Type="String" Nullable="true" /></EntityType>
+ <EntityType Name="Role">
+ <Key>
+ <PropertyRef Name="Id" />
+ </Key>
+ <Property Name="Id" Type="Int32" Nullable="false" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" />
+ <Property Name="Name" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" />
+ <NavigationProperty Name="Users" Relationship="DatabaseModel.UserRole" FromRole="Role" ToRole="User" />
+ </EntityType>
+ <EntityType Name="User">
+ <Key>
+ <PropertyRef Name="Id" />
+ </Key>
+ <Property Name="Id" Type="Int32" Nullable="false" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" />
+ <Property Name="FirstName" Type="String" MaxLength="50" Unicode="true" FixedLength="false" />
+ <Property Name="LastName" Type="String" MaxLength="50" Unicode="true" FixedLength="false" />
+ <Property Name="EmailAddress" Type="String" MaxLength="100" Unicode="true" FixedLength="false" >
+ <Documentation>
+ <Summary>The email address claimed to be controlled by the user. Whether it is actually owned by the user is indicated by the EmailAddressVerified property.</Summary></Documentation></Property>
+ <NavigationProperty Name="Roles" Relationship="DatabaseModel.UserRole" FromRole="User" ToRole="Role" />
+ <NavigationProperty Name="AuthenticationTokens" Relationship="DatabaseModel.UserAuthenticationToken" FromRole="User" ToRole="AuthenticationToken" />
+ <Property Name="EmailAddressVerified" Type="Boolean" Nullable="false" >
+ <Documentation>
+ <Summary>A value indicating whether the email address has been verified as actually owned by this user.</Summary></Documentation></Property>
+ <NavigationProperty Name="IssuedToken" Relationship="DatabaseModel.FK_IssuedToken_User" FromRole="User" ToRole="IssuedTokens" /></EntityType>
+ <Association Name="UserRole">
+ <End Role="Role" Type="DatabaseModel.Role" Multiplicity="*" />
+ <End Role="User" Type="DatabaseModel.User" Multiplicity="*" />
+ </Association>
+ <Association Name="UserAuthenticationToken">
+ <End Type="DatabaseModel.User" Role="User" Multiplicity="1" />
+ <End Type="DatabaseModel.AuthenticationToken" Role="AuthenticationToken" Multiplicity="*" /></Association>
+ <EntityType Name="Consumer">
+ <Key>
+ <PropertyRef Name="ConsumerId" /></Key>
+ <Property Name="ConsumerKey" Type="String" Nullable="false" />
+ <Property Name="ConsumerSecret" Type="String" Nullable="true" />
+ <Property Name="X509CertificateAsBinary" Type="Binary" Nullable="true" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:GetterAccess="Private" />
+ <Property Name="CallbackAsString" Type="String" Nullable="true" />
+ <Property Name="VerificationCodeFormatAsInt" Type="Int32" Nullable="false" a:GetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:SetterAccess="Private" />
+ <Property Name="VerificationCodeLength" Type="Int32" Nullable="false" />
+ <Property Name="ConsumerId" Type="Int32" Nullable="false" />
+ <NavigationProperty Name="IssuedToken" Relationship="DatabaseModel.FK_IssuedToken_Consumer" FromRole="Consumer" ToRole="IssuedTokens" />
+ <Property Name="Name" Type="String" Nullable="true" /></EntityType>
+ <EntityType Name="IssuedToken" Abstract="true">
+ <Key>
+ <PropertyRef Name="TokenId" /></Key>
+ <Property Name="TokenId" Type="Int32" Nullable="false" />
+ <Property Name="Token" Type="String" Nullable="false" />
+ <Property Name="TokenSecret" Type="String" Nullable="false" />
+ <Property Name="CreatedOn" Type="DateTime" Nullable="false" />
+ <NavigationProperty Name="Consumer" Relationship="DatabaseModel.FK_IssuedToken_Consumer" FromRole="IssuedTokens" ToRole="Consumer" />
+ <NavigationProperty Name="User" Relationship="DatabaseModel.FK_IssuedToken_User" FromRole="IssuedTokens" ToRole="User" />
+ <Property Name="Scope" Type="String" Nullable="true" /></EntityType>
+ <Association Name="FK_IssuedToken_Consumer">
+ <End Type="DatabaseModel.Consumer" Role="Consumer" Multiplicity="1" />
+ <End Type="DatabaseModel.IssuedToken" Role="IssuedTokens" Multiplicity="*" /></Association>
+ <Association Name="FK_IssuedToken_User">
+ <End Type="DatabaseModel.User" Role="User" Multiplicity="0..1" />
+ <End Type="DatabaseModel.IssuedToken" Role="IssuedTokens" Multiplicity="*" /></Association>
+ <EntityType Name="IssuedRequestToken" BaseType="DatabaseModel.IssuedToken">
+ <Property Name="ConsumerVersionAsString" Type="String" Nullable="false" a:GetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:SetterAccess="Private" />
+ <Property Name="VerificationCode" Type="String" Nullable="true" />
+ <Property Name="CallbackAsString" Type="String" Nullable="true" a:GetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:SetterAccess="Private" /></EntityType>
+ <EntityType Name="IssuedAccessToken" BaseType="DatabaseModel.IssuedToken">
+ <Property Name="ExpirationDate" Type="DateTime" Nullable="true" /></EntityType></Schema>
+ </edmx:ConceptualModels>
+ <!-- C-S mapping content -->
+ <edmx:Mappings>
+ <Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
+ <EntityContainerMapping StorageEntityContainer="DatabaseModelStoreContainer" CdmEntityContainer="DatabaseEntities">
+ <EntitySetMapping Name="Role">
+ <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.Role)">
+ <MappingFragment StoreEntitySet="Role">
+ <ScalarProperty Name="Id" ColumnName="Id" />
+ <ScalarProperty Name="Name" ColumnName="Name" />
+ </MappingFragment>
+ </EntityTypeMapping>
+ </EntitySetMapping>
+ <EntitySetMapping Name="User">
+ <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.User)">
+ <MappingFragment StoreEntitySet="User">
+ <ScalarProperty Name="EmailAddressVerified" ColumnName="EmailAddressVerified" />
+ <ScalarProperty Name="Id" ColumnName="Id" />
+ <ScalarProperty Name="FirstName" ColumnName="FirstName" />
+ <ScalarProperty Name="LastName" ColumnName="LastName" />
+ <ScalarProperty Name="EmailAddress" ColumnName="EmailAddress" />
+ </MappingFragment>
+ </EntityTypeMapping>
+ </EntitySetMapping>
+ <AssociationSetMapping Name="UserRole" TypeName="DatabaseModel.UserRole" StoreEntitySet="UserRole">
+ <EndProperty Name="Role">
+ <ScalarProperty Name="Id" ColumnName="RoleId" />
+ </EndProperty>
+ <EndProperty Name="User">
+ <ScalarProperty Name="Id" ColumnName="UserId" />
+ </EndProperty>
+ </AssociationSetMapping>
+ <EntitySetMapping Name="AuthenticationToken"><EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.AuthenticationToken)">
+ <MappingFragment StoreEntitySet="AuthenticationToken">
+ <ScalarProperty Name="FriendlyIdentifier" ColumnName="OpenIdFriendlyIdentifier" />
+ <ScalarProperty Name="ClaimedIdentifier" ColumnName="OpenIdClaimedIdentifier" />
+ <ScalarProperty Name="Id" ColumnName="Id" />
+ </MappingFragment>
+ </EntityTypeMapping>
+ </EntitySetMapping>
+ <AssociationSetMapping Name="UserAuthenticationToken" TypeName="DatabaseModel.UserAuthenticationToken" StoreEntitySet="AuthenticationToken">
+ <EndProperty Name="AuthenticationToken">
+ <ScalarProperty Name="Id" ColumnName="Id" /></EndProperty>
+ <EndProperty Name="User">
+ <ScalarProperty Name="Id" ColumnName="UserId" /></EndProperty></AssociationSetMapping>
+ <EntitySetMapping Name="Consumer">
+ <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.Consumer)">
+ <MappingFragment StoreEntitySet="Consumer">
+ <ScalarProperty Name="Name" ColumnName="Name" />
+ <ScalarProperty Name="ConsumerId" ColumnName="ConsumerId" />
+ <ScalarProperty Name="VerificationCodeLength" ColumnName="VerificationCodeLength" />
+ <ScalarProperty Name="VerificationCodeFormatAsInt" ColumnName="VerificationCodeFormat" />
+ <ScalarProperty Name="CallbackAsString" ColumnName="Callback" />
+ <ScalarProperty Name="X509CertificateAsBinary" ColumnName="X509Certificate" />
+ <ScalarProperty Name="ConsumerSecret" ColumnName="ConsumerSecret" />
+ <ScalarProperty Name="ConsumerKey" ColumnName="ConsumerKey" /></MappingFragment></EntityTypeMapping></EntitySetMapping>
+ <EntitySetMapping Name="IssuedToken">
+ <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedToken)">
+ <MappingFragment StoreEntitySet="IssuedToken">
+ <ScalarProperty Name="Scope" ColumnName="Scope" />
+ <ScalarProperty Name="CreatedOn" ColumnName="CreatedOn" />
+ <ScalarProperty Name="TokenSecret" ColumnName="TokenSecret" />
+ <ScalarProperty Name="Token" ColumnName="Token" />
+ <ScalarProperty Name="TokenId" ColumnName="TokenId" /></MappingFragment></EntityTypeMapping>
+ <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedRequestToken)">
+ <MappingFragment StoreEntitySet="IssuedToken" >
+ <ScalarProperty Name="CallbackAsString" ColumnName="Callback" />
+ <ScalarProperty Name="ConsumerVersionAsString" ColumnName="ConsumerVersion" />
+ <ScalarProperty Name="VerificationCode" ColumnName="VerificationCode" />
+ <ScalarProperty Name="TokenId" ColumnName="TokenId" />
+ <Condition ColumnName="IsAccessToken" Value="0" /></MappingFragment></EntityTypeMapping>
+ <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedAccessToken)">
+ <MappingFragment StoreEntitySet="IssuedToken" >
+ <ScalarProperty Name="ExpirationDate" ColumnName="ExpirationDate" />
+ <ScalarProperty Name="TokenId" ColumnName="TokenId" />
+ <Condition ColumnName="IsAccessToken" Value="1" /></MappingFragment></EntityTypeMapping></EntitySetMapping>
+ <AssociationSetMapping Name="FK_IssuedToken_Consumer" TypeName="DatabaseModel.FK_IssuedToken_Consumer" StoreEntitySet="IssuedToken">
+ <EndProperty Name="IssuedTokens">
+ <ScalarProperty Name="TokenId" ColumnName="TokenId" /></EndProperty>
+ <EndProperty Name="Consumer">
+ <ScalarProperty Name="ConsumerId" ColumnName="ConsumerId" /></EndProperty></AssociationSetMapping>
+ <AssociationSetMapping Name="FK_IssuedToken_User" TypeName="DatabaseModel.FK_IssuedToken_User" StoreEntitySet="IssuedToken">
+ <EndProperty Name="IssuedTokens">
+ <ScalarProperty Name="TokenId" ColumnName="TokenId" /></EndProperty>
+ <EndProperty Name="User">
+ <ScalarProperty Name="Id" ColumnName="UserId" /></EndProperty>
+ <Condition ColumnName="UserId" IsNull="false" /></AssociationSetMapping></EntityContainerMapping>
+ </Mapping>
+ </edmx:Mappings>
+ </edmx:Runtime>
+ <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
+ <edmx:Designer xmlns="http://schemas.microsoft.com/ado/2007/06/edmx">
+ <edmx:Connection>
+ <DesignerInfoPropertySet>
+ <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
+ </DesignerInfoPropertySet>
+ </edmx:Connection>
+ <edmx:Options>
+ <DesignerInfoPropertySet>
+ <DesignerProperty Name="ValidateOnBuild" Value="true" />
+ </DesignerInfoPropertySet>
+ </edmx:Options>
+ <!-- Diagram content (shape and connector positions) -->
+ <edmx:Diagrams>
+ <Diagram Name="Model">
+ <EntityTypeShape EntityType="DatabaseModel.AuthenticationToken" Width="1.875" PointX="5.25" PointY="1.125" Height="1.4033821614583335" IsExpanded="true" />
+ <EntityTypeShape EntityType="DatabaseModel.Role" Width="1.5" PointX="0.75" PointY="1.25" Height="1.5956835937500002" IsExpanded="true" />
+ <EntityTypeShape EntityType="DatabaseModel.User" Width="1.75" PointX="2.875" PointY="0.875" Height="2.3648893229166661" IsExpanded="true" />
+ <AssociationConnector Association="DatabaseModel.UserRole" ManuallyRouted="false">
+ <ConnectorPoint PointX="2.25" PointY="2.0478417968750002" />
+ <ConnectorPoint PointX="2.875" PointY="2.0478417968750002" /></AssociationConnector>
+ <InheritanceConnector EntityType="DatabaseModel.AuthenticationToken">
+ <ConnectorPoint PointX="6.5625" PointY="3.375" />
+ <ConnectorPoint PointX="6.5625" PointY="2.9129850260416665" /></InheritanceConnector>
+ <AssociationConnector Association="DatabaseModel.UserAuthenticationToken">
+ <ConnectorPoint PointX="4.625" PointY="2.0189925130208337" />
+ <ConnectorPoint PointX="5.25" PointY="2.0189925130208337" /></AssociationConnector>
+ <EntityTypeShape EntityType="DatabaseModel.Consumer" Width="2.125" PointX="0.5" PointY="3.625" Height="2.1725878906249996" />
+ <EntityTypeShape EntityType="DatabaseModel.IssuedToken" Width="2" PointX="4.5" PointY="3.625" Height="2.1725878906249996" />
+ <AssociationConnector Association="DatabaseModel.FK_IssuedToken_Consumer" ManuallyRouted="false" >
+ <ConnectorPoint PointX="2.625" PointY="5.359375" />
+ <ConnectorPoint PointX="4.5" PointY="5.359375" />
+ </AssociationConnector>
+ <AssociationConnector Association="DatabaseModel.FK_IssuedToken_User" >
+ <ConnectorPoint PointX="3.6874995" PointY="3.4321907552083331" />
+ <ConnectorPoint PointX="3.6874995" PointY="4.005208333333333" />
+ <ConnectorPoint PointX="4.5" PointY="4.005208333333333" />
+ </AssociationConnector>
+ <EntityTypeShape EntityType="DatabaseModel.IssuedRequestToken" Width="2" PointX="4.25" PointY="6.25" Height="1.5956835937499996" />
+ <EntityTypeShape EntityType="DatabaseModel.IssuedAccessToken" Width="1.625" PointX="6.5" PointY="6.25" Height="1.2110807291666657" />
+ <InheritanceConnector EntityType="DatabaseModel.IssuedRequestToken">
+ <ConnectorPoint PointX="5.375" PointY="5.797587890625" />
+ <ConnectorPoint PointX="5.375" PointY="6.25" /></InheritanceConnector>
+ <InheritanceConnector EntityType="DatabaseModel.IssuedAccessToken">
+ <ConnectorPoint PointX="6.5" PointY="4.7112939453125" />
+ <ConnectorPoint PointX="7.34375" PointY="4.7112939453125" />
+ <ConnectorPoint PointX="7.34375" PointY="6.25" /></InheritanceConnector></Diagram></edmx:Diagrams>
+ </edmx:Designer>
+</edmx:Edmx> \ No newline at end of file
diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs
new file mode 100644
index 0000000..e47e4ee
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs
@@ -0,0 +1,78 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthAuthenticationModule.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Security.Principal;
+ using System.Web;
+ using System.Web.Security;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+ using DotNetOpenAuth.OAuth.Messages;
+
+ public class OAuthAuthenticationModule : IHttpModule {
+ private HttpApplication application;
+
+ #region IHttpModule Members
+
+ /// <summary>
+ /// Initializes a module and prepares it to handle requests.
+ /// </summary>
+ /// <param name="context">An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application</param>
+ public void Init(HttpApplication context) {
+ this.application = context;
+ this.application.AuthenticateRequest += this.context_AuthenticateRequest;
+
+ // Register an event that allows us to override roles for OAuth requests.
+ var roleManager = (RoleManagerModule)this.application.Modules["RoleManager"];
+ roleManager.GetRoles += this.roleManager_GetRoles;
+ }
+
+ /// <summary>
+ /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
+ /// </summary>
+ public void Dispose() {
+ }
+
+ /// <summary>
+ /// Handles the AuthenticateRequest event of the HttpApplication.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
+ private void context_AuthenticateRequest(object sender, EventArgs e) {
+ // Don't read OAuth messages directed at the OAuth controller or else we'll fail nonce checks.
+ if (this.IsOAuthControllerRequest()) {
+ return;
+ }
+
+ IDirectedProtocolMessage incomingMessage = OAuthServiceProvider.ServiceProvider.ReadRequest(new HttpRequestInfo(this.application.Context.Request));
+ var authorization = incomingMessage as AccessProtectedResourceRequest;
+ if (authorization != null) {
+ this.application.Context.User = OAuthServiceProvider.ServiceProvider.CreatePrincipal(authorization);
+ }
+ }
+
+ #endregion
+
+ private bool IsOAuthControllerRequest() {
+ return string.Equals(this.application.Context.Request.Url.AbsolutePath, "/OAuth.ashx", StringComparison.OrdinalIgnoreCase);
+ }
+
+ /// <summary>
+ /// Handles the GetRoles event of the roleManager control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="System.Web.Security.RoleManagerEventArgs"/> instance containing the event data.</param>
+ private void roleManager_GetRoles(object sender, RoleManagerEventArgs e) {
+ if (this.application.User is OAuthPrincipal) {
+ e.RolesPopulated = true;
+ }
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs
new file mode 100644
index 0000000..752e2eb
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs
@@ -0,0 +1,67 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthAuthorizationManager.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ 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["OriginalHttpRequestUri"] as Uri;
+ ServiceProvider sp = OAuthServiceProvider.ServiceProvider;
+ var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri);
+ if (auth != null) {
+ var accessToken = Database.DataContext.IssuedToken.OfType<IssuedAccessToken>().First(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;
+ }
+ }
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs b/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs
new file mode 100644
index 0000000..64e6be8
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs
@@ -0,0 +1,48 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthConsumerTokenManager.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ public class OAuthConsumerTokenManager : OAuthTokenManager, IConsumerTokenManager {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OAuthConsumerTokenManager"/> class.
+ /// </summary>
+ /// <param name="consumerKey">The consumer key.</param>
+ /// <param name="consumerSecret">The consumer secret.</param>
+ public OAuthConsumerTokenManager(string consumerKey, string consumerSecret) {
+ if (String.IsNullOrEmpty(consumerKey)) {
+ throw new ArgumentNullException("consumerKey");
+ }
+ if (consumerSecret == null) {
+ throw new ArgumentNullException("consumerSecret");
+ }
+
+ this.ConsumerKey = consumerKey;
+ this.ConsumerSecret = consumerSecret;
+ }
+
+ #region IConsumerTokenManager Members
+
+ /// <summary>
+ /// Gets the consumer key.
+ /// </summary>
+ /// <value>The consumer key.</value>
+ public string ConsumerKey { get; private set; }
+
+ /// <summary>
+ /// Gets the consumer secret.
+ /// </summary>
+ /// <value>The consumer secret.</value>
+ public string ConsumerSecret { get; private set; }
+
+ #endregion
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs b/projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs
new file mode 100644
index 0000000..ddd0b3f
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs
@@ -0,0 +1,53 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthPrincipalAuthorizationPolicy.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ 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/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs b/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs
new file mode 100644
index 0000000..8d582ab
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs
@@ -0,0 +1,120 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthServiceProvider.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+ using DotNetOpenAuth.OAuth.Messages;
+
+ public class OAuthServiceProvider {
+ private const string PendingAuthorizationRequestSessionKey = "PendingAuthorizationRequest";
+
+ /// <summary>
+ /// The shared service description for this web site.
+ /// </summary>
+ private static ServiceProviderDescription serviceDescription;
+
+ private static OAuthServiceProviderTokenManager tokenManager;
+
+ /// <summary>
+ /// The shared service provider object.
+ /// </summary>
+ private static ServiceProvider serviceProvider;
+
+ /// <summary>
+ /// The lock to synchronize initialization of the <see cref="serviceProvider"/> field.
+ /// </summary>
+ private static object initializerLock = new object();
+
+ /// <summary>
+ /// Gets the service provider.
+ /// </summary>
+ /// <value>The service provider.</value>
+ public static ServiceProvider ServiceProvider {
+ get {
+ EnsureInitialized();
+ return serviceProvider;
+ }
+ }
+
+ /// <summary>
+ /// Gets the service description.
+ /// </summary>
+ /// <value>The service description.</value>
+ public static ServiceProviderDescription ServiceDescription {
+ get {
+ EnsureInitialized();
+ return serviceDescription;
+ }
+ }
+
+ public static UserAuthorizationRequest PendingAuthorizationRequest {
+ get { return HttpContext.Current.Session[PendingAuthorizationRequestSessionKey] as UserAuthorizationRequest; }
+ set { HttpContext.Current.Session[PendingAuthorizationRequestSessionKey] = value; }
+ }
+
+ public static Consumer PendingAuthorizationConsumer {
+ get {
+ ITokenContainingMessage message = PendingAuthorizationRequest;
+ if (message == null) {
+ throw new InvalidOperationException();
+ }
+
+ return Database.DataContext.IssuedToken.OfType<IssuedRequestToken>().Include("Consumer").First(t => t.Token == message.Token).Consumer;
+ }
+ }
+
+ public static void AuthorizePendingRequestToken() {
+ var pendingRequest = PendingAuthorizationRequest;
+ if (pendingRequest == null) {
+ throw new InvalidOperationException("No pending authorization request to authorize.");
+ }
+
+ ITokenContainingMessage msg = pendingRequest;
+ var token = Database.DataContext.IssuedToken.OfType<IssuedRequestToken>().First(t => t.Token == msg.Token);
+ token.Authorize();
+
+ PendingAuthorizationRequest = null;
+ var response = serviceProvider.PrepareAuthorizationResponse(pendingRequest);
+ if (response != null) {
+ serviceProvider.Channel.Send(response);
+ }
+ }
+
+ /// <summary>
+ /// Initializes the <see cref="serviceProvider"/> field if it has not yet been initialized.
+ /// </summary>
+ private static void EnsureInitialized() {
+ if (serviceProvider == null) {
+ lock (initializerLock) {
+ if (serviceDescription == null) {
+ var postEndpoint = new MessageReceivingEndpoint(new Uri(Utilities.ApplicationRoot, "OAuth.ashx"), HttpDeliveryMethods.PostRequest);
+ var getEndpoint = new MessageReceivingEndpoint(postEndpoint.Location, HttpDeliveryMethods.GetRequest);
+ serviceDescription = new ServiceProviderDescription {
+ TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
+ RequestTokenEndpoint = postEndpoint,
+ AccessTokenEndpoint = postEndpoint,
+ UserAuthorizationEndpoint = getEndpoint,
+ };
+ }
+
+ if (tokenManager == null) {
+ tokenManager = new OAuthServiceProviderTokenManager();
+ }
+
+ if (serviceProvider == null) {
+ serviceProvider = new ServiceProvider(serviceDescription, tokenManager);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs b/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs
new file mode 100644
index 0000000..be53180
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs
@@ -0,0 +1,112 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthServiceProviderTokenManager.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ public class OAuthServiceProviderTokenManager : OAuthTokenManager, IServiceProviderTokenManager {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OAuthServiceProviderTokenManager"/> class.
+ /// </summary>
+ public OAuthServiceProviderTokenManager() {
+ }
+
+ #region IServiceProviderTokenManager Members
+
+ /// <summary>
+ /// Gets the Consumer description for a given a Consumer Key.
+ /// </summary>
+ /// <param name="consumerKey">The Consumer Key.</param>
+ /// <returns>
+ /// A description of the consumer. Never null.
+ /// </returns>
+ /// <exception cref="KeyNotFoundException">Thrown if the consumer key cannot be found.</exception>
+ public IConsumerDescription GetConsumer(string consumerKey) {
+ try {
+ return Database.DataContext.Consumer.First(c => c.ConsumerKey == consumerKey);
+ } catch (InvalidOperationException) {
+ throw new KeyNotFoundException();
+ }
+ }
+
+ /// <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 Database.DataContext.IssuedToken.OfType<IssuedRequestToken>().Any(
+ t => t.Token == requestToken && t.User != null);
+ }
+
+ /// <summary>
+ /// Gets details on the named request token.
+ /// </summary>
+ /// <param name="token">The request token.</param>
+ /// <returns>A description of the token. Never null.</returns>
+ /// <exception cref="KeyNotFoundException">Thrown if the token cannot be found.</exception>
+ /// <remarks>
+ /// It is acceptable for implementations to find the token, see that it has expired,
+ /// delete it from the database and then throw <see cref="KeyNotFoundException"/>,
+ /// or alternatively it can return the expired token anyway and the OAuth channel will
+ /// log and throw the appropriate error.
+ /// </remarks>
+ public IServiceProviderRequestToken GetRequestToken(string token) {
+ try {
+ return Database.DataContext.IssuedToken.OfType<IssuedRequestToken>().First(tok => tok.Token == token);
+ } catch (InvalidOperationException) {
+ throw new KeyNotFoundException();
+ }
+ }
+
+ /// <summary>
+ /// Gets details on the named access token.
+ /// </summary>
+ /// <param name="token">The access token.</param>
+ /// <returns>A description of the token. Never null.</returns>
+ /// <exception cref="KeyNotFoundException">Thrown if the token cannot be found.</exception>
+ /// <remarks>
+ /// It is acceptable for implementations to find the token, see that it has expired,
+ /// delete it from the database and then throw <see cref="KeyNotFoundException"/>,
+ /// or alternatively it can return the expired token anyway and the OAuth channel will
+ /// log and throw the appropriate error.
+ /// </remarks>
+ public IServiceProviderAccessToken GetAccessToken(string token) {
+ try {
+ return Database.DataContext.IssuedToken.OfType<IssuedAccessToken>().First(tok => tok.Token == token);
+ } catch (InvalidOperationException) {
+ throw new KeyNotFoundException();
+ }
+ }
+
+ /// <summary>
+ /// Persists any changes made to the token.
+ /// </summary>
+ /// <param name="token">The token whose properties have been changed.</param>
+ /// <remarks>
+ /// This library will invoke this method after making a set
+ /// of changes to the token as part of a web request to give the host
+ /// the opportunity to persist those changes to a database.
+ /// Depending on the object persistence framework the host site uses,
+ /// this method MAY not need to do anything (if changes made to the token
+ /// will automatically be saved without any extra handling).
+ /// </remarks>
+ public void UpdateToken(IServiceProviderRequestToken token) {
+ Database.DataContext.SaveChanges();
+ }
+
+ #endregion
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/OAuthTokenManager.cs b/projecttemplates/RelyingPartyLogic/OAuthTokenManager.cs
new file mode 100644
index 0000000..fbba776
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/OAuthTokenManager.cs
@@ -0,0 +1,143 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthTokenManager.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Security.Cryptography.X509Certificates;
+ using System.Web;
+ using DotNetOpenAuth.OAuth;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+ using DotNetOpenAuth.OAuth.Messages;
+
+ /// <summary>
+ /// The token manager this web site uses in its roles both as
+ /// a consumer and as a service provider.
+ /// </summary>
+ public class OAuthTokenManager : ITokenManager {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OAuthTokenManager"/> class.
+ /// </summary>
+ protected OAuthTokenManager() {
+ }
+
+ #region ITokenManager Members
+
+ /// <summary>
+ /// Gets the Token Secret given a request or access token.
+ /// </summary>
+ /// <param name="token">The request or access token.</param>
+ /// <returns>
+ /// The secret associated with the given token.
+ /// </returns>
+ /// <exception cref="ArgumentException">Thrown if the secret cannot be found for the given token.</exception>
+ public string GetTokenSecret(string token) {
+ try {
+ return Database.DataContext.IssuedToken.First(t => t.Token == token).TokenSecret;
+ } catch (InvalidOperationException) {
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ /// <summary>
+ /// Stores a newly generated unauthorized request token, secret, and optional
+ /// application-specific parameters for later recall.
+ /// </summary>
+ /// <param name="request">The request message that resulted in the generation of a new unauthorized request token.</param>
+ /// <param name="response">The response message that includes the unauthorized request token.</param>
+ /// <exception cref="ArgumentException">Thrown if the consumer key is not registered, or a required parameter was not found in the parameters collection.</exception>
+ /// <remarks>
+ /// Request tokens stored by this method SHOULD NOT associate any user account with this token.
+ /// It usually opens up security holes in your application to do so. Instead, you associate a user
+ /// account with access tokens (not request tokens) in the <see cref="ExpireRequestTokenAndStoreNewAccessToken"/>
+ /// method.
+ /// </remarks>
+ public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response) {
+ Consumer consumer;
+ try {
+ consumer = Database.DataContext.Consumer.First(c => c.ConsumerKey == request.ConsumerKey);
+ } catch (InvalidOperationException) {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ var token = new IssuedRequestToken {
+ Callback = request.Callback,
+ Consumer = consumer,
+ CreatedOn = DateTime.Now,
+ Token = response.Token,
+ TokenSecret = response.TokenSecret,
+ };
+ string scope;
+ if (request.ExtraData.TryGetValue("scope", out scope)) {
+ token.Scope = scope;
+ }
+ Database.DataContext.AddToIssuedToken(token);
+ Database.DataContext.SaveChanges();
+ }
+
+ /// <summary>
+ /// Deletes a request token and its associated secret and stores a new access token and secret.
+ /// </summary>
+ /// <param name="consumerKey">The Consumer that is exchanging its request token for an access token.</param>
+ /// <param name="requestToken">The Consumer's request token that should be deleted/expired.</param>
+ /// <param name="accessToken">The new access token that is being issued to the Consumer.</param>
+ /// <param name="accessTokenSecret">The secret associated with the newly issued access token.</param>
+ /// <remarks>
+ /// <para>
+ /// Any scope of granted privileges associated with the request token from the
+ /// original call to <see cref="StoreNewRequestToken"/> should be carried over
+ /// to the new Access Token.
+ /// </para>
+ /// <para>
+ /// To associate a user account with the new access token,
+ /// <see cref="System.Web.HttpContext.User">HttpContext.Current.User</see> may be
+ /// useful in an ASP.NET web application within the implementation of this method.
+ /// Alternatively you may store the access token here without associating with a user account,
+ /// and wait until <see cref="WebConsumer.ProcessUserAuthorization()"/> or
+ /// <see cref="DesktopConsumer.ProcessUserAuthorization(string, string)"/> return the access
+ /// token to associate the access token with a user account at that point.
+ /// </para>
+ /// </remarks>
+ public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) {
+ var requestTokenEntity = Database.DataContext.IssuedToken.OfType<IssuedRequestToken>()
+ .Include("User")
+ .First(t => t.Consumer.ConsumerKey == consumerKey && t.Token == requestToken);
+
+ var accessTokenEntity = new IssuedAccessToken {
+ Token = accessToken,
+ TokenSecret = accessTokenSecret,
+ ExpirationDate = null, // currently, our access tokens don't expire
+ CreatedOn = DateTime.Now,
+ User = requestTokenEntity.User,
+ Scope = requestTokenEntity.Scope,
+ Consumer = requestTokenEntity.Consumer,
+ };
+
+ Database.DataContext.DeleteObject(requestTokenEntity);
+ Database.DataContext.AddToIssuedToken(accessTokenEntity);
+ Database.DataContext.SaveChanges();
+ }
+
+ /// <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) {
+ IssuedToken tok = Database.DataContext.IssuedToken.FirstOrDefault(t => t.Token == token);
+ if (tok == null) {
+ return TokenType.InvalidToken;
+ } else {
+ return tok is IssuedAccessToken ? TokenType.AccessToken : TokenType.RequestToken;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Policies.cs b/projecttemplates/RelyingPartyLogic/Policies.cs
new file mode 100644
index 0000000..6bf72d3
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Policies.cs
@@ -0,0 +1,23 @@
+//-----------------------------------------------------------------------
+// <copyright file="Policies.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+
+ public class Policies {
+ /// <summary>
+ /// The set of OP Endpoints that we trust pre-verify email addresses before sending them
+ /// with positive assertions.
+ /// </summary>
+ public static readonly Uri[] ProviderEndpointsProvidingTrustedEmails = new Uri[] {
+ new Uri("https://www.google.com/accounts/o8/ud"),
+ new Uri("https://open.login.yahooapis.com/openid/op/auth"),
+ };
+ }
+}
diff --git a/projecttemplates/RelyingPartyLogic/Properties/AssemblyInfo.cs b/projecttemplates/RelyingPartyLogic/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8cb040c
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+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("RelyingPartyLogic")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft IT")]
+[assembly: AssemblyProduct("RelyingPartyLogic")]
+[assembly: AssemblyCopyright("Copyright © Microsoft IT 2009")]
+[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("86d51499-3206-4eea-9bfe-b7950dac606b")]
+
+// 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 Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj
new file mode 100644
index 0000000..7000e2b
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{17932639-1F50-48AF-B0A5-E2BF832F82CC}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>RelyingPartyLogic</RootNamespace>
+ <AssemblyName>RelyingPartyLogic</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</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\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\lib\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.SqlServer.ConnectionInfo" />
+ <Reference Include="Microsoft.SqlServer.Smo" />
+ <Reference Include="Microsoft.SqlServer.Management.Sdk.Sfc" />
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.Entity">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.IdentityModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Runtime.Serialization">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Security" />
+ <Reference Include="System.ServiceModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Windows\assembly\GAC_MSIL\System.Web.Entity\3.5.0.0__b77a5c561934e089\System.Web.Entity.dll</HintPath>
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web.Extensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <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>
+ <Compile Include="Database.cs" />
+ <Compile Include="DataRoleProvider.cs" />
+ <Compile Include="Model.AuthenticationToken.cs" />
+ <Compile Include="Model.Consumer.cs" />
+ <Compile Include="Model.Designer.cs">
+ <DependentUpon>Model.edmx</DependentUpon>
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ </Compile>
+ <Compile Include="Model.IssuedAccessToken.cs" />
+ <Compile Include="Model.IssuedRequestToken.cs" />
+ <Compile Include="Model.User.cs" />
+ <Compile Include="OAuthAuthenticationModule.cs" />
+ <Compile Include="OAuthAuthorizationManager.cs" />
+ <Compile Include="OAuthConsumerTokenManager.cs" />
+ <Compile Include="OAuthPrincipalAuthorizationPolicy.cs" />
+ <Compile Include="OAuthServiceProvider.cs" />
+ <Compile Include="OAuthServiceProviderTokenManager.cs" />
+ <Compile Include="OAuthTokenManager.cs" />
+ <Compile Include="Policies.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Utilities.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EntityDeploy Include="Model.edmx">
+ <Generator>EntityModelCodeGenerator</Generator>
+ <LastGenOutput>Model.Designer.cs</LastGenOutput>
+ </EntityDeploy>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\src\DotNetOpenAuth\DotNetOpenAuth.csproj">
+ <Project>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</Project>
+ <Name>DotNetOpenAuth</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="CreateDatabase.sql" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- 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>
+ -->
+</Project> \ No newline at end of file
diff --git a/projecttemplates/RelyingPartyLogic/Utilities.cs b/projecttemplates/RelyingPartyLogic/Utilities.cs
new file mode 100644
index 0000000..02eb273
--- /dev/null
+++ b/projecttemplates/RelyingPartyLogic/Utilities.cs
@@ -0,0 +1,64 @@
+//-----------------------------------------------------------------------
+// <copyright file="Utilities.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace RelyingPartyLogic {
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.IO;
+ using System.Linq;
+ using System.Reflection;
+ using System.Text;
+ using System.Web;
+ using DotNetOpenAuth.OpenId;
+ using Microsoft.SqlServer.Management.Common;
+ using Microsoft.SqlServer.Management.Smo;
+
+ public class Utilities {
+ internal const string DefaultNamespace = "RelyingPartyLogic";
+
+ /// <summary>
+ /// Gets the full URI of the web application root. Guaranteed to end in a slash.
+ /// </summary>
+ public static Uri ApplicationRoot {
+ get {
+ string appRoot = HttpContext.Current.Request.ApplicationPath;
+ if (!appRoot.EndsWith("/", StringComparison.Ordinal)) {
+ appRoot += "/";
+ }
+
+ return new Uri(HttpContext.Current.Request.Url, appRoot);
+ }
+ }
+
+ public static void CreateDatabase(Identifier claimedId, string friendlyId) {
+ const string SqlFormat = @"
+CREATE DATABASE [{0}] ON (NAME='{0}', FILENAME='{0}')
+GO
+USE ""{0}""
+GO
+{1}
+EXEC [dbo].[AddUser] 'admin', 'admin', '{2}', '{3}'
+GO
+";
+ string schemaSql;
+ using (var sr = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(DefaultNamespace + ".CreateDatabase.sql"))) {
+ schemaSql = sr.ReadToEnd();
+ }
+ string databasePath = HttpContext.Current.Server.MapPath("~/App_Data/Database.mdf");
+ string sql = string.Format(CultureInfo.InvariantCulture, SqlFormat, databasePath, schemaSql, claimedId, "Admin");
+
+ var serverConnection = new ServerConnection(".\\sqlexpress");
+ try {
+ serverConnection.ExecuteNonQuery(sql);
+ var server = new Server(serverConnection);
+ server.DetachDatabase(databasePath, true);
+ } finally {
+ serverConnection.Disconnect();
+ }
+ }
+ }
+}