diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2010-07-17 22:04:56 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2010-07-17 22:04:56 -0700 |
commit | 7c86d53eac655514ac0c8b7c8ede95c0af5798fb (patch) | |
tree | 390b5c5a1f695812aa61c2fdfa845e4fe0ae3590 | |
parent | 3ab1adf5a949a5799f6a7fee377ae3c7e77ec69a (diff) | |
parent | 17c604a07b35bcfd3a77299777521f04063bd6ae (diff) | |
download | DotNetOpenAuth-7c86d53eac655514ac0c8b7c8ede95c0af5798fb.zip DotNetOpenAuth-7c86d53eac655514ac0c8b7c8ede95c0af5798fb.tar.gz DotNetOpenAuth-7c86d53eac655514ac0c8b7c8ede95c0af5798fb.tar.bz2 |
Merge branch 'oauth2templates' into oauth2
83 files changed, 1781 insertions, 2087 deletions
diff --git a/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs b/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs index a322f7d..8e35f37 100644 --- a/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs +++ b/projecttemplates/MvcRelyingParty/Controllers/AccountController.cs @@ -50,13 +50,21 @@ [Authorize] public ActionResult Authorize() { - if (OAuthServiceProvider.PendingAuthorizationRequest == null) { + var pendingRequest = OAuthServiceProvider.AuthorizationServer.ReadAuthorizationRequest(); + if (pendingRequest == null) { return RedirectToAction("Edit"); } + var requestingClient = Database.DataContext.Clients.First(c => c.ClientIdentifier == pendingRequest.ClientIdentifier); + + // Consider auto-approving if safe to do so. + if (((OAuthAuthorizationServer)OAuthServiceProvider.AuthorizationServer.AuthorizationServer).CanBeAutoApproved(pendingRequest)) { + OAuthServiceProvider.AuthorizationServer.ApproveAuthorizationRequest(pendingRequest, HttpContext.User.Identity.Name); + } + var model = new AccountAuthorizeModel { - ConsumerApp = OAuthServiceProvider.PendingAuthorizationConsumer.Name, - IsUnsafeRequest = OAuthServiceProvider.PendingAuthorizationRequest.IsUnsafeRequest, + ClientApp = requestingClient.Name, + Scope = pendingRequest.Scope, }; return View(model); @@ -64,43 +72,30 @@ [Authorize, AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken] public ActionResult Authorize(bool isApproved) { + var getRequest = new HttpRequestInfo("GET", this.Request.Url, this.Request.RawUrl, new WebHeaderCollection(), null); + var pendingRequest = OAuthServiceProvider.AuthorizationServer.ReadAuthorizationRequest(getRequest); + var requestingClient = Database.DataContext.Clients.First(c => c.ClientIdentifier == pendingRequest.ClientIdentifier); + + IDirectedProtocolMessage response; if (isApproved) { - var consumer = OAuthServiceProvider.PendingAuthorizationConsumer; - var tokenManager = OAuthServiceProvider.ServiceProvider.TokenManager; - var pendingRequest = OAuthServiceProvider.PendingAuthorizationRequest; - ITokenContainingMessage requestTokenMessage = pendingRequest; - var requestToken = tokenManager.GetRequestToken(requestTokenMessage.Token); - - var response = OAuthServiceProvider.AuthorizePendingRequestTokenAsWebResponse(); - if (response != null) { - // The consumer provided a callback URL that can take care of everything else. - return response.AsActionResult(); - } - - var model = new AccountAuthorizeModel { - ConsumerApp = consumer.Name, - }; - - if (!pendingRequest.IsUnsafeRequest) { - model.VerificationCode = ServiceProvider.CreateVerificationCode(consumer.VerificationCodeFormat, consumer.VerificationCodeLength); - requestToken.VerificationCode = model.VerificationCode; - tokenManager.UpdateToken(requestToken); - } - - return View("AuthorizeApproved", model); + Database.LoggedInUser.ClientAuthorizations.Add( + new ClientAuthorization { + Client = requestingClient, + Scope = pendingRequest.Scope, + User = Database.LoggedInUser, + CreatedOnUtc = DateTime.UtcNow.CutToSecond(), + }); + response = OAuthServiceProvider.AuthorizationServer.PrepareApproveAuthorizationRequest(pendingRequest, HttpContext.User.Identity.Name); } else { - OAuthServiceProvider.PendingAuthorizationRequest = null; - return View("AuthorizeDenied"); + response = OAuthServiceProvider.AuthorizationServer.PrepareRejectAuthorizationRequest(pendingRequest); } + + return OAuthServiceProvider.AuthorizationServer.Channel.PrepareResponse(response).AsActionResult(); } [Authorize, AcceptVerbs(HttpVerbs.Delete)] // ValidateAntiForgeryToken would be GREAT here, but it's not a FORM POST operation so that doesn't work. - public ActionResult RevokeToken(string token) { - if (String.IsNullOrEmpty(token)) { - throw new ArgumentNullException("token"); - } - - var tokenEntity = Database.DataContext.IssuedTokens.OfType<IssuedAccessToken>().Where(t => t.User.UserId == Database.LoggedInUser.UserId && t.Token == token).FirstOrDefault(); + public ActionResult RevokeAuthorization(int authorizationId) { + var tokenEntity = Database.DataContext.ClientAuthorizations.Where(auth => auth.User.UserId == Database.LoggedInUser.UserId && auth.AuthorizationId == authorizationId).FirstOrDefault(); if (tokenEntity == null) { throw new ArgumentOutOfRangeException("id", "The logged in user does not have a token with this name to revoke."); } @@ -112,9 +107,9 @@ } private static AccountInfoModel GetAccountInfoModel() { - var authorizedApps = from token in Database.DataContext.IssuedTokens.OfType<IssuedAccessToken>() - where token.User.UserId == Database.LoggedInUser.UserId - select new AccountInfoModel.AuthorizedApp { AppName = token.Consumer.Name, Token = token.Token }; + var authorizedApps = from auth in Database.DataContext.ClientAuthorizations + where auth.User.UserId == Database.LoggedInUser.UserId + select new AccountInfoModel.AuthorizedApp { AppName = auth.Client.Name, AuthorizationId = auth.AuthorizationId, Scope = auth.Scope }; Database.LoggedInUser.AuthenticationTokens.Load(); var model = new AccountInfoModel { FirstName = Database.LoggedInUser.FirstName, diff --git a/projecttemplates/MvcRelyingParty/Models/AccountAuthorizeModel.cs b/projecttemplates/MvcRelyingParty/Models/AccountAuthorizeModel.cs index 0fbd9f4..7cedabd 100644 --- a/projecttemplates/MvcRelyingParty/Models/AccountAuthorizeModel.cs +++ b/projecttemplates/MvcRelyingParty/Models/AccountAuthorizeModel.cs @@ -5,10 +5,8 @@ using System.Web; public class AccountAuthorizeModel { - public string ConsumerApp { get; set; } + public string ClientApp { get; set; } - public bool IsUnsafeRequest { get; set; } - - public string VerificationCode { get; set; } + public string Scope { get; set; } } } diff --git a/projecttemplates/MvcRelyingParty/Models/AccountInfoModel.cs b/projecttemplates/MvcRelyingParty/Models/AccountInfoModel.cs index 787b8df..6e005c4 100644 --- a/projecttemplates/MvcRelyingParty/Models/AccountInfoModel.cs +++ b/projecttemplates/MvcRelyingParty/Models/AccountInfoModel.cs @@ -17,9 +17,11 @@ public IList<AuthenticationToken> AuthenticationTokens { get; set; } public class AuthorizedApp { - public string Token { get; set; } + public int AuthorizationId { get; set; } public string AppName { get; set; } + + public string Scope { get; set; } } } } diff --git a/projecttemplates/MvcRelyingParty/MvcRelyingParty.csproj b/projecttemplates/MvcRelyingParty/MvcRelyingParty.csproj index 540b702..6378402 100644 --- a/projecttemplates/MvcRelyingParty/MvcRelyingParty.csproj +++ b/projecttemplates/MvcRelyingParty/MvcRelyingParty.csproj @@ -83,8 +83,8 @@ </Compile> <Compile Include="Models\AccountAuthorizeModel.cs" /> <Compile Include="Models\AccountInfoModel.cs" /> - <Compile Include="OAuth.ashx.cs"> - <DependentUpon>OAuth.ashx</DependentUpon> + <Compile Include="OAuthTokenEndpoint.ashx.cs"> + <DependentUpon>OAuthTokenEndpoint.ashx</DependentUpon> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Setup.aspx.cs"> @@ -175,16 +175,16 @@ </ItemGroup> <ItemGroup> <Content Include="Content\images\infocard_23x16.png" /> - <Content Include="OAuth.ashx" /> <Content Include="Views\Account\AuthenticationTokens.ascx" /> <Content Include="Views\Account\Authorize.aspx" /> - <Content Include="Views\Account\AuthorizeApproved.aspx" /> <Content Include="Views\Account\AuthorizedApps.ascx" /> - <Content Include="Views\Account\AuthorizeDenied.aspx" /> </ItemGroup> <ItemGroup> <Folder Include="App_Data\" /> </ItemGroup> + <ItemGroup> + <Content Include="OAuthTokenEndpoint.ashx" /> + </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. diff --git a/projecttemplates/MvcRelyingParty/OAuth.ashx b/projecttemplates/MvcRelyingParty/OAuth.ashx deleted file mode 100644 index 81b3d52..0000000 --- a/projecttemplates/MvcRelyingParty/OAuth.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="OAuth.ashx.cs" Class="MvcRelyingParty.OAuth" %> diff --git a/projecttemplates/MvcRelyingParty/OAuth.ashx.cs b/projecttemplates/MvcRelyingParty/OAuth.ashx.cs deleted file mode 100644 index b9051c1..0000000 --- a/projecttemplates/MvcRelyingParty/OAuth.ashx.cs +++ /dev/null @@ -1,66 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuth.ashx.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace MvcRelyingParty { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Web; - using System.Web.SessionState; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OAuth; - using DotNetOpenAuth.OAuth.Messages; - using RelyingPartyLogic; - - /// <summary> - /// Responds to incoming OAuth Service Provider messages. - /// </summary> - public class OAuth : IHttpHandler, IRequiresSessionState { - /// <summary> - /// Initializes a new instance of the <see cref="OAuth"/> class. - /// </summary> - public OAuth() { - } - - /// <summary> - /// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"/> instance. - /// </summary> - /// <returns> - /// true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false. - /// </returns> - public bool IsReusable { - get { return true; } - } - - /// <summary> - /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface. - /// </summary> - /// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> - public void ProcessRequest(HttpContext context) { - var serviceProvider = OAuthServiceProvider.ServiceProvider; - var requestMessage = serviceProvider.ReadRequest(new HttpRequestInfo(context.Request)); - - UnauthorizedTokenRequest unauthorizedTokenRequestMessage; - AuthorizedTokenRequest authorizedTokenRequestMessage; - UserAuthorizationRequest userAuthorizationRequest; - if ((unauthorizedTokenRequestMessage = requestMessage as UnauthorizedTokenRequest) != null) { - var response = serviceProvider.PrepareUnauthorizedTokenMessage(unauthorizedTokenRequestMessage); - serviceProvider.Channel.Send(response); - } else if ((authorizedTokenRequestMessage = requestMessage as AuthorizedTokenRequest) != null) { - var response = serviceProvider.PrepareAccessTokenMessage(authorizedTokenRequestMessage); - serviceProvider.Channel.Send(response); - } else if ((userAuthorizationRequest = requestMessage as UserAuthorizationRequest) != null) { - // This is a browser opening to allow the user to authorize a request token, - // so redirect to the authorization page, which will automatically redirect - // to have the user log in if necessary. - OAuthServiceProvider.PendingAuthorizationRequest = userAuthorizationRequest; - HttpContext.Current.Response.Redirect("~/Account/Authorize"); - } else { - throw new InvalidOperationException(); - } - } - } -} diff --git a/projecttemplates/MvcRelyingParty/OAuthTokenEndpoint.ashx b/projecttemplates/MvcRelyingParty/OAuthTokenEndpoint.ashx new file mode 100644 index 0000000..dc12aeb --- /dev/null +++ b/projecttemplates/MvcRelyingParty/OAuthTokenEndpoint.ashx @@ -0,0 +1 @@ +<%@ WebHandler Language="C#" CodeBehind="OAuthTokenEndpoint.ashx.cs" Class="MvcRelyingParty.OAuthTokenEndpoint" %> diff --git a/projecttemplates/MvcRelyingParty/OAuthTokenEndpoint.ashx.cs b/projecttemplates/MvcRelyingParty/OAuthTokenEndpoint.ashx.cs new file mode 100644 index 0000000..89e55d5 --- /dev/null +++ b/projecttemplates/MvcRelyingParty/OAuthTokenEndpoint.ashx.cs @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthTokenEndpoint.ashx.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace MvcRelyingParty { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using System.Web.SessionState; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth2; + using RelyingPartyLogic; + + /// <summary> + /// An OAuth 2.0 token endpoint. + /// </summary> + public class OAuthTokenEndpoint : IHttpHandler, IRequiresSessionState { + /// <summary> + /// Initializes a new instance of the <see cref="OAuthTokenEndpoint"/> class. + /// </summary> + public OAuthTokenEndpoint() { + } + + /// <summary> + /// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"/> instance. + /// </summary> + /// <returns> + /// true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false. + /// </returns> + public bool IsReusable { + get { return true; } + } + + /// <summary> + /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface. + /// </summary> + /// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> + public void ProcessRequest(HttpContext context) { + var serviceProvider = OAuthServiceProvider.AuthorizationServer; + IDirectResponseProtocolMessage response; + if (serviceProvider.TryPrepareAccessTokenResponse(new HttpRequestInfo(context.Request), out response)) { + serviceProvider.Channel.Send(response); + } else { + throw new InvalidOperationException(); + } + } + } +} diff --git a/projecttemplates/MvcRelyingParty/Views/Account/Authorize.aspx b/projecttemplates/MvcRelyingParty/Views/Account/Authorize.aspx index e8eaaaa..4130a45 100644 --- a/projecttemplates/MvcRelyingParty/Views/Account/Authorize.aspx +++ b/projecttemplates/MvcRelyingParty/Views/Account/Authorize.aspx @@ -12,11 +12,15 @@ </div> <p> The - <%= Html.Encode(Model.ConsumerApp) %> + <%= Html.Encode(Model.ClientApp) %> application is requesting to access the private data in your account here. Is that alright with you? </p> <p> + <b>Requested access: </b> + <%= Html.Encode(Model.Scope) %> + </p> + <p> If you grant access now, you can revoke it at any time by returning to <%= Html.ActionLink("your account page", "Edit") %>. </p> @@ -31,18 +35,6 @@ <b>Javascript appears to be disabled in your browser. </b>This page requires Javascript to be enabled to better protect your security. </div> - <% if (Model.IsUnsafeRequest) { %> - <div style="background-color: red; color: white; font-weight: bold"> - This website is registered with - <asp:Label runat="server" ID="serviceProviderDomainNameLabel" /> - to make authorization requests, but has not been configured to send requests securely. - If you grant access but you did not initiate this request at - <%= Html.Encode(Model.ConsumerApp) %>, it may be possible for other users of - <%= Html.Encode(Model.ConsumerApp) %> - to access your data. We recommend you deny access unless you are certain that you - initiated this request directly with - <%= Html.Encode(Model.ConsumerApp) %>. - <% } %> <script language="javascript" type="text/javascript"> //<![CDATA[ diff --git a/projecttemplates/MvcRelyingParty/Views/Account/AuthorizeApproved.aspx b/projecttemplates/MvcRelyingParty/Views/Account/AuthorizeApproved.aspx deleted file mode 100644 index a2d91b0..0000000 --- a/projecttemplates/MvcRelyingParty/Views/Account/AuthorizeApproved.aspx +++ /dev/null @@ -1,24 +0,0 @@ -<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcRelyingParty.Models.AccountAuthorizeModel>" %> - -<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> - Authorized -</asp:Content> -<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> - <h2> - Authorized - </h2> - <p> - Authorization has been granted. - </p> - <% if (!string.IsNullOrEmpty(Model.VerificationCode)) { %> - <p> - You must enter this verification code at the Consumer: <b> - <%= Html.Encode(Model.VerificationCode)%> - </b> - </p> - <% } else { %> - <p> - You may now close this window and return to the Consumer. - </p> - <% } %> -</asp:Content> diff --git a/projecttemplates/MvcRelyingParty/Views/Account/AuthorizeDenied.aspx b/projecttemplates/MvcRelyingParty/Views/Account/AuthorizeDenied.aspx deleted file mode 100644 index 99bfb2a..0000000 --- a/projecttemplates/MvcRelyingParty/Views/Account/AuthorizeDenied.aspx +++ /dev/null @@ -1,13 +0,0 @@ -<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcRelyingParty.Models.AccountAuthorizeModel>" %> - -<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> - AuthorizeDenied -</asp:Content> -<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> - <h2> - AuthorizeDenied - </h2> - <p> - Authorization has been denied. You're free to do whatever now. - </p> -</asp:Content> diff --git a/projecttemplates/MvcRelyingParty/Views/Account/AuthorizedApps.ascx b/projecttemplates/MvcRelyingParty/Views/Account/AuthorizedApps.ascx index 57c2b1a..4fadad9 100644 --- a/projecttemplates/MvcRelyingParty/Views/Account/AuthorizedApps.ascx +++ b/projecttemplates/MvcRelyingParty/Views/Account/AuthorizedApps.ascx @@ -9,7 +9,7 @@ <% } else { %> <ul> <% foreach (var app in Model.AuthorizedApps) { %> - <li><%= Html.Encode(app.AppName) %> - <%= Ajax.ActionLink("revoke", "RevokeToken", new { token = app.Token }, new AjaxOptions { HttpMethod = "DELETE", UpdateTargetId = "authorizedApps", OnFailure = "function(e) { alert('Revoking authorization for this application failed.'); }" }) %></li> + <li><%= Html.Encode(app.AppName) %> - <%= Html.Encode(app.Scope) %> - <%= Ajax.ActionLink("revoke", "RevokeAuthorization", new { authorizationId = app.AuthorizationId }, new AjaxOptions { HttpMethod = "DELETE", UpdateTargetId = "authorizedApps", OnFailure = "function(e) { alert('Revoking authorization for this application failed.'); }" })%></li> <% } %> </ul> <% } %>
\ No newline at end of file diff --git a/projecttemplates/RelyingPartyDatabase/Properties/Database.sqlcmdvars b/projecttemplates/RelyingPartyDatabase/Properties/Database.sqlcmdvars index a396dc9..f2c472d 100644 --- a/projecttemplates/RelyingPartyDatabase/Properties/Database.sqlcmdvars +++ b/projecttemplates/RelyingPartyDatabase/Properties/Database.sqlcmdvars @@ -4,7 +4,7 @@ <Properties> <Property> <PropertyName>Path1</PropertyName> - <PropertyValue>WEBROOT\App_Data\</PropertyValue> + <PropertyValue>WEBROOT</PropertyValue> </Property> </Properties> </SqlCommandVariables>
\ No newline at end of file diff --git a/projecttemplates/RelyingPartyDatabase/RelyingPartyDatabase.dbproj b/projecttemplates/RelyingPartyDatabase/RelyingPartyDatabase.dbproj index 8163828..9ffe9cf 100644 --- a/projecttemplates/RelyingPartyDatabase/RelyingPartyDatabase.dbproj +++ b/projecttemplates/RelyingPartyDatabase/RelyingPartyDatabase.dbproj @@ -6,7 +6,7 @@ <SchemaVersion>2.0</SchemaVersion> <ProjectVersion>4.0</ProjectVersion> <ProjectGuid>{2b4261ac-25ac-4b8d-b459-1c42b6b1401d}</ProjectGuid> - <DSP>Microsoft.Data.Schema.Sql.Sql100DatabaseSchemaProvider</DSP> + <DSP>Microsoft.Data.Schema.Sql.Sql90DatabaseSchemaProvider</DSP> <AppDesignerFolder>Properties</AppDesignerFolder> <ShowWizard>True</ShowWizard> <OutputType>Database</OutputType> @@ -284,4 +284,39 @@ <ItemGroup> <BuildContributorArgument Include="OutDir=$(OutDir)" /> </ItemGroup> + <ItemGroup> + <NotInBuild Include="Schema Comparisons\SchemaComparison1.scmp"> + <SubType>NotInBuild</SubType> + </NotInBuild> + </ItemGroup> + <ItemGroup> + <Build Include="Schema Objects\Schemas\dbo\Tables\Constraints\DF_IssuedToken_CreatedOn_1.defconst.sql"> + <SubType>Code</SubType> + </Build> + <Build Include="Schema Objects\Schemas\dbo\Tables\Keys\FK_IssuedToken_Consumer_1.fkey.sql"> + <SubType>Code</SubType> + </Build> + <Build Include="Schema Objects\Schemas\dbo\Tables\Keys\FK_IssuedToken_User_1.fkey.sql"> + <SubType>Code</SubType> + </Build> + <Build Include="Schema Objects\Schemas\dbo\Tables\Indexes\IX_Consumer_1.index.sql"> + <SubType>Code</SubType> + </Build> + <Build Include="Schema Objects\Schemas\dbo\Tables\Keys\PK_IssuedToken_1.pkey.sql"> + <SubType>Code</SubType> + </Build> + <Build Include="Schema Objects\Schemas\dbo\Tables\Keys\PK_Consumer_1.pkey.sql"> + <SubType>Code</SubType> + </Build> + <Build Include="Schema Objects\Schemas\dbo\Tables\ClientAuthorization.table.sql"> + <SubType>Code</SubType> + <AnsiNulls>On</AnsiNulls> + <QuotedIdentifier>On</QuotedIdentifier> + </Build> + <Build Include="Schema Objects\Schemas\dbo\Tables\Client.table.sql"> + <SubType>Code</SubType> + <AnsiNulls>On</AnsiNulls> + <QuotedIdentifier>On</QuotedIdentifier> + </Build> + </ItemGroup> </Project>
\ No newline at end of file diff --git a/projecttemplates/RelyingPartyDatabase/Schema Comparisons/SchemaComparison1.scmp b/projecttemplates/RelyingPartyDatabase/Schema Comparisons/SchemaComparison1.scmp new file mode 100644 index 0000000..b3160a4 --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Comparisons/SchemaComparison1.scmp @@ -0,0 +1,328 @@ +<?xml version="1.0" encoding="utf-8"?> +<SchemaComparison> + <Version>1</Version> + <SourceModelProvider> + <ConnectionBasedModelProvider> + <ConnectionString>Data Source=.\sqlexpress;Initial Catalog=RelyingPartyDatabase;Integrated Security=True;Password=</ConnectionString> + <DatabaseName>RelyingPartyDatabase</DatabaseName> + <DspFamilyName>sql</DspFamilyName> + <Name>[THINKAGAIN\sqlexpress.RelyingPartyDatabase]</Name> + </ConnectionBasedModelProvider> + </SourceModelProvider> + <TargetModelProvider> + <ProjectBasedModelProvider> + <ProjectGuid>{2b4261ac-25ac-4b8d-b459-1c42b6b1401d}</ProjectGuid> + <Name>RelyingPartyDatabase</Name> + </ProjectBasedModelProvider> + </TargetModelProvider> + <SchemaCompareSettingsService> + <SchemaCompareSettingsService> + <PropertyElementName> + <Name>Version</Name> + <Value>1</Value> + </PropertyElementName> + </SchemaCompareSettingsService> + <ConfigurationOptionsElement> + <PropertyElementName> + <Name>PlanGenerationType</Name> + <Value>Sql90SchemaDeploymentOptions</Value> + </PropertyElementName> + <PropertyElementName> + <Name>DoNotUseAlterAssemblyStatementsToUpdateCLRTypes</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>DisableAndReenableDdlTriggers</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreDdlTriggerOrder</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreDdlTriggerState</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreObjectPlacementOnPartitionScheme</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreAuthorizer</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreDefaultSchema</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreRouteLifetime</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>OnlyCompareElementsInSource</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreStatisticsSample</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>CommentOutSetVarDeclarations</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>GenerateDeployStateChecks</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>DeployDatabaseProperties</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreComments</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreWhitespace</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreKeywordCasing</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreSemicolonBetweenStatements</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>BlockIncrementalDeploymentIfDataLoss</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>PerformDatabaseBackup</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SingleUserMode</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IncludeTransactionalScripts</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>EnforceMinimalDependencies</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>DeploymentCollationPreference</Name> + <Value>UseSourceModelCollation</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnorePartitionSchemes</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreWithNocheckOnCheckConstraints</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreWithNocheckOnForeignKeys</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreIdentitySeed</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreIncrement</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreFillFactor</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreIndexPadding</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreColumnCollation</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreLockHintsOnIndexes</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreTableOptions</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreIndexOptions</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreDmlTriggerOrder</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>ScriptDatabaseCollation</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreDmlTriggerState</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreAnsiNulls</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreQuotedIdentifiers</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreUserSettingsObjects</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>AbortOnFirstError</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreFilegroupPlacement</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreFullTextCatalogFilePath</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreFileAndLogFilePath</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreLoginSids</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreNotForReplication</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreFileSize</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>OverrideSevenSetOptions</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SetAnsiNulls</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SetAnsiPadding</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SetAnsiWarnings</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SetArithAbort</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SetConcatNullYieldsNull</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SetQuotedIdentifier</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SetNumericRoundAbort</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>UnmodifiableObjectWarnings</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>DropIndexesNotInSource</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>DropConstraintsNotInSource</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>CheckNewConstraints</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreColumnOrder</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnorePasswords</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>IgnoreBodyDependencies</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>SourceSqlCmdVariablesFile</Name> + <Value>C:\Users\andarno\git\dotnetopenid\projecttemplates\RelyingPartyDatabase\Properties\Database.sqlcmdvars</Value> + </PropertyElementName> + <PropertyElementName> + <Name>AlwaysCreateNewDatabase</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>GenerateDropsIfNotInProject</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>TargetDatabaseName</Name> + <Value>RelyingPartyDatabase</Value> + </PropertyElementName> + <PropertyElementName> + <Name>TargetConnectionString</Name> + <Value>Data Source=.\sqlexpress;Initial Catalog=RelyingPartyDatabase;Integrated Security=True;Pooling=False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>VerifyDeployment</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>TreatVerificationErrorsAsWarnings</Name> + <Value>False</Value> + </PropertyElementName> + <PropertyElementName> + <Name>BuildtimeContributorsMustExist</Name> + <Value>True</Value> + </PropertyElementName> + <PropertyElementName> + <Name>Microsoft.Data.Schema.Sql.SchemaModel.ISqlPermissionStatement</Name> + <Value>ExcludedType</Value> + </PropertyElementName> + <PropertyElementName> + <Name>Microsoft.Data.Schema.Sql.SchemaModel.ISqlFilegroup</Name> + <Value>ExcludedType</Value> + </PropertyElementName> + <PropertyElementName> + <Name>Microsoft.Data.Schema.Sql.SchemaModel.ISqlFile</Name> + <Value>ExcludedType</Value> + </PropertyElementName> + <PropertyElementName> + <Name>Microsoft.Data.Schema.Sql.SchemaModel.ISqlExtendedProperty</Name> + <Value>ExcludedType</Value> + </PropertyElementName> + </ConfigurationOptionsElement> + </SchemaCompareSettingsService> +</SchemaComparison>
\ No newline at end of file diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Client.table.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Client.table.sql new file mode 100644 index 0000000..8dc2f64 --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Client.table.sql @@ -0,0 +1,12 @@ +CREATE TABLE [dbo].[Client] ( + [ClientId] INT IDENTITY (1, 1) NOT NULL, + [ClientIdentifier] VARCHAR (255) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, + [ClientSecret] VARCHAR (255) COLLATE SQL_Latin1_General_CP1_CS_AS NULL, + [Callback] VARCHAR (2048) NULL, + [Name] NVARCHAR (50) NOT NULL +); + + + + + diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/ClientAuthorization.table.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/ClientAuthorization.table.sql new file mode 100644 index 0000000..3a31062 --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/ClientAuthorization.table.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[ClientAuthorization] ( + [AuthorizationId] INT IDENTITY (1, 1) NOT NULL, + [ClientId] INT NOT NULL, + [UserId] INT NOT NULL, + [CreatedOn] DATETIME NOT NULL, + [ExpirationDate] DATETIME NULL, + [Scope] VARCHAR (2048) NULL +); + diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_CreatedOn.defconst.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_CreatedOn.defconst.sql index c60323f..28f59be 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_CreatedOn.defconst.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_CreatedOn.defconst.sql @@ -1,3 +1,3 @@ -ALTER TABLE [dbo].[IssuedToken] - ADD CONSTRAINT [DF_IssuedToken_CreatedOn] DEFAULT (getutcdate()) FOR [CreatedOn]; +/*ALTER TABLE [dbo].[IssuedToken] + ADD CONSTRAINT [DF_IssuedToken_CreatedOn] DEFAULT (getutcdate()) FOR [CreatedOn];*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_CreatedOn_1.defconst.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_CreatedOn_1.defconst.sql new file mode 100644 index 0000000..3ba2b0b --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_CreatedOn_1.defconst.sql @@ -0,0 +1,3 @@ +ALTER TABLE [dbo].[ClientAuthorization] + ADD CONSTRAINT [DF_IssuedToken_CreatedOn] DEFAULT (getutcdate()) FOR [CreatedOn]; + diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_IsAccessToken.defconst.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_IsAccessToken.defconst.sql index 2e9e5fd..cf3ec08 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_IsAccessToken.defconst.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Constraints/DF_IssuedToken_IsAccessToken.defconst.sql @@ -1,3 +1,3 @@ -ALTER TABLE [dbo].[IssuedToken] - ADD CONSTRAINT [DF_IssuedToken_IsAccessToken] DEFAULT ((0)) FOR [IsAccessToken]; +/*ALTER TABLE [dbo].[IssuedToken] + ADD CONSTRAINT [DF_IssuedToken_IsAccessToken] DEFAULT ((0)) FOR [IsAccessToken];*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Consumer.table.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Consumer.table.sql index 8549a78..ab14759 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Consumer.table.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Consumer.table.sql @@ -1,4 +1,4 @@ -CREATE TABLE [dbo].[Consumer] ( +/*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_CS_AS NULL, @@ -7,5 +7,5 @@ [VerificationCodeFormat] INT NOT NULL, [VerificationCodeLength] INT NOT NULL, [Name] NVARCHAR (50) NULL -); +);*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_Consumer.index.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_Consumer.index.sql index 149ae35..d469e71 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_Consumer.index.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_Consumer.index.sql @@ -1,3 +1,3 @@ -CREATE UNIQUE NONCLUSTERED INDEX [IX_Consumer] - ON [dbo].[Consumer]([ConsumerKey] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = OFF, MAXDOP = 0); +/*CREATE UNIQUE NONCLUSTERED INDEX [IX_Consumer] + ON [dbo].[Consumer]([ConsumerKey] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = OFF, MAXDOP = 0);*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_Consumer_1.index.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_Consumer_1.index.sql new file mode 100644 index 0000000..e5ad21b --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_Consumer_1.index.sql @@ -0,0 +1,4 @@ +CREATE UNIQUE NONCLUSTERED INDEX [IX_Consumer] + ON [dbo].[Client]([ClientIdentifier] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = OFF, MAXDOP = 0) + ON [PRIMARY]; + diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_IssuedToken.index.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_IssuedToken.index.sql index 5bc3a53..f2f59e1 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_IssuedToken.index.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Indexes/IX_IssuedToken.index.sql @@ -1,3 +1,3 @@ -CREATE UNIQUE NONCLUSTERED INDEX [IX_IssuedToken] - ON [dbo].[IssuedToken]([Token] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = OFF, MAXDOP = 0); +/*CREATE UNIQUE NONCLUSTERED INDEX [IX_IssuedToken] + ON [dbo].[IssuedToken]([Token] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = OFF, MAXDOP = 0);*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/IssuedToken.table.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/IssuedToken.table.sql index 8882e93..ee0ffdf 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/IssuedToken.table.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/IssuedToken.table.sql @@ -1,4 +1,4 @@ -CREATE TABLE [dbo].[IssuedToken] ( +/*CREATE TABLE [dbo].[IssuedToken] ( [IssuedTokenId] INT IDENTITY (1, 1) NOT NULL, [ConsumerId] INT NOT NULL, [UserId] INT NULL, @@ -11,5 +11,5 @@ [ExpirationDate] DATETIME NULL, [IsAccessToken] BIT NOT NULL, [Scope] NVARCHAR (255) NULL -); +);*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_Consumer.fkey.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_Consumer.fkey.sql index a5b3dac..fe25092 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_Consumer.fkey.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_Consumer.fkey.sql @@ -1,3 +1,3 @@ -ALTER TABLE [dbo].[IssuedToken] - ADD CONSTRAINT [FK_IssuedToken_Consumer] FOREIGN KEY ([ConsumerId]) REFERENCES [dbo].[Consumer] ([ConsumerId]) ON DELETE CASCADE ON UPDATE CASCADE; +/*ALTER TABLE [dbo].[IssuedToken] + ADD CONSTRAINT [FK_IssuedToken_Consumer] FOREIGN KEY ([ConsumerId]) REFERENCES [dbo].[Consumer] ([ConsumerId]) ON DELETE CASCADE ON UPDATE CASCADE;*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_Consumer_1.fkey.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_Consumer_1.fkey.sql new file mode 100644 index 0000000..062b9d7 --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_Consumer_1.fkey.sql @@ -0,0 +1,3 @@ +ALTER TABLE [dbo].[ClientAuthorization] + ADD CONSTRAINT [FK_IssuedToken_Consumer] FOREIGN KEY ([ClientId]) REFERENCES [dbo].[Client] ([ClientId]) ON DELETE CASCADE ON UPDATE CASCADE; + diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_User.fkey.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_User.fkey.sql index 045a694..3b9bbc1 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_User.fkey.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_User.fkey.sql @@ -1,3 +1,3 @@ -ALTER TABLE [dbo].[IssuedToken] - ADD CONSTRAINT [FK_IssuedToken_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([UserId]) ON DELETE CASCADE ON UPDATE CASCADE; +/*ALTER TABLE [dbo].[IssuedToken] + ADD CONSTRAINT [FK_IssuedToken_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([UserId]) ON DELETE CASCADE ON UPDATE CASCADE;*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_User_1.fkey.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_User_1.fkey.sql new file mode 100644 index 0000000..e32b291 --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/FK_IssuedToken_User_1.fkey.sql @@ -0,0 +1,3 @@ +ALTER TABLE [dbo].[ClientAuthorization] + ADD CONSTRAINT [FK_IssuedToken_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([UserId]) ON DELETE CASCADE ON UPDATE CASCADE; + diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_Consumer.pkey.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_Consumer.pkey.sql index edde20f..181fdf5 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_Consumer.pkey.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_Consumer.pkey.sql @@ -1,3 +1,3 @@ -ALTER TABLE [dbo].[Consumer] - ADD CONSTRAINT [PK_Consumer] PRIMARY KEY CLUSTERED ([ConsumerId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); +/*ALTER TABLE [dbo].[Consumer] + ADD CONSTRAINT [PK_Consumer] PRIMARY KEY CLUSTERED ([ConsumerId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF);*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_Consumer_1.pkey.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_Consumer_1.pkey.sql new file mode 100644 index 0000000..04c039f --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_Consumer_1.pkey.sql @@ -0,0 +1,3 @@ +ALTER TABLE [dbo].[Client] + ADD CONSTRAINT [PK_Consumer] PRIMARY KEY CLUSTERED ([ClientId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); + diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_IssuedToken.pkey.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_IssuedToken.pkey.sql index e2f95ef..931fa54 100644 --- a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_IssuedToken.pkey.sql +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_IssuedToken.pkey.sql @@ -1,3 +1,3 @@ -ALTER TABLE [dbo].[IssuedToken] - ADD CONSTRAINT [PK_IssuedToken] PRIMARY KEY CLUSTERED ([IssuedTokenId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); +/*ALTER TABLE [dbo].[IssuedToken] + ADD CONSTRAINT [PK_IssuedToken] PRIMARY KEY CLUSTERED ([IssuedTokenId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF);*/ diff --git a/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_IssuedToken_1.pkey.sql b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_IssuedToken_1.pkey.sql new file mode 100644 index 0000000..dcd7edc --- /dev/null +++ b/projecttemplates/RelyingPartyDatabase/Schema Objects/Schemas/dbo/Tables/Keys/PK_IssuedToken_1.pkey.sql @@ -0,0 +1,3 @@ +ALTER TABLE [dbo].[ClientAuthorization] + ADD CONSTRAINT [PK_IssuedToken] PRIMARY KEY CLUSTERED ([AuthorizationId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); + diff --git a/projecttemplates/RelyingPartyLogic/CreateDatabase.sql b/projecttemplates/RelyingPartyLogic/CreateDatabase.sql index 0fa1b43..5c82398 100644 --- a/projecttemplates/RelyingPartyLogic/CreateDatabase.sql +++ b/projecttemplates/RelyingPartyLogic/CreateDatabase.sql @@ -8,10 +8,10 @@ SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL GO /* -:setvar Path1 "WEBROOT\App_Data\" +:setvar Path1 "WEBROOT" :setvar DatabaseName "RelyingPartyDatabase" -:setvar DefaultDataPath "" -:setvar DefaultLogPath "" +:setvar DefaultDataPath "c:\Program Files (x86)\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\" +:setvar DefaultLogPath "c:\Program Files (x86)\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\" */ GO @@ -128,24 +128,6 @@ ELSE GO -IF IS_SRVROLEMEMBER(N'sysadmin') = 1 - BEGIN - IF EXISTS (SELECT 1 - FROM [master].[dbo].[sysdatabases] - WHERE [name] = N'$(DatabaseName)') - BEGIN - EXECUTE sp_executesql N'ALTER DATABASE [$(DatabaseName)] - SET HONOR_BROKER_PRIORITY OFF - WITH ROLLBACK IMMEDIATE'; - END - END -ELSE - BEGIN - PRINT N'The database settings cannot be modified. You must be a SysAdmin to apply these settings.'; - END - - -GO USE [$(DatabaseName)] GO @@ -200,7 +182,7 @@ ALTER TABLE [dbo].[AuthenticationToken] GO -PRINT N'Creating [dbo].[Consumer]...'; +PRINT N'Creating [dbo].[Client]...'; GO @@ -208,15 +190,12 @@ SET ANSI_NULLS, 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_CS_AS NULL, - [X509Certificate] IMAGE NULL, - [Callback] NVARCHAR (2048) NULL, - [VerificationCodeFormat] INT NOT NULL, - [VerificationCodeLength] INT NOT NULL, - [Name] NVARCHAR (50) NULL +CREATE TABLE [dbo].[Client] ( + [ClientId] INT IDENTITY (1, 1) NOT NULL, + [ClientIdentifier] VARCHAR (255) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, + [ClientSecret] VARCHAR (255) COLLATE SQL_Latin1_General_CP1_CS_AS NULL, + [Callback] VARCHAR (2048) NULL, + [Name] NVARCHAR (50) NOT NULL ); @@ -229,21 +208,22 @@ PRINT N'Creating PK_Consumer...'; GO -ALTER TABLE [dbo].[Consumer] - ADD CONSTRAINT [PK_Consumer] PRIMARY KEY CLUSTERED ([ConsumerId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); +ALTER TABLE [dbo].[Client] + ADD CONSTRAINT [PK_Consumer] PRIMARY KEY CLUSTERED ([ClientId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); GO -PRINT N'Creating [dbo].[Consumer].[IX_Consumer]...'; +PRINT N'Creating [dbo].[Client].[IX_Consumer]...'; GO CREATE UNIQUE NONCLUSTERED INDEX [IX_Consumer] - ON [dbo].[Consumer]([ConsumerKey] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = OFF, MAXDOP = 0); + ON [dbo].[Client]([ClientIdentifier] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = OFF, MAXDOP = 0) + ON [PRIMARY]; GO -PRINT N'Creating [dbo].[IssuedToken]...'; +PRINT N'Creating [dbo].[ClientAuthorization]...'; GO @@ -251,19 +231,13 @@ SET ANSI_NULLS, QUOTED_IDENTIFIER ON; GO -CREATE TABLE [dbo].[IssuedToken] ( - [IssuedTokenId] 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) NULL, - [VerificationCode] NVARCHAR (255) COLLATE SQL_Latin1_General_CP1_CS_AS NULL, - [ConsumerVersion] VARCHAR (10) NULL, - [ExpirationDate] DATETIME NULL, - [IsAccessToken] BIT NOT NULL, - [Scope] NVARCHAR (255) NULL +CREATE TABLE [dbo].[ClientAuthorization] ( + [AuthorizationId] INT IDENTITY (1, 1) NOT NULL, + [ClientId] INT NOT NULL, + [UserId] INT NOT NULL, + [CreatedOn] DATETIME NOT NULL, + [ExpirationDate] DATETIME NULL, + [Scope] VARCHAR (2048) NULL ); @@ -276,17 +250,8 @@ PRINT N'Creating PK_IssuedToken...'; GO -ALTER TABLE [dbo].[IssuedToken] - ADD CONSTRAINT [PK_IssuedToken] PRIMARY KEY CLUSTERED ([IssuedTokenId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); - - -GO -PRINT N'Creating [dbo].[IssuedToken].[IX_IssuedToken]...'; - - -GO -CREATE UNIQUE NONCLUSTERED INDEX [IX_IssuedToken] - ON [dbo].[IssuedToken]([Token] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, ONLINE = OFF, MAXDOP = 0); +ALTER TABLE [dbo].[ClientAuthorization] + ADD CONSTRAINT [PK_IssuedToken] PRIMARY KEY CLUSTERED ([AuthorizationId] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); GO @@ -515,20 +480,11 @@ PRINT N'Creating DF_IssuedToken_CreatedOn...'; GO -ALTER TABLE [dbo].[IssuedToken] +ALTER TABLE [dbo].[ClientAuthorization] ADD CONSTRAINT [DF_IssuedToken_CreatedOn] DEFAULT (getutcdate()) FOR [CreatedOn]; GO -PRINT N'Creating DF_IssuedToken_IsAccessToken...'; - - -GO -ALTER TABLE [dbo].[IssuedToken] - ADD CONSTRAINT [DF_IssuedToken_IsAccessToken] DEFAULT ((0)) FOR [IsAccessToken]; - - -GO PRINT N'Creating DF_Nonce_Issued...'; @@ -569,8 +525,8 @@ PRINT N'Creating FK_IssuedToken_Consumer...'; GO -ALTER TABLE [dbo].[IssuedToken] WITH NOCHECK - ADD CONSTRAINT [FK_IssuedToken_Consumer] FOREIGN KEY ([ConsumerId]) REFERENCES [dbo].[Consumer] ([ConsumerId]) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE [dbo].[ClientAuthorization] WITH NOCHECK + ADD CONSTRAINT [FK_IssuedToken_Consumer] FOREIGN KEY ([ClientId]) REFERENCES [dbo].[Client] ([ClientId]) ON DELETE CASCADE ON UPDATE CASCADE; GO @@ -578,7 +534,7 @@ PRINT N'Creating FK_IssuedToken_User...'; GO -ALTER TABLE [dbo].[IssuedToken] WITH NOCHECK +ALTER TABLE [dbo].[ClientAuthorization] WITH NOCHECK ADD CONSTRAINT [FK_IssuedToken_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([UserId]) ON DELETE CASCADE ON UPDATE CASCADE; @@ -717,9 +673,9 @@ USE [$(DatabaseName)]; GO ALTER TABLE [dbo].[AuthenticationToken] WITH CHECK CHECK CONSTRAINT [FK_AuthenticationToken_User]; -ALTER TABLE [dbo].[IssuedToken] WITH CHECK CHECK CONSTRAINT [FK_IssuedToken_Consumer]; +ALTER TABLE [dbo].[ClientAuthorization] WITH CHECK CHECK CONSTRAINT [FK_IssuedToken_Consumer]; -ALTER TABLE [dbo].[IssuedToken] WITH CHECK CHECK CONSTRAINT [FK_IssuedToken_User]; +ALTER TABLE [dbo].[ClientAuthorization] WITH CHECK CHECK CONSTRAINT [FK_IssuedToken_User]; ALTER TABLE [dbo].[UserRole] WITH CHECK CHECK CONSTRAINT [FK_UserRole_Role]; @@ -727,9 +683,3 @@ ALTER TABLE [dbo].[UserRole] WITH CHECK CHECK CONSTRAINT [FK_UserRole_User]; GO -ALTER DATABASE [$(DatabaseName)] - SET MULTI_USER - WITH ROLLBACK IMMEDIATE; - - -GO diff --git a/projecttemplates/RelyingPartyLogic/Model.Client.cs b/projecttemplates/RelyingPartyLogic/Model.Client.cs new file mode 100644 index 0000000..9426408 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Model.Client.cs @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------- +// <copyright file="Model.Client.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + + using DotNetOpenAuth.OAuth2; + + public partial class Client : IConsumerDescription { + public Uri Callback { + get { return this.CallbackAsString != null ? new Uri(this.CallbackAsString) : null; } + set { this.CallbackAsString = value != null ? value.AbsoluteUri : null; } + } + + #region IConsumerDescription Members + + /// <summary> + /// Gets the client secret. + /// </summary> + string IConsumerDescription.Secret { + get { return this.ClientSecret; } + } + + #endregion + } +} diff --git a/projecttemplates/RelyingPartyLogic/Model.IssuedToken.cs b/projecttemplates/RelyingPartyLogic/Model.ClientAuthorization.cs index 5e10178..3d7646a 100644 --- a/projecttemplates/RelyingPartyLogic/Model.IssuedToken.cs +++ b/projecttemplates/RelyingPartyLogic/Model.ClientAuthorization.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="Model.IssuedToken.cs" company="Andrew Arnott"> +// <copyright file="Model.ClientAuthorization.cs" company="Andrew Arnott"> // Copyright (c) Andrew Arnott. All rights reserved. // </copyright> //----------------------------------------------------------------------- @@ -11,11 +11,11 @@ namespace RelyingPartyLogic { using System.Web; using DotNetOpenAuth.OAuth.ChannelElements; - public partial class IssuedToken { + public partial class ClientAuthorization { /// <summary> /// Initializes a new instance of the <see cref="IssuedToken"/> class. /// </summary> - public IssuedToken() { + public ClientAuthorization() { this.CreatedOnUtc = DateTime.UtcNow; } diff --git a/projecttemplates/RelyingPartyLogic/Model.Consumer.cs b/projecttemplates/RelyingPartyLogic/Model.Consumer.cs deleted file mode 100644 index a09029a..0000000 --- a/projecttemplates/RelyingPartyLogic/Model.Consumer.cs +++ /dev/null @@ -1,40 +0,0 @@ -//----------------------------------------------------------------------- -// <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 index a1a5348..8884760 100644 --- a/projecttemplates/RelyingPartyLogic/Model.Designer.cs +++ b/projecttemplates/RelyingPartyLogic/Model.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:4.0.30104.0 +// Runtime Version:4.0.30319.1 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -11,11 +11,11 @@ [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", "FK_AuthenticationToken_User", "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_Consumer1", "Consumer", global::System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(RelyingPartyLogic.Consumer), "IssuedToken", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.IssuedToken))] -[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "FK_IssuedToken_User1", "User", global::System.Data.Metadata.Edm.RelationshipMultiplicity.ZeroOrOne, typeof(RelyingPartyLogic.User), "IssuedToken", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.IssuedToken))] +[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "Client", global::System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(RelyingPartyLogic.Client), "ClientAuthorization", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.ClientAuthorization))] +[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "FK_IssuedToken_User", "User", global::System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(RelyingPartyLogic.User), "ClientAuthorization", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.ClientAuthorization))] // Original file name: -// Generation date: 1/7/2010 8:42:18 PM +// Generation date: 7/14/2010 9:35:17 PM namespace RelyingPartyLogic { @@ -101,73 +101,73 @@ namespace RelyingPartyLogic [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] private global::System.Data.Objects.ObjectQuery<AuthenticationToken> _AuthenticationTokens; /// <summary> - /// There are no comments for Consumers in the schema. + /// There are no comments for Nonces in the schema. /// </summary> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.Data.Objects.ObjectQuery<Consumer> Consumers + public global::System.Data.Objects.ObjectQuery<Nonce> Nonces { get { - if ((this._Consumers == null)) + if ((this._Nonces == null)) { - this._Consumers = base.CreateQuery<Consumer>("[Consumers]"); + this._Nonces = base.CreateQuery<Nonce>("[Nonces]"); } - return this._Consumers; + return this._Nonces; } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.Data.Objects.ObjectQuery<Consumer> _Consumers; + private global::System.Data.Objects.ObjectQuery<Nonce> _Nonces; /// <summary> - /// There are no comments for IssuedTokens in the schema. + /// There are no comments for OpenIdAssociations in the schema. /// </summary> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.Data.Objects.ObjectQuery<IssuedToken> IssuedTokens + public global::System.Data.Objects.ObjectQuery<OpenIdAssociation> OpenIdAssociations { get { - if ((this._IssuedTokens == null)) + if ((this._OpenIdAssociations == null)) { - this._IssuedTokens = base.CreateQuery<IssuedToken>("[IssuedTokens]"); + this._OpenIdAssociations = base.CreateQuery<OpenIdAssociation>("[OpenIdAssociations]"); } - return this._IssuedTokens; + return this._OpenIdAssociations; } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.Data.Objects.ObjectQuery<IssuedToken> _IssuedTokens; + private global::System.Data.Objects.ObjectQuery<OpenIdAssociation> _OpenIdAssociations; /// <summary> - /// There are no comments for Nonces in the schema. + /// There are no comments for Clients in the schema. /// </summary> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.Data.Objects.ObjectQuery<Nonce> Nonces + public global::System.Data.Objects.ObjectQuery<Client> Clients { get { - if ((this._Nonces == null)) + if ((this._Clients == null)) { - this._Nonces = base.CreateQuery<Nonce>("[Nonces]"); + this._Clients = base.CreateQuery<Client>("[Clients]"); } - return this._Nonces; + return this._Clients; } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.Data.Objects.ObjectQuery<Nonce> _Nonces; + private global::System.Data.Objects.ObjectQuery<Client> _Clients; /// <summary> - /// There are no comments for OpenIdAssociations in the schema. + /// There are no comments for ClientAuthorizations in the schema. /// </summary> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.Data.Objects.ObjectQuery<OpenIdAssociation> OpenIdAssociations + public global::System.Data.Objects.ObjectQuery<ClientAuthorization> ClientAuthorizations { get { - if ((this._OpenIdAssociations == null)) + if ((this._ClientAuthorizations == null)) { - this._OpenIdAssociations = base.CreateQuery<OpenIdAssociation>("[OpenIdAssociations]"); + this._ClientAuthorizations = base.CreateQuery<ClientAuthorization>("[ClientAuthorizations]"); } - return this._OpenIdAssociations; + return this._ClientAuthorizations; } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.Data.Objects.ObjectQuery<OpenIdAssociation> _OpenIdAssociations; + private global::System.Data.Objects.ObjectQuery<ClientAuthorization> _ClientAuthorizations; /// <summary> /// There are no comments for Roles in the schema. /// </summary> @@ -193,36 +193,36 @@ namespace RelyingPartyLogic base.AddObject("AuthenticationTokens", authenticationToken); } /// <summary> - /// There are no comments for Consumers in the schema. + /// There are no comments for Nonces in the schema. /// </summary> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public void AddToConsumers(Consumer consumer) + public void AddToNonces(Nonce nonce) { - base.AddObject("Consumers", consumer); + base.AddObject("Nonces", nonce); } /// <summary> - /// There are no comments for IssuedTokens in the schema. + /// There are no comments for OpenIdAssociations in the schema. /// </summary> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public void AddToIssuedTokens(IssuedToken issuedToken) + public void AddToOpenIdAssociations(OpenIdAssociation openIdAssociation) { - base.AddObject("IssuedTokens", issuedToken); + base.AddObject("OpenIdAssociations", openIdAssociation); } /// <summary> - /// There are no comments for Nonces in the schema. + /// There are no comments for Clients in the schema. /// </summary> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public void AddToNonces(Nonce nonce) + public void AddToClients(Client client) { - base.AddObject("Nonces", nonce); + base.AddObject("Clients", client); } /// <summary> - /// There are no comments for OpenIdAssociations in the schema. + /// There are no comments for ClientAuthorizations in the schema. /// </summary> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public void AddToOpenIdAssociations(OpenIdAssociation openIdAssociation) + public void AddToClientAuthorizations(ClientAuthorization clientAuthorization) { - base.AddObject("OpenIdAssociations", openIdAssociation); + base.AddObject("ClientAuthorizations", clientAuthorization); } } /// <summary> @@ -791,609 +791,503 @@ namespace RelyingPartyLogic } } /// <summary> - /// There are no comments for IssuedTokens in the schema. + /// There are no comments for ClientAuthorizations in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_User1", "IssuedToken")] + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_User", "ClientAuthorization")] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] [global::System.Xml.Serialization.XmlIgnoreAttribute()] [global::System.Xml.Serialization.SoapIgnoreAttribute()] [global::System.Runtime.Serialization.DataMemberAttribute()] - public global::System.Data.Objects.DataClasses.EntityCollection<IssuedToken> IssuedTokens + public global::System.Data.Objects.DataClasses.EntityCollection<ClientAuthorization> ClientAuthorizations { get { - return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_User1", "IssuedToken"); + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<ClientAuthorization>("DatabaseModel.FK_IssuedToken_User", "ClientAuthorization"); } set { if ((value != null)) { - ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_User1", "IssuedToken", value); + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<ClientAuthorization>("DatabaseModel.FK_IssuedToken_User", "ClientAuthorization", value); } } } } /// <summary> - /// There are no comments for DatabaseModel.Consumer in the schema. + /// There are no comments for DatabaseModel.Nonce in the schema. /// </summary> /// <KeyProperties> - /// ConsumerId + /// NonceId /// </KeyProperties> - [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="Consumer")] + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="Nonce")] [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] [global::System.Serializable()] - public partial class Consumer : global::System.Data.Objects.DataClasses.EntityObject + public partial class Nonce : global::System.Data.Objects.DataClasses.EntityObject { /// <summary> - /// Create a new Consumer object. + /// Create a new Nonce 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> + /// <param name="nonceId">Initial value of NonceId.</param> + /// <param name="context">Initial value of Context.</param> + /// <param name="code">Initial value of Code.</param> + /// <param name="issuedUtc">Initial value of IssuedUtc.</param> + /// <param name="expiresUtc">Initial value of ExpiresUtc.</param> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public static Consumer CreateConsumer(string consumerKey, int verificationCodeLength, int consumerId) + public static Nonce CreateNonce(int nonceId, string context, string code, global::System.DateTime issuedUtc, global::System.DateTime expiresUtc) { - Consumer consumer = new Consumer(); - consumer.ConsumerKey = consumerKey; - consumer.VerificationCodeLength = verificationCodeLength; - consumer.ConsumerId = consumerId; - return consumer; + Nonce nonce = new Nonce(); + nonce.NonceId = nonceId; + nonce.Context = context; + nonce.Code = code; + nonce.IssuedUtc = issuedUtc; + nonce.ExpiresUtc = expiresUtc; + return nonce; } /// <summary> - /// There are no comments for property ConsumerKey in the schema. + /// There are no comments for property NonceId in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string ConsumerKey + public int NonceId { get { - return this._ConsumerKey; + return this._NonceId; } set { - this.OnConsumerKeyChanging(value); - this.ReportPropertyChanging("ConsumerKey"); - this._ConsumerKey = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("ConsumerKey"); - this.OnConsumerKeyChanged(); + this.OnNonceIdChanging(value); + this.ReportPropertyChanging("NonceId"); + this._NonceId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("NonceId"); + this.OnNonceIdChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _ConsumerKey; + private int _NonceId; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnConsumerKeyChanging(string value); + partial void OnNonceIdChanging(int value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnConsumerKeyChanged(); + partial void OnNonceIdChanged(); /// <summary> - /// There are no comments for property ConsumerSecret in the schema. + /// Gets or sets the Provider Endpoint URL the nonce came from. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string ConsumerSecret + public string Context { get { - return this._ConsumerSecret; + return this._Context; } set { - this.OnConsumerSecretChanging(value); - this.ReportPropertyChanging("ConsumerSecret"); - this._ConsumerSecret = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); - this.ReportPropertyChanged("ConsumerSecret"); - this.OnConsumerSecretChanged(); + this.OnContextChanging(value); + this.ReportPropertyChanging("Context"); + this._Context = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("Context"); + this.OnContextChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _ConsumerSecret; + private string _Context; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnConsumerSecretChanging(string value); + partial void OnContextChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnConsumerSecretChanged(); + partial void OnContextChanged(); /// <summary> - /// There are no comments for property X509CertificateAsBinary in the schema. + /// There are no comments for property Code in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private byte[] X509CertificateAsBinary + public string Code { get { - return global::System.Data.Objects.DataClasses.StructuralObject.GetValidValue(this._X509CertificateAsBinary); + return this._Code; } set { - this.OnX509CertificateAsBinaryChanging(value); - this.ReportPropertyChanging("X509CertificateAsBinary"); - this._X509CertificateAsBinary = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); - this.ReportPropertyChanged("X509CertificateAsBinary"); - this.OnX509CertificateAsBinaryChanged(); + this.OnCodeChanging(value); + this.ReportPropertyChanging("Code"); + this._Code = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("Code"); + this.OnCodeChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private byte[] _X509CertificateAsBinary; + private string _Code; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnX509CertificateAsBinaryChanging(byte[] value); + partial void OnCodeChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnX509CertificateAsBinaryChanged(); + partial void OnCodeChanged(); /// <summary> - /// There are no comments for property CallbackAsString in the schema. + /// There are no comments for property IssuedUtc in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string CallbackAsString + public global::System.DateTime IssuedUtc { get { - return this._CallbackAsString; + return this._IssuedUtc; } set { - this.OnCallbackAsStringChanging(value); - this.ReportPropertyChanging("CallbackAsString"); - this._CallbackAsString = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); - this.ReportPropertyChanged("CallbackAsString"); - this.OnCallbackAsStringChanged(); + this.OnIssuedUtcChanging(value); + this.ReportPropertyChanging("IssuedUtc"); + this._IssuedUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("IssuedUtc"); + this.OnIssuedUtcChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _CallbackAsString; + private global::System.DateTime _IssuedUtc; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnCallbackAsStringChanging(string value); + partial void OnIssuedUtcChanging(global::System.DateTime value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnCallbackAsStringChanged(); + partial void OnIssuedUtcChanged(); /// <summary> - /// There are no comments for property VerificationCodeFormatAsInt in the schema. + /// There are no comments for property ExpiresUtc in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private int VerificationCodeFormatAsInt + public global::System.DateTime ExpiresUtc { get { - return this._VerificationCodeFormatAsInt; + return this._ExpiresUtc; } set { - this.OnVerificationCodeFormatAsIntChanging(value); - this.ReportPropertyChanging("VerificationCodeFormatAsInt"); - this._VerificationCodeFormatAsInt = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("VerificationCodeFormatAsInt"); - this.OnVerificationCodeFormatAsIntChanged(); + this.OnExpiresUtcChanging(value); + this.ReportPropertyChanging("ExpiresUtc"); + this._ExpiresUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("ExpiresUtc"); + this.OnExpiresUtcChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private int _VerificationCodeFormatAsInt; + private global::System.DateTime _ExpiresUtc; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnVerificationCodeFormatAsIntChanging(int value); + partial void OnExpiresUtcChanging(global::System.DateTime value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnVerificationCodeFormatAsIntChanged(); + partial void OnExpiresUtcChanged(); + } + /// <summary> + /// There are no comments for DatabaseModel.OpenIdAssociation in the schema. + /// </summary> + /// <KeyProperties> + /// AssociationId + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="OpenIdAssociation")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class OpenIdAssociation : global::System.Data.Objects.DataClasses.EntityObject + { /// <summary> - /// There are no comments for property VerificationCodeLength in the schema. + /// Create a new OpenIdAssociation object. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] - [global::System.Runtime.Serialization.DataMemberAttribute()] + /// <param name="associationId">Initial value of AssociationId.</param> + /// <param name="distinguishingFactor">Initial value of DistinguishingFactor.</param> + /// <param name="associationHandle">Initial value of AssociationHandle.</param> + /// <param name="expirationUtc">Initial value of ExpirationUtc.</param> + /// <param name="privateData">Initial value of PrivateData.</param> + /// <param name="privateDataLength">Initial value of PrivateDataLength.</param> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public int VerificationCodeLength + public static OpenIdAssociation CreateOpenIdAssociation(int associationId, string distinguishingFactor, string associationHandle, global::System.DateTime expirationUtc, byte[] privateData, int privateDataLength) { - 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(); - } + OpenIdAssociation openIdAssociation = new OpenIdAssociation(); + openIdAssociation.AssociationId = associationId; + openIdAssociation.DistinguishingFactor = distinguishingFactor; + openIdAssociation.AssociationHandle = associationHandle; + openIdAssociation.ExpirationUtc = expirationUtc; + openIdAssociation.PrivateData = privateData; + openIdAssociation.PrivateDataLength = privateDataLength; + return openIdAssociation; } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private int _VerificationCodeLength; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnVerificationCodeLengthChanging(int value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnVerificationCodeLengthChanged(); /// <summary> - /// There are no comments for property ConsumerId in the schema. + /// There are no comments for property AssociationId in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public int ConsumerId + public int AssociationId { get { - return this._ConsumerId; + return this._AssociationId; } - private set + set { - this.OnConsumerIdChanging(value); - this.ReportPropertyChanging("ConsumerId"); - this._ConsumerId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("ConsumerId"); - this.OnConsumerIdChanged(); + this.OnAssociationIdChanging(value); + this.ReportPropertyChanging("AssociationId"); + this._AssociationId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("AssociationId"); + this.OnAssociationIdChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private int _ConsumerId; + private int _AssociationId; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnConsumerIdChanging(int value); + partial void OnAssociationIdChanging(int value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnConsumerIdChanged(); + partial void OnAssociationIdChanged(); /// <summary> - /// There are no comments for property Name in the schema. + /// Gets or sets the Provider Endpoint URL the association is with. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string Name + public string DistinguishingFactor { get { - return this._Name; + return this._DistinguishingFactor; } set { - this.OnNameChanging(value); - this.ReportPropertyChanging("Name"); - this._Name = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); - this.ReportPropertyChanged("Name"); - this.OnNameChanged(); + this.OnDistinguishingFactorChanging(value); + this.ReportPropertyChanging("DistinguishingFactor"); + this._DistinguishingFactor = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("DistinguishingFactor"); + this.OnDistinguishingFactorChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _Name; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnNameChanging(string value); + private string _DistinguishingFactor; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnNameChanged(); - /// <summary> - /// There are no comments for IssuedTokens in the schema. - /// </summary> - [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_Consumer1", "IssuedToken")] + partial void OnDistinguishingFactorChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - [global::System.Xml.Serialization.XmlIgnoreAttribute()] - [global::System.Xml.Serialization.SoapIgnoreAttribute()] - [global::System.Runtime.Serialization.DataMemberAttribute()] - public global::System.Data.Objects.DataClasses.EntityCollection<IssuedToken> IssuedTokens - { - get - { - return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_Consumer1", "IssuedToken"); - } - set - { - if ((value != null)) - { - ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_Consumer1", "IssuedToken", value); - } - } - } - } - /// <summary> - /// There are no comments for DatabaseModel.IssuedToken in the schema. - /// </summary> - /// <KeyProperties> - /// IssuedTokenId - /// </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 - { + partial void OnDistinguishingFactorChanged(); /// <summary> - /// There are no comments for property Token in the schema. + /// There are no comments for property AssociationHandle in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string Token + public string AssociationHandle { get { - return this._Token; + return this._AssociationHandle; } set { - this.OnTokenChanging(value); - this.ReportPropertyChanging("Token"); - this._Token = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("Token"); - this.OnTokenChanged(); + this.OnAssociationHandleChanging(value); + this.ReportPropertyChanging("AssociationHandle"); + this._AssociationHandle = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("AssociationHandle"); + this.OnAssociationHandleChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _Token; + private string _AssociationHandle; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnTokenChanging(string value); + partial void OnAssociationHandleChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnTokenChanged(); + partial void OnAssociationHandleChanged(); /// <summary> - /// There are no comments for property TokenSecret in the schema. + /// There are no comments for property ExpirationUtc in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string TokenSecret + public global::System.DateTime ExpirationUtc { get { - return this._TokenSecret; + return this._ExpirationUtc; } set { - this.OnTokenSecretChanging(value); - this.ReportPropertyChanging("TokenSecret"); - this._TokenSecret = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("TokenSecret"); - this.OnTokenSecretChanged(); + this.OnExpirationUtcChanging(value); + this.ReportPropertyChanging("ExpirationUtc"); + this._ExpirationUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("ExpirationUtc"); + this.OnExpirationUtcChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _TokenSecret; + private global::System.DateTime _ExpirationUtc; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnTokenSecretChanging(string value); + partial void OnExpirationUtcChanging(global::System.DateTime value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnTokenSecretChanged(); + partial void OnExpirationUtcChanged(); /// <summary> - /// There are no comments for property CreatedOnUtc in the schema. + /// There are no comments for property PrivateData in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.DateTime CreatedOnUtc + public byte[] PrivateData { get { - return this._CreatedOnUtc; + return global::System.Data.Objects.DataClasses.StructuralObject.GetValidValue(this._PrivateData); } - internal set + set { - this.OnCreatedOnUtcChanging(value); - this.ReportPropertyChanging("CreatedOnUtc"); - this._CreatedOnUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("CreatedOnUtc"); - this.OnCreatedOnUtcChanged(); + this.OnPrivateDataChanging(value); + this.ReportPropertyChanging("PrivateData"); + this._PrivateData = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("PrivateData"); + this.OnPrivateDataChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.DateTime _CreatedOnUtc; + private byte[] _PrivateData; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnCreatedOnUtcChanging(global::System.DateTime value); + partial void OnPrivateDataChanging(byte[] value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnCreatedOnUtcChanged(); + partial void OnPrivateDataChanged(); /// <summary> - /// There are no comments for property Scope in the schema. + /// There are no comments for property PrivateDataLength in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string Scope + public int PrivateDataLength { get { - return this._Scope; + return this._PrivateDataLength; } set { - this.OnScopeChanging(value); - this.ReportPropertyChanging("Scope"); - this._Scope = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); - this.ReportPropertyChanged("Scope"); - this.OnScopeChanged(); + this.OnPrivateDataLengthChanging(value); + this.ReportPropertyChanging("PrivateDataLength"); + this._PrivateDataLength = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("PrivateDataLength"); + this.OnPrivateDataLengthChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _Scope; + private int _PrivateDataLength; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnScopeChanging(string value); + partial void OnPrivateDataLengthChanging(int value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnScopeChanged(); + partial void OnPrivateDataLengthChanged(); + } + /// <summary> + /// There are no comments for DatabaseModel.Client in the schema. + /// </summary> + /// <KeyProperties> + /// ClientId + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="Client")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class Client : global::System.Data.Objects.DataClasses.EntityObject + { /// <summary> - /// There are no comments for property IssuedTokenId in the schema. + /// Create a new Client object. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] - [global::System.Runtime.Serialization.DataMemberAttribute()] + /// <param name="clientId">Initial value of ClientId.</param> + /// <param name="clientIdentifier">Initial value of ClientIdentifier.</param> + /// <param name="name">Initial value of Name.</param> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public int IssuedTokenId + public static Client CreateClient(int clientId, string clientIdentifier, string name) { - get - { - return this._IssuedTokenId; - } - internal set - { - this.OnIssuedTokenIdChanging(value); - this.ReportPropertyChanging("IssuedTokenId"); - this._IssuedTokenId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("IssuedTokenId"); - this.OnIssuedTokenIdChanged(); - } + Client client = new Client(); + client.ClientId = clientId; + client.ClientIdentifier = clientIdentifier; + client.Name = name; + return client; } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private int _IssuedTokenId; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnIssuedTokenIdChanging(int value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnIssuedTokenIdChanged(); /// <summary> - /// There are no comments for Consumer in the schema. + /// There are no comments for property ClientId in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_Consumer1", "Consumer")] - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - [global::System.Xml.Serialization.XmlIgnoreAttribute()] - [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] - public Consumer Consumer - { - get - { - return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer1", "Consumer").Value; - } - set - { - ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer1", "Consumer").Value = value; - } - } - /// <summary> - /// There are no comments for Consumer in the schema. - /// </summary> - [global::System.ComponentModel.BrowsableAttribute(false)] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - [global::System.Runtime.Serialization.DataMemberAttribute()] - public global::System.Data.Objects.DataClasses.EntityReference<Consumer> ConsumerReference + public int ClientId { get { - return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer1", "Consumer"); + return this._ClientId; } set { - if ((value != null)) - { - ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer1", "Consumer", value); - } + this.OnClientIdChanging(value); + this.ReportPropertyChanging("ClientId"); + this._ClientId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("ClientId"); + this.OnClientIdChanged(); } } - /// <summary> - /// There are no comments for User in the schema. - /// </summary> - [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_User1", "User")] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - [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_User1", "User").Value; - } - set - { - ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User1", "User").Value = value; - } - } - /// <summary> - /// There are no comments for User in the schema. - /// </summary> - [global::System.ComponentModel.BrowsableAttribute(false)] + private int _ClientId; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - [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_User1", "User"); - } - set - { - if ((value != null)) - { - ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<User>("DatabaseModel.FK_IssuedToken_User1", "User", value); - } - } - } - } - /// <summary> - /// There are no comments for DatabaseModel.IssuedRequestToken in the schema. - /// </summary> - /// <KeyProperties> - /// IssuedTokenId - /// </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="token">Initial value of Token.</param> - /// <param name="tokenSecret">Initial value of TokenSecret.</param> - /// <param name="createdOnUtc">Initial value of CreatedOnUtc.</param> - /// <param name="issuedTokenId">Initial value of IssuedTokenId.</param> + partial void OnClientIdChanging(int value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public static IssuedRequestToken CreateIssuedRequestToken(string token, string tokenSecret, global::System.DateTime createdOnUtc, int issuedTokenId) - { - IssuedRequestToken issuedRequestToken = new IssuedRequestToken(); - issuedRequestToken.Token = token; - issuedRequestToken.TokenSecret = tokenSecret; - issuedRequestToken.CreatedOnUtc = createdOnUtc; - issuedRequestToken.IssuedTokenId = issuedTokenId; - return issuedRequestToken; - } + partial void OnClientIdChanged(); /// <summary> - /// There are no comments for property ConsumerVersionAsString in the schema. + /// There are no comments for property ClientIdentifier in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string ConsumerVersionAsString + public string ClientIdentifier { get { - return this._ConsumerVersionAsString; + return this._ClientIdentifier; } set { - this.OnConsumerVersionAsStringChanging(value); - this.ReportPropertyChanging("ConsumerVersionAsString"); - this._ConsumerVersionAsString = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("ConsumerVersionAsString"); - this.OnConsumerVersionAsStringChanged(); + this.OnClientIdentifierChanging(value); + this.ReportPropertyChanging("ClientIdentifier"); + this._ClientIdentifier = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("ClientIdentifier"); + this.OnClientIdentifierChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _ConsumerVersionAsString; + private string _ClientIdentifier; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnConsumerVersionAsStringChanging(string value); + partial void OnClientIdentifierChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnConsumerVersionAsStringChanged(); + partial void OnClientIdentifierChanged(); /// <summary> - /// There are no comments for property VerificationCode in the schema. + /// There are no comments for property ClientSecret in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string VerificationCode + public string ClientSecret { get { - return this._VerificationCode; + return this._ClientSecret; } set { - this.OnVerificationCodeChanging(value); - this.ReportPropertyChanging("VerificationCode"); - this._VerificationCode = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); - this.ReportPropertyChanged("VerificationCode"); - this.OnVerificationCodeChanged(); + this.OnClientSecretChanging(value); + this.ReportPropertyChanging("ClientSecret"); + this._ClientSecret = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("ClientSecret"); + this.OnClientSecretChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _VerificationCode; + private string _ClientSecret; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnVerificationCodeChanging(string value); + partial void OnClientSecretChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnVerificationCodeChanged(); + partial void OnClientSecretChanged(); /// <summary> /// There are no comments for property CallbackAsString in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string CallbackAsString + public string CallbackAsString { get { @@ -1414,422 +1308,265 @@ namespace RelyingPartyLogic partial void OnCallbackAsStringChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] partial void OnCallbackAsStringChanged(); - } - /// <summary> - /// There are no comments for DatabaseModel.IssuedAccessToken in the schema. - /// </summary> - /// <KeyProperties> - /// IssuedTokenId - /// </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="token">Initial value of Token.</param> - /// <param name="tokenSecret">Initial value of TokenSecret.</param> - /// <param name="createdOnUtc">Initial value of CreatedOnUtc.</param> - /// <param name="issuedTokenId">Initial value of IssuedTokenId.</param> - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public static IssuedAccessToken CreateIssuedAccessToken(string token, string tokenSecret, global::System.DateTime createdOnUtc, int issuedTokenId) - { - IssuedAccessToken issuedAccessToken = new IssuedAccessToken(); - issuedAccessToken.Token = token; - issuedAccessToken.TokenSecret = tokenSecret; - issuedAccessToken.CreatedOnUtc = createdOnUtc; - issuedAccessToken.IssuedTokenId = issuedTokenId; - return issuedAccessToken; - } - /// <summary> - /// There are no comments for property ExpirationDateUtc in the schema. + /// There are no comments for property Name in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.Nullable<global::System.DateTime> ExpirationDateUtc + public string Name { get { - return this._ExpirationDateUtc; + return this._Name; } set { - this.OnExpirationDateUtcChanging(value); - this.ReportPropertyChanging("ExpirationDateUtc"); - this._ExpirationDateUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("ExpirationDateUtc"); - this.OnExpirationDateUtcChanged(); + this.OnNameChanging(value); + this.ReportPropertyChanging("Name"); + this._Name = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("Name"); + this.OnNameChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.Nullable<global::System.DateTime> _ExpirationDateUtc; + private string _Name; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnExpirationDateUtcChanging(global::System.Nullable<global::System.DateTime> value); + partial void OnNameChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnExpirationDateUtcChanged(); - } - /// <summary> - /// There are no comments for DatabaseModel.Nonce in the schema. - /// </summary> - /// <KeyProperties> - /// NonceId - /// </KeyProperties> - [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="Nonce")] - [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] - [global::System.Serializable()] - public partial class Nonce : global::System.Data.Objects.DataClasses.EntityObject - { + partial void OnNameChanged(); /// <summary> - /// Create a new Nonce object. + /// There are no comments for ClientAuthorizations in the schema. /// </summary> - /// <param name="nonceId">Initial value of NonceId.</param> - /// <param name="context">Initial value of Context.</param> - /// <param name="code">Initial value of Code.</param> - /// <param name="issuedUtc">Initial value of IssuedUtc.</param> - /// <param name="expiresUtc">Initial value of ExpiresUtc.</param> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "ClientAuthorization")] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public static Nonce CreateNonce(int nonceId, string context, string code, global::System.DateTime issuedUtc, global::System.DateTime expiresUtc) - { - Nonce nonce = new Nonce(); - nonce.NonceId = nonceId; - nonce.Context = context; - nonce.Code = code; - nonce.IssuedUtc = issuedUtc; - nonce.ExpiresUtc = expiresUtc; - return nonce; - } - /// <summary> - /// There are no comments for property NonceId in the schema. - /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] [global::System.Runtime.Serialization.DataMemberAttribute()] - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public int NonceId + public global::System.Data.Objects.DataClasses.EntityCollection<ClientAuthorization> ClientAuthorizations { get { - return this._NonceId; + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<ClientAuthorization>("DatabaseModel.FK_IssuedToken_Consumer", "ClientAuthorization"); } set { - this.OnNonceIdChanging(value); - this.ReportPropertyChanging("NonceId"); - this._NonceId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("NonceId"); - this.OnNonceIdChanged(); + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<ClientAuthorization>("DatabaseModel.FK_IssuedToken_Consumer", "ClientAuthorization", value); + } } } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private int _NonceId; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnNonceIdChanging(int value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnNonceIdChanged(); + } + /// <summary> + /// There are no comments for DatabaseModel.ClientAuthorization in the schema. + /// </summary> + /// <KeyProperties> + /// AuthorizationId + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="ClientAuthorization")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class ClientAuthorization : global::System.Data.Objects.DataClasses.EntityObject + { /// <summary> - /// Gets or sets the Provider Endpoint URL the nonce came from. + /// Create a new ClientAuthorization object. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] - [global::System.Runtime.Serialization.DataMemberAttribute()] + /// <param name="authorizationId">Initial value of AuthorizationId.</param> + /// <param name="createdOnUtc">Initial value of CreatedOnUtc.</param> [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string Context + public static ClientAuthorization CreateClientAuthorization(int authorizationId, global::System.DateTime createdOnUtc) { - get - { - return this._Context; - } - set - { - this.OnContextChanging(value); - this.ReportPropertyChanging("Context"); - this._Context = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("Context"); - this.OnContextChanged(); - } + ClientAuthorization clientAuthorization = new ClientAuthorization(); + clientAuthorization.AuthorizationId = authorizationId; + clientAuthorization.CreatedOnUtc = createdOnUtc; + return clientAuthorization; } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _Context; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnContextChanging(string value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnContextChanged(); /// <summary> - /// There are no comments for property Code in the schema. + /// There are no comments for property AuthorizationId in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string Code + public int AuthorizationId { get { - return this._Code; + return this._AuthorizationId; } set { - this.OnCodeChanging(value); - this.ReportPropertyChanging("Code"); - this._Code = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("Code"); - this.OnCodeChanged(); + this.OnAuthorizationIdChanging(value); + this.ReportPropertyChanging("AuthorizationId"); + this._AuthorizationId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("AuthorizationId"); + this.OnAuthorizationIdChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _Code; + private int _AuthorizationId; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnCodeChanging(string value); + partial void OnAuthorizationIdChanging(int value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnCodeChanged(); + partial void OnAuthorizationIdChanged(); /// <summary> - /// There are no comments for property IssuedUtc in the schema. + /// There are no comments for property CreatedOnUtc in the schema. /// </summary> [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.DateTime IssuedUtc + public global::System.DateTime CreatedOnUtc { get { - return this._IssuedUtc; + return this._CreatedOnUtc; } set { - this.OnIssuedUtcChanging(value); - this.ReportPropertyChanging("IssuedUtc"); - this._IssuedUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("IssuedUtc"); - this.OnIssuedUtcChanged(); + this.OnCreatedOnUtcChanging(value); + this.ReportPropertyChanging("CreatedOnUtc"); + this._CreatedOnUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("CreatedOnUtc"); + this.OnCreatedOnUtcChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.DateTime _IssuedUtc; + private global::System.DateTime _CreatedOnUtc; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnIssuedUtcChanging(global::System.DateTime value); + partial void OnCreatedOnUtcChanging(global::System.DateTime value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnIssuedUtcChanged(); + partial void OnCreatedOnUtcChanged(); /// <summary> - /// There are no comments for property ExpiresUtc in the schema. + /// There are no comments for property ExpirationDate in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.DateTime ExpiresUtc + public global::System.Nullable<global::System.DateTime> ExpirationDate { get { - return this._ExpiresUtc; + return this._ExpirationDate; } set { - this.OnExpiresUtcChanging(value); - this.ReportPropertyChanging("ExpiresUtc"); - this._ExpiresUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("ExpiresUtc"); - this.OnExpiresUtcChanged(); + this.OnExpirationDateChanging(value); + this.ReportPropertyChanging("ExpirationDate"); + this._ExpirationDate = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("ExpirationDate"); + this.OnExpirationDateChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.DateTime _ExpiresUtc; + private global::System.Nullable<global::System.DateTime> _ExpirationDate; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnExpiresUtcChanging(global::System.DateTime value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnExpiresUtcChanged(); - } - /// <summary> - /// There are no comments for DatabaseModel.OpenIdAssociation in the schema. - /// </summary> - /// <KeyProperties> - /// AssociationId - /// </KeyProperties> - [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="OpenIdAssociation")] - [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] - [global::System.Serializable()] - public partial class OpenIdAssociation : global::System.Data.Objects.DataClasses.EntityObject - { - /// <summary> - /// Create a new OpenIdAssociation object. - /// </summary> - /// <param name="associationId">Initial value of AssociationId.</param> - /// <param name="distinguishingFactor">Initial value of DistinguishingFactor.</param> - /// <param name="associationHandle">Initial value of AssociationHandle.</param> - /// <param name="expirationUtc">Initial value of ExpirationUtc.</param> - /// <param name="privateData">Initial value of PrivateData.</param> - /// <param name="privateDataLength">Initial value of PrivateDataLength.</param> + partial void OnExpirationDateChanging(global::System.Nullable<global::System.DateTime> value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public static OpenIdAssociation CreateOpenIdAssociation(int associationId, string distinguishingFactor, string associationHandle, global::System.DateTime expirationUtc, byte[] privateData, int privateDataLength) - { - OpenIdAssociation openIdAssociation = new OpenIdAssociation(); - openIdAssociation.AssociationId = associationId; - openIdAssociation.DistinguishingFactor = distinguishingFactor; - openIdAssociation.AssociationHandle = associationHandle; - openIdAssociation.ExpirationUtc = expirationUtc; - openIdAssociation.PrivateData = privateData; - openIdAssociation.PrivateDataLength = privateDataLength; - return openIdAssociation; - } + partial void OnExpirationDateChanged(); /// <summary> - /// There are no comments for property AssociationId in the schema. + /// There are no comments for property Scope in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] [global::System.Runtime.Serialization.DataMemberAttribute()] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public int AssociationId + public string Scope { get { - return this._AssociationId; + return this._Scope; } set { - this.OnAssociationIdChanging(value); - this.ReportPropertyChanging("AssociationId"); - this._AssociationId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("AssociationId"); - this.OnAssociationIdChanged(); + this.OnScopeChanging(value); + this.ReportPropertyChanging("Scope"); + this._Scope = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("Scope"); + this.OnScopeChanged(); } } [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private int _AssociationId; + private string _Scope; [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnAssociationIdChanging(int value); + partial void OnScopeChanging(string value); [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnAssociationIdChanged(); + partial void OnScopeChanged(); /// <summary> - /// Gets or sets the Provider Endpoint URL the association is with. + /// There are no comments for Client in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] - [global::System.Runtime.Serialization.DataMemberAttribute()] - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string DistinguishingFactor - { - get - { - return this._DistinguishingFactor; - } - set - { - this.OnDistinguishingFactorChanging(value); - this.ReportPropertyChanging("DistinguishingFactor"); - this._DistinguishingFactor = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("DistinguishingFactor"); - this.OnDistinguishingFactorChanged(); - } - } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _DistinguishingFactor; + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "Client")] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnDistinguishingFactorChanging(string value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnDistinguishingFactorChanged(); - /// <summary> - /// There are no comments for property AssociationHandle in the schema. - /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] [global::System.Runtime.Serialization.DataMemberAttribute()] - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public string AssociationHandle + public Client Client { get { - return this._AssociationHandle; + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Client>("DatabaseModel.FK_IssuedToken_Consumer", "Client").Value; } set { - this.OnAssociationHandleChanging(value); - this.ReportPropertyChanging("AssociationHandle"); - this._AssociationHandle = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("AssociationHandle"); - this.OnAssociationHandleChanged(); + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Client>("DatabaseModel.FK_IssuedToken_Consumer", "Client").Value = value; } } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private string _AssociationHandle; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnAssociationHandleChanging(string value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnAssociationHandleChanged(); /// <summary> - /// There are no comments for property ExpirationUtc in the schema. + /// There are no comments for Client in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] - [global::System.Runtime.Serialization.DataMemberAttribute()] + [global::System.ComponentModel.BrowsableAttribute(false)] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public global::System.DateTime ExpirationUtc + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityReference<Client> ClientReference { get { - return this._ExpirationUtc; + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Client>("DatabaseModel.FK_IssuedToken_Consumer", "Client"); } set { - this.OnExpirationUtcChanging(value); - this.ReportPropertyChanging("ExpirationUtc"); - this._ExpirationUtc = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("ExpirationUtc"); - this.OnExpirationUtcChanged(); + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<Client>("DatabaseModel.FK_IssuedToken_Consumer", "Client", value); + } } } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private global::System.DateTime _ExpirationUtc; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnExpirationUtcChanging(global::System.DateTime value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnExpirationUtcChanged(); /// <summary> - /// There are no comments for property PrivateData in the schema. + /// There are no comments for User in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] - [global::System.Runtime.Serialization.DataMemberAttribute()] + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_User", "User")] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public byte[] PrivateData + [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.StructuralObject.GetValidValue(this._PrivateData); + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User").Value; } set { - this.OnPrivateDataChanging(value); - this.ReportPropertyChanging("PrivateData"); - this._PrivateData = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); - this.ReportPropertyChanged("PrivateData"); - this.OnPrivateDataChanged(); + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User").Value = value; } } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private byte[] _PrivateData; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnPrivateDataChanging(byte[] value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnPrivateDataChanged(); /// <summary> - /// There are no comments for property PrivateDataLength in the schema. + /// There are no comments for User in the schema. /// </summary> - [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] - [global::System.Runtime.Serialization.DataMemberAttribute()] + [global::System.ComponentModel.BrowsableAttribute(false)] [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - public int PrivateDataLength + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityReference<User> UserReference { get { - return this._PrivateDataLength; + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User"); } set { - this.OnPrivateDataLengthChanging(value); - this.ReportPropertyChanging("PrivateDataLength"); - this._PrivateDataLength = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); - this.ReportPropertyChanged("PrivateDataLength"); - this.OnPrivateDataLengthChanged(); + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User", value); + } } } - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - private int _PrivateDataLength; - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnPrivateDataLengthChanging(int value); - [global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")] - partial void OnPrivateDataLengthChanged(); } } diff --git a/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs b/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs deleted file mode 100644 index 25d983b..0000000 --- a/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------- -// <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; - } - } - - /// <summary> - /// Gets the expiration date (local time) for the access token. - /// </summary> - /// <value> - /// The expiration date, or <c>null</c> if there is no expiration date. - /// </value> - DateTime? IServiceProviderAccessToken.ExpirationDate { - get { return this.ExpirationDateUtc.HasValue ? (DateTime?)this.ExpirationDateUtc.Value.ToLocalTime() : null; } - } - - partial void OnExpirationDateUtcChanging(DateTime? value) { - if (value.HasValue) { - Utilities.VerifyThrowNotLocalTime(value.Value); - } - } - } -} diff --git a/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs b/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs deleted file mode 100644 index 1e96eb7..0000000 --- a/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs +++ /dev/null @@ -1,63 +0,0 @@ -//----------------------------------------------------------------------- -// <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> - /// Gets the (local) date that this request token was first created on. - /// </summary> - DateTime IServiceProviderRequestToken.CreatedOn { - get { return this.CreatedOnUtc.ToLocalTime(); } - } - - /// <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.edmx b/projecttemplates/RelyingPartyLogic/Model.edmx index 9d7ec7b..a003493 100644 --- a/projecttemplates/RelyingPartyLogic/Model.edmx +++ b/projecttemplates/RelyingPartyLogic/Model.edmx @@ -4,27 +4,27 @@ <edmx:Runtime> <!-- SSDL content --> <edmx:StorageModels> - <Schema Namespace="DatabaseModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl"> + <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" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" /> - <EntitySet Name="Consumer" EntityType="DatabaseModel.Store.Consumer" store:Type="Tables" Schema="dbo" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" /> - <EntitySet Name="IssuedToken" EntityType="DatabaseModel.Store.IssuedToken" store:Type="Tables" Schema="dbo" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" /> - <EntitySet Name="Nonce" EntityType="DatabaseModel.Store.Nonce" store:Type="Tables" Schema="dbo" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" /> - <EntitySet Name="OpenIDAssociation" EntityType="DatabaseModel.Store.OpenIDAssociation" store:Type="Tables" Schema="dbo" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" /> - <EntitySet Name="Role" EntityType="DatabaseModel.Store.Role" store:Type="Tables" Schema="dbo" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" /> - <EntitySet Name="User" EntityType="DatabaseModel.Store.User" store:Type="Tables" Schema="dbo" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" /> - <EntitySet Name="UserRole" EntityType="DatabaseModel.Store.UserRole" store:Type="Tables" Schema="dbo" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" /> + <EntitySet Name="AuthenticationToken" EntityType="DatabaseModel.Store.AuthenticationToken" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="Client" EntityType="DatabaseModel.Store.Client" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="ClientAuthorization" EntityType="DatabaseModel.Store.ClientAuthorization" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="Nonce" EntityType="DatabaseModel.Store.Nonce" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="OpenIDAssociation" EntityType="DatabaseModel.Store.OpenIDAssociation" 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" /> + <End Role="Client" EntitySet="Client" /> + <End Role="ClientAuthorization" EntitySet="ClientAuthorization" /> </AssociationSet> <AssociationSet Name="FK_IssuedToken_User" Association="DatabaseModel.Store.FK_IssuedToken_User"> <End Role="User" EntitySet="User" /> - <End Role="IssuedToken" EntitySet="IssuedToken" /> + <End Role="ClientAuthorization" EntitySet="ClientAuthorization" /> </AssociationSet> <AssociationSet Name="FK_UserRole_Role" Association="DatabaseModel.Store.FK_UserRole_Role"> <End Role="Role" EntitySet="Role" /> @@ -47,35 +47,26 @@ <Property Name="LastUsed" Type="datetime" Nullable="false" /> <Property Name="UsageCount" Type="int" Nullable="false" /> </EntityType> - <EntityType Name="Consumer"> + <EntityType Name="Client"> <Key> - <PropertyRef Name="ConsumerId" /> + <PropertyRef Name="ClientId" /> </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" /> + <Property Name="ClientId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> + <Property Name="ClientIdentifier" Type="varchar" Nullable="false" MaxLength="255" /> + <Property Name="ClientSecret" Type="varchar" MaxLength="255" /> + <Property Name="Callback" Type="varchar" MaxLength="2048" /> + <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" /> </EntityType> - <EntityType Name="IssuedToken"> + <EntityType Name="ClientAuthorization"> <Key> - <PropertyRef Name="IssuedTokenId" /> + <PropertyRef Name="AuthorizationId" /> </Key> - <Property Name="IssuedTokenId" 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="AuthorizationId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> + <Property Name="ClientId" Type="int" Nullable="false" /> + <Property Name="UserId" Type="int" Nullable="false" /> <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" /> + <Property Name="Scope" Type="varchar" MaxLength="2048" /> </EntityType> <EntityType Name="Nonce"> <Key> @@ -95,7 +86,7 @@ <Property Name="DistinguishingFactor" Type="varchar" Nullable="false" MaxLength="255" /> <Property Name="AssociationHandle" Type="varchar" Nullable="false" MaxLength="255" /> <Property Name="Expiration" Type="datetime" Nullable="false" /> - <Property Name="PrivateData" Type="binary" Nullable="false" MaxLength="32" /> + <Property Name="PrivateData" Type="binary" Nullable="false" MaxLength="64" /> <Property Name="PrivateDataLength" Type="int" Nullable="false" /> </EntityType> <EntityType Name="Role"> @@ -139,29 +130,29 @@ </ReferentialConstraint> </Association> <Association Name="FK_IssuedToken_Consumer"> - <End Role="Consumer" Type="DatabaseModel.Store.Consumer" Multiplicity="1"> + <End Role="Client" Type="DatabaseModel.Store.Client" Multiplicity="1"> <OnDelete Action="Cascade" /> </End> - <End Role="IssuedToken" Type="DatabaseModel.Store.IssuedToken" Multiplicity="*" /> + <End Role="ClientAuthorization" Type="DatabaseModel.Store.ClientAuthorization" Multiplicity="*" /> <ReferentialConstraint> - <Principal Role="Consumer"> - <PropertyRef Name="ConsumerId" /> + <Principal Role="Client"> + <PropertyRef Name="ClientId" /> </Principal> - <Dependent Role="IssuedToken"> - <PropertyRef Name="ConsumerId" /> + <Dependent Role="ClientAuthorization"> + <PropertyRef Name="ClientId" /> </Dependent> </ReferentialConstraint> </Association> <Association Name="FK_IssuedToken_User"> - <End Role="User" Type="DatabaseModel.Store.User" Multiplicity="0..1"> + <End Role="User" Type="DatabaseModel.Store.User" Multiplicity="1"> <OnDelete Action="Cascade" /> </End> - <End Role="IssuedToken" Type="DatabaseModel.Store.IssuedToken" Multiplicity="*" /> + <End Role="ClientAuthorization" Type="DatabaseModel.Store.ClientAuthorization" Multiplicity="*" /> <ReferentialConstraint> <Principal Role="User"> <PropertyRef Name="UserId" /> </Principal> - <Dependent Role="IssuedToken"> + <Dependent Role="ClientAuthorization"> <PropertyRef Name="UserId" /> </Dependent> </ReferentialConstraint> @@ -208,20 +199,23 @@ <End Role="User" EntitySet="Users" /> </AssociationSet> <EntitySet Name="AuthenticationTokens" EntityType="DatabaseModel.AuthenticationToken" /> - <EntitySet Name="Consumers" EntityType="DatabaseModel.Consumer" /> - <EntitySet Name="IssuedTokens" EntityType="DatabaseModel.IssuedToken" /> <AssociationSet Name="FK_AuthenticationToken_User" Association="DatabaseModel.FK_AuthenticationToken_User"> <End Role="User" EntitySet="Users" /> <End Role="AuthenticationToken" EntitySet="AuthenticationTokens" /></AssociationSet> - <AssociationSet Name="FK_IssuedToken_Consumer1" Association="DatabaseModel.FK_IssuedToken_Consumer1"> - <End Role="Consumer" EntitySet="Consumers" /> - <End Role="IssuedToken" EntitySet="IssuedTokens" /></AssociationSet> - <AssociationSet Name="FK_IssuedToken_User1" Association="DatabaseModel.FK_IssuedToken_User1"> - <End Role="User" EntitySet="Users" /> - <End Role="IssuedToken" EntitySet="IssuedTokens" /></AssociationSet> <EntitySet Name="Nonces" EntityType="DatabaseModel.Nonce" /> <EntitySet Name="OpenIdAssociations" EntityType="DatabaseModel.OpenIdAssociation" /> - <FunctionImport Name="ClearExpiredNonces" /></EntityContainer> + <FunctionImport Name="ClearExpiredNonces" /> + <EntitySet Name="Clients" EntityType="DatabaseModel.Client" /> + <EntitySet Name="ClientAuthorizations" EntityType="DatabaseModel.ClientAuthorization" /> + <AssociationSet Name="FK_IssuedToken_Consumer" Association="DatabaseModel.FK_IssuedToken_Consumer"> + <End Role="Client" EntitySet="Clients" /> + <End Role="ClientAuthorization" EntitySet="ClientAuthorizations" /> + </AssociationSet> + <AssociationSet Name="FK_IssuedToken_User" Association="DatabaseModel.FK_IssuedToken_User"> + <End Role="User" EntitySet="Users" /> + <End Role="ClientAuthorization" EntitySet="ClientAuthorizations" /> + </AssociationSet> + </EntityContainer> <EntityType Name="AuthenticationToken" Abstract="false"> <Key> <PropertyRef Name="AuthenticationTokenId" /></Key> @@ -253,48 +247,14 @@ <Property Name="CreatedOnUtc" Type="DateTime" Nullable="false" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> <Property Name="UserId" Type="Int32" Nullable="false" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> <NavigationProperty Name="AuthenticationTokens" Relationship="DatabaseModel.FK_AuthenticationToken_User" FromRole="User" ToRole="AuthenticationToken" /> - <NavigationProperty Name="IssuedTokens" Relationship="DatabaseModel.FK_IssuedToken_User1" FromRole="User" ToRole="IssuedToken" /></EntityType> + <NavigationProperty Name="ClientAuthorizations" Relationship="DatabaseModel.FK_IssuedToken_User" FromRole="User" ToRole="ClientAuthorization" /></EntityType> <Association Name="UserRole"> <End Role="Role" Type="DatabaseModel.Role" Multiplicity="*" /> <End Role="User" Type="DatabaseModel.User" 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" a:GetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> - <Property Name="CallbackAsString" Type="String" Nullable="true" /> - <Property Name="VerificationCodeFormatAsInt" Type="Int32" Nullable="false" a:GetterAccess="Private" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> - <Property Name="VerificationCodeLength" Type="Int32" Nullable="false" /> - <Property Name="ConsumerId" Type="Int32" Nullable="false" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> - <Property Name="Name" Type="String" Nullable="true" /> - <NavigationProperty Name="IssuedTokens" Relationship="DatabaseModel.FK_IssuedToken_Consumer1" FromRole="Consumer" ToRole="IssuedToken" /></EntityType> - <EntityType Name="IssuedToken" Abstract="true"> - <Key> - <PropertyRef Name="IssuedTokenId" /></Key> - <Property Name="Token" Type="String" Nullable="false" /> - <Property Name="TokenSecret" Type="String" Nullable="false" /> - <Property Name="CreatedOnUtc" Type="DateTime" Nullable="false" a:SetterAccess="Internal" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> - <Property Name="Scope" Type="String" Nullable="true" /> - <Property Name="IssuedTokenId" Type="Int32" Nullable="false" a:SetterAccess="Internal" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> - <NavigationProperty Name="Consumer" Relationship="DatabaseModel.FK_IssuedToken_Consumer1" FromRole="IssuedToken" ToRole="Consumer" /> - <NavigationProperty Name="User" Relationship="DatabaseModel.FK_IssuedToken_User1" FromRole="IssuedToken" ToRole="User" /></EntityType> - <EntityType Name="IssuedRequestToken" BaseType="DatabaseModel.IssuedToken"> - <Property Name="ConsumerVersionAsString" Type="String" Nullable="false" a:GetterAccess="Private" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> - <Property Name="VerificationCode" Type="String" Nullable="true" /> - <Property Name="CallbackAsString" Type="String" Nullable="true" a:GetterAccess="Private" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /></EntityType> - <EntityType Name="IssuedAccessToken" BaseType="DatabaseModel.IssuedToken"> - <Property Name="ExpirationDateUtc" Type="DateTime" Nullable="true" /></EntityType> <Association Name="FK_AuthenticationToken_User"> <End Type="DatabaseModel.User" Role="User" Multiplicity="1" /> <End Type="DatabaseModel.AuthenticationToken" Role="AuthenticationToken" Multiplicity="*" /></Association> - <Association Name="FK_IssuedToken_Consumer1"> - <End Type="DatabaseModel.Consumer" Role="Consumer" Multiplicity="1" /> - <End Type="DatabaseModel.IssuedToken" Role="IssuedToken" Multiplicity="*" /></Association> - <Association Name="FK_IssuedToken_User1"> - <End Type="DatabaseModel.User" Role="User" Multiplicity="0..1" /> - <End Type="DatabaseModel.IssuedToken" Role="IssuedToken" Multiplicity="*" /></Association> <EntityType Name="Nonce" a:TypeAccess="Public" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration"> <Key> <PropertyRef Name="NonceId" /></Key> @@ -315,7 +275,37 @@ <Property Name="AssociationHandle" Type="String" Nullable="false" /> <Property Name="ExpirationUtc" Type="DateTime" Nullable="false" /> <Property Name="PrivateData" Type="Binary" Nullable="false" /> - <Property Name="PrivateDataLength" Type="Int32" Nullable="false" /></EntityType></Schema> + <Property Name="PrivateDataLength" Type="Int32" Nullable="false" /></EntityType> + <EntityType Name="Client"> + <Key> + <PropertyRef Name="ClientId" /> + </Key> + <Property Type="Int32" Name="ClientId" Nullable="false" a:StoreGeneratedPattern="Identity" xmlns:a="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> + <Property Type="String" Name="ClientIdentifier" Nullable="false" MaxLength="255" FixedLength="false" Unicode="true" /> + <Property Type="String" Name="ClientSecret" MaxLength="255" FixedLength="false" Unicode="true" /> + <Property Type="String" Name="CallbackAsString" MaxLength="2048" FixedLength="false" Unicode="true" /> + <Property Type="String" Name="Name" MaxLength="50" FixedLength="false" Unicode="true" Nullable="false" /> + <NavigationProperty Name="ClientAuthorizations" Relationship="DatabaseModel.FK_IssuedToken_Consumer" FromRole="Client" ToRole="ClientAuthorization" /> + </EntityType> + <EntityType Name="ClientAuthorization"> + <Key> + <PropertyRef Name="AuthorizationId" /> + </Key> + <Property Type="Int32" Name="AuthorizationId" Nullable="false" a:StoreGeneratedPattern="Identity" xmlns:a="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> + <Property Type="DateTime" Name="CreatedOnUtc" Nullable="false" /> + <Property Type="DateTime" Name="ExpirationDate" /> + <Property Type="String" Name="Scope" MaxLength="2048" FixedLength="false" Unicode="false" /> + <NavigationProperty Name="Client" Relationship="DatabaseModel.FK_IssuedToken_Consumer" FromRole="ClientAuthorization" ToRole="Client" /> + <NavigationProperty Name="User" Relationship="DatabaseModel.FK_IssuedToken_User" FromRole="ClientAuthorization" ToRole="User" /> + </EntityType> + <Association Name="FK_IssuedToken_Consumer"> + <End Type="DatabaseModel.Client" Role="Client" Multiplicity="1" /> + <End Type="DatabaseModel.ClientAuthorization" Role="ClientAuthorization" Multiplicity="*" /> + </Association> + <Association Name="FK_IssuedToken_User"> + <End Type="DatabaseModel.User" Role="User" Multiplicity="1" /> + <End Type="DatabaseModel.ClientAuthorization" Role="ClientAuthorization" Multiplicity="*" /> + </Association></Schema> </edmx:ConceptualModels> <!-- C-S mapping content --> <edmx:Mappings> @@ -358,54 +348,11 @@ </MappingFragment> </EntityTypeMapping> </EntitySetMapping> - <EntitySetMapping Name="Consumers"> - <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="IssuedTokens"> - <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedToken)"> - <MappingFragment StoreEntitySet="IssuedToken"> - <ScalarProperty Name="IssuedTokenId" ColumnName="IssuedTokenId" /> - <ScalarProperty Name="Scope" ColumnName="Scope" /> - <ScalarProperty Name="CreatedOnUtc" ColumnName="CreatedOn" /> - <ScalarProperty Name="TokenSecret" ColumnName="TokenSecret" /> - <ScalarProperty Name="Token" ColumnName="Token" /> - </MappingFragment></EntityTypeMapping> - <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedRequestToken)"> - <MappingFragment StoreEntitySet="IssuedToken"> - <ScalarProperty Name="IssuedTokenId" ColumnName="IssuedTokenId" /> - <ScalarProperty Name="CallbackAsString" ColumnName="Callback" /> - <ScalarProperty Name="ConsumerVersionAsString" ColumnName="ConsumerVersion" /> - <ScalarProperty Name="VerificationCode" ColumnName="VerificationCode" /> - <Condition ColumnName="IsAccessToken" Value="0" /></MappingFragment></EntityTypeMapping> - <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedAccessToken)"> - <MappingFragment StoreEntitySet="IssuedToken"> - <ScalarProperty Name="IssuedTokenId" ColumnName="IssuedTokenId" /> - <ScalarProperty Name="ExpirationDateUtc" ColumnName="ExpirationDate" /> - <Condition ColumnName="IsAccessToken" Value="1" /></MappingFragment></EntityTypeMapping></EntitySetMapping> <AssociationSetMapping Name="FK_AuthenticationToken_User" TypeName="DatabaseModel.FK_AuthenticationToken_User" StoreEntitySet="AuthenticationToken"> <EndProperty Name="AuthenticationToken"> <ScalarProperty Name="AuthenticationTokenId" ColumnName="AuthenticationTokenId" /></EndProperty> <EndProperty Name="User"> <ScalarProperty Name="UserId" ColumnName="UserId" /></EndProperty></AssociationSetMapping> - <AssociationSetMapping Name="FK_IssuedToken_Consumer1" TypeName="DatabaseModel.FK_IssuedToken_Consumer1" StoreEntitySet="IssuedToken"> - <EndProperty Name="IssuedToken"> - <ScalarProperty Name="IssuedTokenId" ColumnName="IssuedTokenId" /></EndProperty> - <EndProperty Name="Consumer"> - <ScalarProperty Name="ConsumerId" ColumnName="ConsumerId" /></EndProperty></AssociationSetMapping> - <AssociationSetMapping Name="FK_IssuedToken_User1" TypeName="DatabaseModel.FK_IssuedToken_User1" StoreEntitySet="IssuedToken"> - <EndProperty Name="IssuedToken"> - <ScalarProperty Name="IssuedTokenId" ColumnName="IssuedTokenId" /></EndProperty> - <EndProperty Name="User"> - <ScalarProperty Name="UserId" ColumnName="UserId" /></EndProperty> - <Condition ColumnName="UserId" IsNull="false" /></AssociationSetMapping> <EntitySetMapping Name="Nonces"> <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.Nonce)"> <MappingFragment StoreEntitySet="Nonce"> @@ -423,7 +370,44 @@ <ScalarProperty Name="AssociationHandle" ColumnName="AssociationHandle" /> <ScalarProperty Name="DistinguishingFactor" ColumnName="DistinguishingFactor" /> <ScalarProperty Name="AssociationId" ColumnName="AssociationId" /></MappingFragment></EntityTypeMapping></EntitySetMapping> - <FunctionImportMapping FunctionImportName="ClearExpiredNonces" FunctionName="DatabaseModel.Store.ClearExpiredNonces" /></EntityContainerMapping> + <FunctionImportMapping FunctionImportName="ClearExpiredNonces" FunctionName="DatabaseModel.Store.ClearExpiredNonces" /> + <EntitySetMapping Name="Clients"> + <EntityTypeMapping TypeName="DatabaseModel.Client"> + <MappingFragment StoreEntitySet="Client"> + <ScalarProperty Name="Name" ColumnName="Name" /> + <ScalarProperty Name="CallbackAsString" ColumnName="Callback" /> + <ScalarProperty Name="ClientSecret" ColumnName="ClientSecret" /> + <ScalarProperty Name="ClientIdentifier" ColumnName="ClientIdentifier" /> + <ScalarProperty Name="ClientId" ColumnName="ClientId" /> + </MappingFragment> + </EntityTypeMapping> + </EntitySetMapping> + <EntitySetMapping Name="ClientAuthorizations"> + <EntityTypeMapping TypeName="DatabaseModel.ClientAuthorization"> + <MappingFragment StoreEntitySet="ClientAuthorization"> + <ScalarProperty Name="Scope" ColumnName="Scope" /> + <ScalarProperty Name="ExpirationDate" ColumnName="ExpirationDate" /> + <ScalarProperty Name="CreatedOnUtc" ColumnName="CreatedOn" /> + <ScalarProperty Name="AuthorizationId" ColumnName="AuthorizationId" /> + </MappingFragment> + </EntityTypeMapping> + </EntitySetMapping> + <AssociationSetMapping Name="FK_IssuedToken_Consumer" TypeName="DatabaseModel.FK_IssuedToken_Consumer" StoreEntitySet="ClientAuthorization"> + <EndProperty Name="ClientAuthorization"> + <ScalarProperty Name="AuthorizationId" ColumnName="AuthorizationId" /> + </EndProperty> + <EndProperty Name="Client"> + <ScalarProperty Name="ClientId" ColumnName="ClientId" /> + </EndProperty> + </AssociationSetMapping> + <AssociationSetMapping Name="FK_IssuedToken_User" TypeName="DatabaseModel.FK_IssuedToken_User" StoreEntitySet="ClientAuthorization"> + <EndProperty Name="ClientAuthorization"> + <ScalarProperty Name="AuthorizationId" ColumnName="AuthorizationId" /> + </EndProperty> + <EndProperty Name="User"> + <ScalarProperty Name="UserId" ColumnName="UserId" /> + </EndProperty> + </AssociationSetMapping></EntityContainerMapping> </Mapping> </edmx:Mappings> </edmx:Runtime> @@ -437,11 +421,13 @@ <edmx:Options> <DesignerInfoPropertySet xmlns="http://schemas.microsoft.com/ado/2007/06/edmx"> <DesignerProperty Name="ValidateOnBuild" Value="true" /> + <DesignerProperty Name="EnablePluralization" Value="True" /> + <DesignerProperty Name="IncludeForeignKeysInModel" Value="False" /> </DesignerInfoPropertySet> </edmx:Options> <!-- Diagram content (shape and connector positions) --> <edmx:Diagrams> - <Diagram Name="Model" ZoomLevel="56" xmlns="http://schemas.microsoft.com/ado/2007/06/edmx"> + <Diagram Name="Model" ZoomLevel="101" xmlns="http://schemas.microsoft.com/ado/2007/06/edmx"> <EntityTypeShape EntityType="DatabaseModel.AuthenticationToken" Width="1.875" PointX="5.25" PointY="0.75" Height="2.5571907552083339" IsExpanded="true" /> <EntityTypeShape EntityType="DatabaseModel.Role" Width="1.5" PointX="0.75" PointY="1.25" Height="1.59568359375" IsExpanded="true" /> <EntityTypeShape EntityType="DatabaseModel.User" Width="1.75" PointX="2.875" PointY="0.5" Height="3.1340950520833339" IsExpanded="true" /> @@ -451,30 +437,20 @@ <InheritanceConnector EntityType="DatabaseModel.AuthenticationToken"> <ConnectorPoint PointX="6.5625" PointY="3.375" /> <ConnectorPoint PointX="6.5625" PointY="2.9129850260416665" /></InheritanceConnector> - <EntityTypeShape EntityType="DatabaseModel.Consumer" Width="2.125" PointX="0.5" PointY="3.625" Height="2.1725878906249996" /> - <EntityTypeShape EntityType="DatabaseModel.IssuedToken" Width="2" PointX="5.25" PointY="3.875" Height="2.7494921874999996" /> - <EntityTypeShape EntityType="DatabaseModel.IssuedRequestToken" Width="2" PointX="4.25" PointY="7" Height="1.5956835937499996" /> - <EntityTypeShape EntityType="DatabaseModel.IssuedAccessToken" Width="1.625" PointX="6.5" PointY="7" Height="1.2110807291666657" /> - <InheritanceConnector EntityType="DatabaseModel.IssuedRequestToken" ManuallyRouted="false"> - <ConnectorPoint PointX="5.75" PointY="6.6244921875" /> - <ConnectorPoint PointX="5.75" PointY="7" /> - </InheritanceConnector> - <InheritanceConnector EntityType="DatabaseModel.IssuedAccessToken" ManuallyRouted="false"> - <ConnectorPoint PointX="6.875" PointY="6.6244921875" /> - <ConnectorPoint PointX="6.875" PointY="7" /> - </InheritanceConnector> <AssociationConnector Association="DatabaseModel.FK_AuthenticationToken_User"> - <ConnectorPoint PointX="4.625" PointY="1.4776205358072916" /> - <ConnectorPoint PointX="5.25" PointY="1.4776205358072916" /></AssociationConnector> - <AssociationConnector Association="DatabaseModel.FK_IssuedToken_Consumer1"> - <ConnectorPoint PointX="2.625" PointY="4.8322661624685885" /> - <ConnectorPoint PointX="5.25" PointY="4.8322661624685885" /> - </AssociationConnector> - <AssociationConnector Association="DatabaseModel.FK_IssuedToken_User1"> - <ConnectorPoint PointX="3.75" PointY="3.6340950520833339" /> - <ConnectorPoint PointX="3.75" PointY="4.0627779870647478" /> - <ConnectorPoint PointX="5.25" PointY="4.0627779870647478" /></AssociationConnector> - <EntityTypeShape EntityType="DatabaseModel.Nonce" Width="1.5" PointX="0.5" PointY="7.75" Height="1.9802864583333326" /> - <EntityTypeShape EntityType="DatabaseModel.OpenIdAssociation" Width="1.75" PointX="2.25" PointY="7.75" Height="1.9802864583333333" /></Diagram></edmx:Diagrams> + <ConnectorPoint PointX="4.625" PointY="1.9324446614583337" /> + <ConnectorPoint PointX="5.25" PointY="1.9324446614583337" /></AssociationConnector> + <EntityTypeShape EntityType="DatabaseModel.Nonce" Width="1.5" PointX="9.375" PointY="0.75" Height="1.9802864583333326" /> + <EntityTypeShape EntityType="DatabaseModel.OpenIdAssociation" Width="1.75" PointX="7.375" PointY="0.75" Height="2.1725878906249996" /> + <EntityTypeShape EntityType="DatabaseModel.Client" Width="1.625" PointX="5.25" PointY="3.75" Height="2.1725878906249996" /> + <EntityTypeShape EntityType="DatabaseModel.ClientAuthorization" Width="1.75" PointX="2.875" PointY="3.75" Height="2.1725878906250031" /> + <AssociationConnector Association="DatabaseModel.FK_IssuedToken_Consumer" > + <ConnectorPoint PointX="5.25" PointY="4.8362939453125" /> + <ConnectorPoint PointX="4.625" PointY="4.8362939453125" /> + </AssociationConnector> + <AssociationConnector Association="DatabaseModel.FK_IssuedToken_User" > + <ConnectorPoint PointX="3.75" PointY="3.2494921875" /> + <ConnectorPoint PointX="3.75" PointY="3.75" /> + </AssociationConnector></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 index e47e4ee..c0685bc 100644 --- a/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs @@ -12,9 +12,7 @@ namespace RelyingPartyLogic { using System.Web; using System.Web.Security; using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OAuth; - using DotNetOpenAuth.OAuth.ChannelElements; - using DotNetOpenAuth.OAuth.Messages; + using DotNetOpenAuth.OAuth2; public class OAuthAuthenticationModule : IHttpModule { private HttpApplication application; @@ -51,10 +49,13 @@ namespace RelyingPartyLogic { 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); + var tokenAnalyzer = new SpecialAccessTokenAnalyzer(OAuthAuthorizationServer.AsymmetricKey, OAuthAuthorizationServer.AsymmetricKey); + var resourceServer = new ResourceServer(tokenAnalyzer); + + IPrincipal principal; + var errorMessage = resourceServer.VerifyAccess(new HttpRequestInfo(this.application.Context.Request), out principal); + if (errorMessage == null) { + this.application.Context.User = principal; } } @@ -70,7 +71,7 @@ namespace RelyingPartyLogic { /// <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) { + if (this.application.User is DotNetOpenAuth.OAuth.ChannelElements.OAuthPrincipal) { e.RolesPopulated = true; } } diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs index 35af472..6ac2977 100644 --- a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs @@ -15,6 +15,7 @@ namespace RelyingPartyLogic { using System.ServiceModel.Security; using DotNetOpenAuth; using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth2; /// <summary> /// A WCF extension to authenticate incoming messages using OAuth. @@ -28,15 +29,16 @@ namespace RelyingPartyLogic { 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; - try { - var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri); - if (auth != null) { - var accessToken = Database.DataContext.IssuedTokens.OfType<IssuedAccessToken>().First(token => token.Token == auth.AccessToken); + var httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; + var requestUri = operationContext.RequestContext.RequestMessage.Properties["OriginalHttpRequestUri"] as Uri; - var principal = sp.CreatePrincipal(auth); + var tokenAnalyzer = new SpecialAccessTokenAnalyzer(OAuthAuthorizationServer.AsymmetricKey, OAuthAuthorizationServer.AsymmetricKey); + var resourceServer = new ResourceServer(tokenAnalyzer); + + try { + IPrincipal principal; + var errorResponse = resourceServer.VerifyAccess(httpDetails, requestUri, out principal); + if (errorResponse == null) { var policy = new OAuthPrincipalAuthorizationPolicy(principal); var policies = new List<IAuthorizationPolicy> { policy, @@ -56,8 +58,7 @@ namespace RelyingPartyLogic { }; // Only allow this method call if the access token scope permits it. - string[] scopes = accessToken.Scope.Split('|'); - if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { + if (principal.IsInRole(operationContext.IncomingMessageHeaders.Action)) { return true; } } diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs new file mode 100644 index 0000000..2b207f9 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs @@ -0,0 +1,176 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthAuthorizationServer.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; + using System.Text; + using System.Web; + + using DotNetOpenAuth.Messaging.Bindings; + using DotNetOpenAuth.OAuth2; + using DotNetOpenAuth.OAuth2.ChannelElements; + using DotNetOpenAuth.OAuth2.Messages; + + /// <summary> + /// Provides OAuth 2.0 authorization server information to DotNetOpenAuth. + /// </summary> + public class OAuthAuthorizationServer : IAuthorizationServer { + internal static readonly RSAParameters AsymmetricKey; + + private static readonly byte[] secret; + + private readonly INonceStore nonceStore = new NonceDbStore(); + + static OAuthAuthorizationServer() { + // TODO: Replace this sample code with real code. + // For this sample, we just generate random secrets. + RandomNumberGenerator crypto = new RNGCryptoServiceProvider(); + secret = new byte[16]; + crypto.GetBytes(secret); + + AsymmetricKey = new RSACryptoServiceProvider().ExportParameters(true); + } + + /// <summary> + /// Initializes a new instance of the <see cref="OAuthAuthorizationServer"/> class. + /// </summary> + public OAuthAuthorizationServer() { + } + + #region IAuthorizationServer Members + + /// <summary> + /// Gets the secret used to symmetrically encrypt and sign authorization codes and refresh tokens. + /// </summary> + /// <value></value> + /// <remarks> + /// This secret should be kept strictly confidential in the authorization server(s) + /// and NOT shared with the resource server. Anyone with this secret can mint + /// tokens to essentially grant themselves access to anything they want. + /// </remarks> + public byte[] Secret { + get { return secret; } + } + + /// <summary> + /// Gets the asymmetric private key to use for signing access tokens. + /// </summary> + /// <value></value> + /// <remarks> + /// The public key in the private/public key pair will be used by the resource + /// servers to validate that the access token is minted by a trusted authorization server. + /// </remarks> + public RSAParameters AccessTokenSigningPrivateKey { + get { return AsymmetricKey; } + } + + /// <summary> + /// Gets the authorization code nonce store to use to ensure that authorization codes can only be used once. + /// </summary> + /// <value>The authorization code nonce store.</value> + public INonceStore VerificationCodeNonceStore { + get { return this.nonceStore; } + } + + /// <summary> + /// Gets the client with a given identifier. + /// </summary> + /// <param name="clientIdentifier">The client identifier.</param> + /// <returns>The client registration. Never null.</returns> + /// <exception cref="ArgumentException">Thrown when no client with the given identifier is registered with this authorization server.</exception> + public IConsumerDescription GetClient(string clientIdentifier) { + try { + return Database.DataContext.Clients.First(c => c.ClientIdentifier == clientIdentifier); + } catch (InvalidOperationException ex) { + throw new ArgumentOutOfRangeException("No client by that identifier.", ex); + } + } + + /// <summary> + /// Determines whether a described authorization is (still) valid. + /// </summary> + /// <param name="authorization">The authorization.</param> + /// <returns> + /// <c>true</c> if the original authorization is still valid; otherwise, <c>false</c>. + /// </returns> + /// <remarks> + /// <para>When establishing that an authorization is still valid, + /// it's very important to only match on recorded authorizations that + /// meet these criteria:</para> + /// 1) The client identifier matches. + /// 2) The user account matches. + /// 3) The scope on the recorded authorization must include all scopes in the given authorization. + /// 4) The date the recorded authorization was issued must be <em>no later</em> that the date the given authorization was issued. + /// <para>One possible scenario is where the user authorized a client, later revoked authorization, + /// and even later reinstated authorization. This subsequent recorded authorization + /// would not satisfy requirement #4 in the above list. This is important because the revocation + /// the user went through should invalidate all previously issued tokens as a matter of + /// security in the event the user was revoking access in order to sever authorization on a stolen + /// account or piece of hardware in which the tokens were stored. </para> + /// </remarks> + public bool IsAuthorizationValid(IAuthorizationDescription authorization) { + return this.IsAuthorizationValid(authorization.Scope, authorization.ClientIdentifier, authorization.UtcIssued, authorization.User); + } + + #endregion + + public bool CanBeAutoApproved(EndUserAuthorizationRequest authorizationRequest) { + if (authorizationRequest == null) { + throw new ArgumentNullException("authorizationRequest"); + } + + // NEVER issue an auto-approval to a client that would end up getting an access token immediately + // (without a client secret), as that would allow ANY client to spoof an approved client's identity + // and obtain unauthorized access to user data. + if (authorizationRequest.ResponseType == EndUserAuthorizationResponseType.AuthorizationCode) { + // Never issue auto-approval if the client secret is blank, since that too makes it easy to spoof + // a client's identity and obtain unauthorized access. + var requestingClient = Database.DataContext.Clients.First(c => c.ClientIdentifier == authorizationRequest.ClientIdentifier); + if (!string.IsNullOrEmpty(requestingClient.ClientSecret)) { + return this.IsAuthorizationValid( + authorizationRequest.Scope, + authorizationRequest.ClientIdentifier, + DateTime.UtcNow, + HttpContext.Current.User.Identity.Name); + } + } + + // Default to not auto-approving. + return false; + } + + private bool IsAuthorizationValid(string requestedScope, string clientIdentifier, DateTime issuedUtc, string username) + { + var stringCompare = StringComparer.Ordinal; + var requestedScopes = OAuthUtilities.BreakUpScopes(requestedScope, stringCompare); + + var grantedScopeStrings = from auth in Database.DataContext.ClientAuthorizations + where + auth.Client.ClientIdentifier == clientIdentifier && + auth.CreatedOnUtc <= issuedUtc && + auth.User.AuthenticationTokens.Any(token => token.ClaimedIdentifier == username) + select auth.Scope; + + if (!grantedScopeStrings.Any()) { + // No granted authorizations prior to the issuance of this token, so it must have been revoked. + // Even if later authorizations restore this client's ability to call in, we can't allow + // access tokens issued before the re-authorization because the revoked authorization should + // effectively and permanently revoke all access and refresh tokens. + return false; + } + + var grantedScopes = new HashSet<string>(stringCompare); + foreach (string scope in grantedScopeStrings) { + grantedScopes.UnionWith(OAuthUtilities.BreakUpScopes(scope, stringCompare)); + } + + return requestedScopes.IsSubsetOf(grantedScopes); + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs b/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs deleted file mode 100644 index 64e6be8..0000000 --- a/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs +++ /dev/null @@ -1,48 +0,0 @@ -//----------------------------------------------------------------------- -// <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 index ddd0b3f..482f44b 100644 --- a/projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs +++ b/projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs @@ -10,18 +10,19 @@ namespace RelyingPartyLogic { using System.IdentityModel.Claims; using System.IdentityModel.Policy; using System.Linq; + using System.Security.Principal; using System.Web; using DotNetOpenAuth.OAuth.ChannelElements; public class OAuthPrincipalAuthorizationPolicy : IAuthorizationPolicy { private readonly Guid uniqueId = Guid.NewGuid(); - private readonly OAuthPrincipal principal; + private readonly IPrincipal principal; /// <summary> /// Initializes a new instance of the <see cref="OAuthPrincipalAuthorizationPolicy"/> class. /// </summary> /// <param name="principal">The principal.</param> - public OAuthPrincipalAuthorizationPolicy(OAuthPrincipal principal) { + public OAuthPrincipalAuthorizationPolicy(IPrincipal principal) { this.principal = principal; } diff --git a/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs b/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs index 807da2d..9b6fb50 100644 --- a/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs +++ b/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs @@ -10,9 +10,9 @@ namespace RelyingPartyLogic { using System.Linq; using System.Web; using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OAuth; - using DotNetOpenAuth.OAuth.ChannelElements; - using DotNetOpenAuth.OAuth.Messages; + using DotNetOpenAuth.OAuth2; + using DotNetOpenAuth.OAuth2.ChannelElements; + using DotNetOpenAuth.OAuth2.Messages; public class OAuthServiceProvider { private const string PendingAuthorizationRequestSessionKey = "PendingAuthorizationRequest"; @@ -20,28 +20,26 @@ namespace RelyingPartyLogic { /// <summary> /// The shared service description for this web site. /// </summary> - private static ServiceProviderDescription serviceDescription; - - private static OAuthServiceProviderTokenManager tokenManager; + private static AuthorizationServerDescription authorizationServerDescription; /// <summary> - /// The shared service provider object. + /// The shared authorization server. /// </summary> - private static ServiceProvider serviceProvider; + private static WebServerAuthorizationServer authorizationServer; /// <summary> - /// The lock to synchronize initialization of the <see cref="serviceProvider"/> field. + /// The lock to synchronize initialization of the <see cref="authorizationServer"/> field. /// </summary> - private static object initializerLock = new object(); + private static readonly object InitializerLock = new object(); /// <summary> /// Gets the service provider. /// </summary> /// <value>The service provider.</value> - public static ServiceProvider ServiceProvider { + public static WebServerAuthorizationServer AuthorizationServer { get { EnsureInitialized(); - return serviceProvider; + return authorizationServer; } } @@ -49,83 +47,28 @@ namespace RelyingPartyLogic { /// Gets the service description. /// </summary> /// <value>The service description.</value> - public static ServiceProviderDescription ServiceDescription { + public static AuthorizationServerDescription AuthorizationServerDescription { 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.IssuedTokens.OfType<IssuedRequestToken>().Include("Consumer").First(t => t.Token == message.Token).Consumer; - } - } - - public static void AuthorizePendingRequestToken() { - var response = AuthorizePendingRequestTokenAndGetResponse(); - if (response != null) { - serviceProvider.Channel.Send(response); - } - } - - public static OutgoingWebResponse AuthorizePendingRequestTokenAsWebResponse() { - var response = AuthorizePendingRequestTokenAndGetResponse(); - if (response != null) { - return serviceProvider.Channel.PrepareResponse(response); - } else { - return null; + return authorizationServerDescription; } } - private static UserAuthorizationResponse AuthorizePendingRequestTokenAndGetResponse() { - var pendingRequest = PendingAuthorizationRequest; - if (pendingRequest == null) { - throw new InvalidOperationException("No pending authorization request to authorize."); - } - - ITokenContainingMessage msg = pendingRequest; - var token = Database.DataContext.IssuedTokens.OfType<IssuedRequestToken>().First(t => t.Token == msg.Token); - token.Authorize(); - - PendingAuthorizationRequest = null; - var response = serviceProvider.PrepareAuthorizationResponse(pendingRequest); - return response; - } - /// <summary> - /// Initializes the <see cref="serviceProvider"/> field if it has not yet been initialized. + /// Initializes the <see cref="authorizationServer"/> 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 (authorizationServer == null) { + lock (InitializerLock) { + if (authorizationServerDescription == null) { + authorizationServerDescription = new AuthorizationServerDescription { + AuthorizationEndpoint = new Uri(Utilities.ApplicationRoot, "OAuth.ashx"), + TokenEndpoint = new Uri(Utilities.ApplicationRoot, "OAuth.ashx"), }; } - if (tokenManager == null) { - tokenManager = new OAuthServiceProviderTokenManager(); - } - - if (serviceProvider == null) { - serviceProvider = new ServiceProvider(serviceDescription, tokenManager); + if (authorizationServer == null) { + authorizationServer = new WebServerAuthorizationServer(new OAuthAuthorizationServer()); } } } diff --git a/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs b/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs deleted file mode 100644 index 4ae50ce..0000000 --- a/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs +++ /dev/null @@ -1,112 +0,0 @@ -//----------------------------------------------------------------------- -// <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.Consumers.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.IssuedTokens.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.IssuedTokens.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.IssuedTokens.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 deleted file mode 100644 index fbf808c..0000000 --- a/projecttemplates/RelyingPartyLogic/OAuthTokenManager.cs +++ /dev/null @@ -1,141 +0,0 @@ -//----------------------------------------------------------------------- -// <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.IssuedTokens.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.Consumers.First(c => c.ConsumerKey == request.ConsumerKey); - } catch (InvalidOperationException) { - throw new ArgumentOutOfRangeException(); - } - - var token = new IssuedRequestToken { - Callback = request.Callback, - Consumer = consumer, - Token = response.Token, - TokenSecret = response.TokenSecret, - }; - string scope; - if (request.ExtraData.TryGetValue("scope", out scope)) { - token.Scope = scope; - } - Database.DataContext.AddToIssuedTokens(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.IssuedTokens.OfType<IssuedRequestToken>() - .Include("User") - .First(t => t.Consumer.ConsumerKey == consumerKey && t.Token == requestToken); - - var accessTokenEntity = new IssuedAccessToken { - Token = accessToken, - TokenSecret = accessTokenSecret, - ExpirationDateUtc = null, // currently, our access tokens don't expire - User = requestTokenEntity.User, - Scope = requestTokenEntity.Scope, - Consumer = requestTokenEntity.Consumer, - }; - - Database.DataContext.DeleteObject(requestTokenEntity); - Database.DataContext.AddToIssuedTokens(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.IssuedTokens.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/RelyingPartyLogic.csproj b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj index 338622c..06dee41 100644 --- a/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj +++ b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj @@ -106,31 +106,28 @@ </ItemGroup> <ItemGroup> <Compile Include="Model.cs" /> - <Compile Include="Model.IssuedToken.cs" /> + <Compile Include="Model.ClientAuthorization.cs" /> <Compile Include="Database.cs" /> <Compile Include="DataRoleProvider.cs" /> <Compile Include="Model.AuthenticationToken.cs" /> - <Compile Include="Model.Consumer.cs" /> + <Compile Include="Model.Client.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.OpenIdAssociation.cs" /> <Compile Include="Model.User.cs" /> <Compile Include="NonceDbStore.cs" /> + <Compile Include="OAuthAuthorizationServer.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="RelyingPartyApplicationDbStore.cs" /> + <Compile Include="SpecialAccessTokenAnalyzer.cs" /> <Compile Include="Utilities.cs" /> </ItemGroup> <ItemGroup> @@ -144,12 +141,12 @@ <Project>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</Project> <Name>DotNetOpenAuth</Name> </ProjectReference> - <ProjectReference Include="..\RelyingPartyDatabase\RelyingPartyDatabase.dbproj"> - <Name>RelyingPartyDatabase</Name> - <!-- Deploy the latest SQL script first, so that this project can embed the latest version. --> - <Targets>Build;Deploy</Targets> - <ReferenceOutputAssembly>false</ReferenceOutputAssembly> - </ProjectReference> + <ProjectReference Include="..\RelyingPartyDatabase\RelyingPartyDatabase.dbproj"> + <Name>RelyingPartyDatabase</Name> + <!-- Deploy the latest SQL script first, so that this project can embed the latest version. --> + <Targets>Build;Deploy</Targets> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> </ItemGroup> <ItemGroup> <EmbeddedResource Include="CreateDatabase.sql" /> diff --git a/projecttemplates/RelyingPartyLogic/SpecialAccessTokenAnalyzer.cs b/projecttemplates/RelyingPartyLogic/SpecialAccessTokenAnalyzer.cs new file mode 100644 index 0000000..f189433 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/SpecialAccessTokenAnalyzer.cs @@ -0,0 +1,36 @@ +//----------------------------------------------------------------------- +// <copyright file="SpecialAccessTokenAnalyzer.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; + using System.Text; + + using DotNetOpenAuth.OAuth2; + + internal class SpecialAccessTokenAnalyzer : StandardAccessTokenAnalyzer { + /// <summary> + /// Initializes a new instance of the <see cref="SpecialAccessTokenAnalyzer"/> class. + /// </summary> + /// <param name="authorizationServerPublicSigningKey">The authorization server public signing key.</param> + /// <param name="resourceServerPrivateEncryptionKey">The resource server private encryption key.</param> + internal SpecialAccessTokenAnalyzer(RSAParameters authorizationServerPublicSigningKey, RSAParameters resourceServerPrivateEncryptionKey) + : base(authorizationServerPublicSigningKey, resourceServerPrivateEncryptionKey) { + } + + public override bool TryValidateAccessToken(DotNetOpenAuth.Messaging.IDirectedProtocolMessage message, string accessToken, out string user, out string scope) { + bool result = base.TryValidateAccessToken(message, accessToken, out user, out scope); + if (result) { + // Ensure that clients coming in this way always belong to the oauth_client role. + scope += " " + "oauth_client"; + } + + return result; + } + } +} diff --git a/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx b/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx index fd438d0..458d624 100644 --- a/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx +++ b/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx @@ -89,12 +89,14 @@ </HeaderTemplate> <ItemTemplate> <li> - <asp:Label runat="server" Text='<%# HttpUtility.HtmlEncode(Eval("Consumer.Name").ToString()) %>' /> + <asp:Label runat="server" Text='<%# HttpUtility.HtmlEncode(Eval("Client.Name").ToString()) %>' /> - - <asp:Label ID="Label1" runat="server" Text='<%# HttpUtility.HtmlEncode(Eval("CreatedOn").ToString()) %>' ForeColor="Gray" /> + <asp:Label ID="Label2" runat="server" Text='<%# HttpUtility.HtmlEncode((string)Eval("Scope")) %>' ForeColor="Gray" /> + - + <asp:Label ID="Label1" runat="server" Text='<%# HttpUtility.HtmlEncode(Eval("CreatedOnUtc").ToString()) %>' ForeColor="Gray" /> - <asp:LinkButton ID="revokeLink" runat="server" Text="revoke" OnCommand="revokeToken_Command" - CommandName="revokeToken" CommandArgument='<%# Eval("Token") %>' /> + CommandName="revokeToken" CommandArgument='<%# Eval("AuthorizationId") %>' /> </li> </ItemTemplate> <FooterTemplate> diff --git a/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx.cs b/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx.cs index 68b4398..95feb8c 100644 --- a/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx.cs +++ b/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx.cs @@ -20,16 +20,16 @@ namespace WebFormsRelyingParty.Members { Database.LoggedInUser.AuthenticationTokens.Load(); this.Repeater1.DataSource = Database.LoggedInUser.AuthenticationTokens; - if (!Database.LoggedInUser.IssuedTokens.IsLoaded) { - Database.LoggedInUser.IssuedTokens.Load(); + if (!Database.LoggedInUser.ClientAuthorizations.IsLoaded) { + Database.LoggedInUser.ClientAuthorizations.Load(); } - this.tokenListRepeater.DataSource = Database.LoggedInUser.IssuedTokens; - foreach (var token in Database.LoggedInUser.IssuedTokens) { - if (!token.ConsumerReference.IsLoaded) { - token.ConsumerReference.Load(); + this.tokenListRepeater.DataSource = Database.LoggedInUser.ClientAuthorizations; + foreach (var token in Database.LoggedInUser.ClientAuthorizations) { + if (!token.ClientReference.IsLoaded) { + token.ClientReference.Load(); } } - this.authorizedClientsPanel.Visible = Database.LoggedInUser.IssuedTokens.Count > 0; + this.authorizedClientsPanel.Visible = Database.LoggedInUser.ClientAuthorizations.Count > 0; if (!IsPostBack) { this.Repeater1.DataBind(); @@ -71,14 +71,14 @@ namespace WebFormsRelyingParty.Members { } protected void revokeToken_Command(object sender, CommandEventArgs e) { - string token = (string)e.CommandArgument; - var tokenToRevoke = Database.DataContext.IssuedTokens.FirstOrDefault(t => t.Token == token && t.User.UserId == Database.LoggedInUser.UserId); + int authorizationId = Convert.ToInt32(e.CommandArgument); + var tokenToRevoke = Database.DataContext.ClientAuthorizations.FirstOrDefault(a => a.AuthorizationId == authorizationId && a.User.UserId == Database.LoggedInUser.UserId); if (tokenToRevoke != null) { Database.DataContext.DeleteObject(tokenToRevoke); } this.tokenListRepeater.DataBind(); - this.noAuthorizedClientsPanel.Visible = Database.LoggedInUser.IssuedTokens.Count == 0; + this.noAuthorizedClientsPanel.Visible = Database.LoggedInUser.ClientAuthorizations.Count == 0; } private void AddIdentifier(string claimedId, string friendlyId) { diff --git a/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx.designer.cs b/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx.designer.cs index 359794b..100b794 100644 --- a/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx.designer.cs +++ b/projecttemplates/WebFormsRelyingParty/Members/AccountInfo.aspx.designer.cs @@ -1,10 +1,9 @@ //------------------------------------------------------------------------------ // <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. +// the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ diff --git a/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx b/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx index 7886157..9ec00a8 100644 --- a/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx +++ b/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx @@ -5,81 +5,45 @@ <h2> Client authorization </h2> - <asp:MultiView runat="server" ID="outerMultiView" ActiveViewIndex="0"> - <asp:View runat="server" ID="getPermissionView"> - <div style="background-color: Yellow"> - <b>Warning</b>: Never give your login credentials to another web site or application. - </div> - <p> - The - <asp:Label ID="consumerNameLabel" runat="server" Text="(app name)" /> - application is requesting to access the private data in your account here. Is that - alright with you? - </p> - <p> - If you grant access now, you can revoke it at any time by returning to <a href="AccountInfo.aspx" - target="_blank">your account page</a>. - </p> - <div style="display: none" id="responseButtonsDiv"> - <asp:Button ID="yesButton" runat="server" Text="Yes" OnClick="yesButton_Click" /> - <asp:Button ID="noButton" runat="server" Text="No" OnClick="noButton_Click" /> - <asp:HiddenField runat="server" ID="csrfCheck" EnableViewState="false" /> - </div> - <div id="javascriptDisabled"> - <b>Javascript appears to be disabled in your browser. </b>This page requires Javascript - to be enabled to better protect your security. - </div> - <asp:Panel runat="server" BackColor="Red" ForeColor="White" Font-Bold="true" Visible="false" - ID="OAuth10ConsumerWarning"> - This website is registered with - <asp:Label runat="server" ID="serviceProviderDomainNameLabel" /> - to make authorization requests, but has not been configured to send requests securely. - If you grant access but you did not initiate this request at - <asp:Label runat="server" ID="consumerDomainNameLabel1" />, it may be possible for - other users of - <asp:Label runat="server" ID="consumerDomainNameLabel2" /> - to access your data. We recommend you deny access unless you are certain that you - initiated this request directly with - <asp:Label runat="server" ID="consumerDomainNameLabel3" />. - </asp:Panel> + <div style="background-color: Yellow"> + <b>Warning</b>: Never give your login credentials to another web site or application. + </div> + <p> + The + <asp:Label ID="consumerNameLabel" runat="server" Text="(app name)" /> + application is requesting to access the private data in your account here. Is that + alright with you? + </p> + <p> + <b>Requested access: </b> + <asp:Label runat="server" ID="scopeLabel" /> + </p> + <p> + If you grant access now, you can revoke it at any time by returning to <a href="AccountInfo.aspx" + target="_blank">your account page</a>. + </p> + <div style="display: none" id="responseButtonsDiv"> + <asp:Button ID="yesButton" runat="server" Text="Yes" OnClick="yesButton_Click" /> + <asp:Button ID="noButton" runat="server" Text="No" OnClick="noButton_Click" /> + <asp:HiddenField runat="server" ID="csrfCheck" EnableViewState="false" /> + </div> + <div id="javascriptDisabled"> + <b>Javascript appears to be disabled in your browser. </b>This page requires Javascript + to be enabled to better protect your security. + </div> - <script language="javascript" type="text/javascript"> - //<![CDATA[ - // we use HTML to hide the action buttons and Javascript to show them - // to protect against click-jacking in an iframe whose javascript is disabled. - document.getElementById('responseButtonsDiv').style.display = 'block'; - document.getElementById('javascriptDisabled').style.display = 'none'; + <script language="javascript" type="text/javascript"> + //<![CDATA[ + // we use HTML to hide the action buttons and Javascript to show them + // to protect against click-jacking in an iframe whose javascript is disabled. + document.getElementById('responseButtonsDiv').style.display = 'block'; + document.getElementById('javascriptDisabled').style.display = 'none'; - // Frame busting code (to protect us from being hosted in an iframe). - // This protects us from click-jacking. - if (document.location !== window.top.location) { - window.top.location = document.location; - } - //]]> - </script> - - </asp:View> - <asp:View ID="authorizationGrantedView" runat="server"> - <p> - Authorization has been granted.</p> - <asp:MultiView runat="server" ID="verifierMultiView" ActiveViewIndex="0"> - <asp:View ID="verificationCodeView" runat="server"> - <p> - You must enter this verification code at the Consumer: - <asp:Label runat="server" ID="verificationCodeLabel" /> - </p> - </asp:View> - <asp:View ID="noCallbackView" runat="server"> - <p> - You may now close this window and return to the Consumer. - </p> - </asp:View> - </asp:MultiView> - </asp:View> - <asp:View ID="authorizationDeniedView" runat="server"> - <p> - Authorization has been denied. You're free to do whatever now. - </p> - </asp:View> - </asp:MultiView> + // Frame busting code (to protect us from being hosted in an iframe). + // This protects us from click-jacking. + if (document.location !== window.top.location) { + window.top.location = document.location; + } + //]]> + </script> </asp:Content> diff --git a/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx.cs b/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx.cs index 16e48f0..2a95b89 100644 --- a/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx.cs +++ b/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx.cs @@ -7,60 +7,61 @@ namespace WebFormsRelyingParty.Members { using System; using System.Collections.Generic; + using System.Globalization; using System.Linq; + using System.Net; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth; using DotNetOpenAuth.OAuth.Messages; + using DotNetOpenAuth.OAuth2.Messages; using RelyingPartyLogic; public partial class OAuthAuthorize : System.Web.UI.Page { + private EndUserAuthorizationRequest pendingRequest; + protected void Page_Load(object sender, EventArgs e) { - if (!IsPostBack) { - var pendingRequest = OAuthServiceProvider.PendingAuthorizationRequest; - if (pendingRequest == null) { - Response.Redirect("AccountInfo.aspx"); - } + // We'll mask that on postback it's a POST when looking up the authorization details so that the GET-only + // message can be picked up. + var requestInfo = this.IsPostBack + ? new HttpRequestInfo("GET", this.Request.Url, this.Request.RawUrl, new WebHeaderCollection(), null) + : null; + this.pendingRequest = OAuthServiceProvider.AuthorizationServer.ReadAuthorizationRequest(requestInfo); + if (this.pendingRequest == null) { + Response.Redirect("AccountInfo.aspx"); + } + if (!IsPostBack) { this.csrfCheck.Value = Code.SiteUtilities.SetCsrfCookie(); - this.consumerNameLabel.Text = HttpUtility.HtmlEncode(OAuthServiceProvider.PendingAuthorizationConsumer.Name); - this.OAuth10ConsumerWarning.Visible = pendingRequest.IsUnsafeRequest; + var requestingClient = Database.DataContext.Clients.First(c => c.ClientIdentifier == this.pendingRequest.ClientIdentifier); + this.consumerNameLabel.Text = HttpUtility.HtmlEncode(requestingClient.Name); + this.scopeLabel.Text = HttpUtility.HtmlEncode(this.pendingRequest.Scope); - this.serviceProviderDomainNameLabel.Text = HttpUtility.HtmlEncode(this.Request.Url.Host); - this.consumerDomainNameLabel3.Text = this.consumerDomainNameLabel2.Text = this.consumerDomainNameLabel1.Text = HttpUtility.HtmlEncode(OAuthServiceProvider.PendingAuthorizationConsumer.Name); + // Consider auto-approving if safe to do so. + if (((OAuthAuthorizationServer)OAuthServiceProvider.AuthorizationServer.AuthorizationServer).CanBeAutoApproved(this.pendingRequest)) { + OAuthServiceProvider.AuthorizationServer.ApproveAuthorizationRequest(this.pendingRequest, HttpContext.Current.User.Identity.Name); + } } else { Code.SiteUtilities.VerifyCsrfCookie(this.csrfCheck.Value); } } protected void yesButton_Click(object sender, EventArgs e) { - this.outerMultiView.SetActiveView(this.authorizationGrantedView); - - var consumer = OAuthServiceProvider.PendingAuthorizationConsumer; - var tokenManager = OAuthServiceProvider.ServiceProvider.TokenManager; - var pendingRequest = OAuthServiceProvider.PendingAuthorizationRequest; - ITokenContainingMessage requestTokenMessage = pendingRequest; - var requestToken = tokenManager.GetRequestToken(requestTokenMessage.Token); - - OAuthServiceProvider.AuthorizePendingRequestToken(); - - // The rest of this method only executes if we couldn't automatically - // redirect to the consumer. - if (pendingRequest.IsUnsafeRequest) { - this.verifierMultiView.SetActiveView(this.noCallbackView); - } else { - this.verifierMultiView.SetActiveView(this.verificationCodeView); - string verifier = ServiceProvider.CreateVerificationCode(consumer.VerificationCodeFormat, consumer.VerificationCodeLength); - this.verificationCodeLabel.Text = HttpUtility.HtmlEncode(verifier); - requestToken.VerificationCode = verifier; - tokenManager.UpdateToken(requestToken); - } + var requestingClient = Database.DataContext.Clients.First(c => c.ClientIdentifier == this.pendingRequest.ClientIdentifier); + Database.LoggedInUser.ClientAuthorizations.Add( + new ClientAuthorization { + Client = requestingClient, + Scope = this.pendingRequest.Scope, + User = Database.LoggedInUser, + CreatedOnUtc = DateTime.UtcNow.CutToSecond(), + }); + OAuthServiceProvider.AuthorizationServer.ApproveAuthorizationRequest(this.pendingRequest, HttpContext.Current.User.Identity.Name); } protected void noButton_Click(object sender, EventArgs e) { - this.outerMultiView.SetActiveView(this.authorizationDeniedView); - OAuthServiceProvider.PendingAuthorizationRequest = null; + OAuthServiceProvider.AuthorizationServer.RejectAuthorizationRequest(this.pendingRequest); } } } diff --git a/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx.designer.cs b/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx.designer.cs index 20d5ea9..d243c81 100644 --- a/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx.designer.cs +++ b/projecttemplates/WebFormsRelyingParty/Members/OAuthAuthorize.aspx.designer.cs @@ -1,10 +1,9 @@ //------------------------------------------------------------------------------ // <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. +// the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ @@ -14,31 +13,22 @@ namespace WebFormsRelyingParty.Members { public partial class OAuthAuthorize { /// <summary> - /// outerMultiView control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.MultiView outerMultiView; - - /// <summary> - /// getPermissionView control. + /// consumerNameLabel control. /// </summary> /// <remarks> /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// </remarks> - protected global::System.Web.UI.WebControls.View getPermissionView; + protected global::System.Web.UI.WebControls.Label consumerNameLabel; /// <summary> - /// consumerNameLabel control. + /// scopeLabel control. /// </summary> /// <remarks> /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// </remarks> - protected global::System.Web.UI.WebControls.Label consumerNameLabel; + protected global::System.Web.UI.WebControls.Label scopeLabel; /// <summary> /// yesButton control. @@ -66,104 +56,5 @@ namespace WebFormsRelyingParty.Members { /// To modify move field declaration from designer file to code-behind file. /// </remarks> protected global::System.Web.UI.WebControls.HiddenField csrfCheck; - - /// <summary> - /// OAuth10ConsumerWarning control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.Panel OAuth10ConsumerWarning; - - /// <summary> - /// serviceProviderDomainNameLabel control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.Label serviceProviderDomainNameLabel; - - /// <summary> - /// consumerDomainNameLabel1 control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.Label consumerDomainNameLabel1; - - /// <summary> - /// consumerDomainNameLabel2 control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.Label consumerDomainNameLabel2; - - /// <summary> - /// consumerDomainNameLabel3 control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.Label consumerDomainNameLabel3; - - /// <summary> - /// authorizationGrantedView control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.View authorizationGrantedView; - - /// <summary> - /// verifierMultiView control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.MultiView verifierMultiView; - - /// <summary> - /// verificationCodeView control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.View verificationCodeView; - - /// <summary> - /// verificationCodeLabel control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.Label verificationCodeLabel; - - /// <summary> - /// noCallbackView control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.View noCallbackView; - - /// <summary> - /// authorizationDeniedView control. - /// </summary> - /// <remarks> - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// </remarks> - protected global::System.Web.UI.WebControls.View authorizationDeniedView; } } diff --git a/projecttemplates/WebFormsRelyingParty/Members/Web.config b/projecttemplates/WebFormsRelyingParty/Members/Web.config index f95a16d..4ab44bc 100644 --- a/projecttemplates/WebFormsRelyingParty/Members/Web.config +++ b/projecttemplates/WebFormsRelyingParty/Members/Web.config @@ -20,7 +20,7 @@ <location path="AccountInfo.aspx"> <system.web> <authorization> - <deny roles="delegated" /> + <deny roles="oauth_client" /> </authorization> </system.web> </location> diff --git a/projecttemplates/WebFormsRelyingParty/OAuth.ashx b/projecttemplates/WebFormsRelyingParty/OAuth.ashx deleted file mode 100644 index 6176757..0000000 --- a/projecttemplates/WebFormsRelyingParty/OAuth.ashx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebHandler Language="C#" CodeBehind="OAuth.ashx.cs" Class="WebFormsRelyingParty.OAuth" %> diff --git a/projecttemplates/WebFormsRelyingParty/OAuth.ashx.cs b/projecttemplates/WebFormsRelyingParty/OAuth.ashx.cs deleted file mode 100644 index cb7c819..0000000 --- a/projecttemplates/WebFormsRelyingParty/OAuth.ashx.cs +++ /dev/null @@ -1,66 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuth.ashx.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace WebFormsRelyingParty { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Web; - using System.Web.SessionState; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OAuth; - using DotNetOpenAuth.OAuth.Messages; - using RelyingPartyLogic; - - /// <summary> - /// Responds to incoming OAuth Service Provider messages. - /// </summary> - public class OAuth : IHttpHandler, IRequiresSessionState { - /// <summary> - /// Initializes a new instance of the <see cref="OAuth"/> class. - /// </summary> - public OAuth() { - } - - /// <summary> - /// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"/> instance. - /// </summary> - /// <returns> - /// true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false. - /// </returns> - public bool IsReusable { - get { return true; } - } - - /// <summary> - /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface. - /// </summary> - /// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> - public void ProcessRequest(HttpContext context) { - var serviceProvider = OAuthServiceProvider.ServiceProvider; - var requestMessage = serviceProvider.ReadRequest(new HttpRequestInfo(context.Request)); - - UnauthorizedTokenRequest unauthorizedTokenRequestMessage; - AuthorizedTokenRequest authorizedTokenRequestMessage; - UserAuthorizationRequest userAuthorizationRequest; - if ((unauthorizedTokenRequestMessage = requestMessage as UnauthorizedTokenRequest) != null) { - var response = serviceProvider.PrepareUnauthorizedTokenMessage(unauthorizedTokenRequestMessage); - serviceProvider.Channel.Send(response); - } else if ((authorizedTokenRequestMessage = requestMessage as AuthorizedTokenRequest) != null) { - var response = serviceProvider.PrepareAccessTokenMessage(authorizedTokenRequestMessage); - serviceProvider.Channel.Send(response); - } else if ((userAuthorizationRequest = requestMessage as UserAuthorizationRequest) != null) { - // This is a browser opening to allow the user to authorize a request token, - // so redirect to the authorization page, which will automatically redirect - // to have the user log in if necessary. - OAuthServiceProvider.PendingAuthorizationRequest = userAuthorizationRequest; - HttpContext.Current.Response.Redirect("~/Members/OAuthAuthorize.aspx"); - } else { - throw new InvalidOperationException(); - } - } - } -} diff --git a/projecttemplates/WebFormsRelyingParty/OAuthTokenEndpoint.ashx b/projecttemplates/WebFormsRelyingParty/OAuthTokenEndpoint.ashx new file mode 100644 index 0000000..3d1cd86 --- /dev/null +++ b/projecttemplates/WebFormsRelyingParty/OAuthTokenEndpoint.ashx @@ -0,0 +1 @@ +<%@ WebHandler Language="C#" CodeBehind="OAuthTokenEndpoint.ashx.cs" Class="WebFormsRelyingParty.OAuthTokenEndpoint" %> diff --git a/projecttemplates/WebFormsRelyingParty/OAuthTokenEndpoint.ashx.cs b/projecttemplates/WebFormsRelyingParty/OAuthTokenEndpoint.ashx.cs new file mode 100644 index 0000000..ca9b399 --- /dev/null +++ b/projecttemplates/WebFormsRelyingParty/OAuthTokenEndpoint.ashx.cs @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthTokenEndpoint.ashx.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace WebFormsRelyingParty { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using System.Web.SessionState; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth2; + using RelyingPartyLogic; + + /// <summary> + /// An OAuth 2.0 token endpoint. + /// </summary> + public class OAuthTokenEndpoint : IHttpHandler, IRequiresSessionState { + /// <summary> + /// Initializes a new instance of the <see cref="OAuthTokenEndpoint"/> class. + /// </summary> + public OAuthTokenEndpoint() { + } + + /// <summary> + /// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"/> instance. + /// </summary> + /// <returns> + /// true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false. + /// </returns> + public bool IsReusable { + get { return true; } + } + + /// <summary> + /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface. + /// </summary> + /// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> + public void ProcessRequest(HttpContext context) { + var serviceProvider = OAuthServiceProvider.AuthorizationServer; + IDirectResponseProtocolMessage response; + if (serviceProvider.TryPrepareAccessTokenResponse(new HttpRequestInfo(context.Request), out response)) { + serviceProvider.Channel.Send(response); + } else { + throw new InvalidOperationException(); + } + } + } +} diff --git a/projecttemplates/WebFormsRelyingParty/WebFormsRelyingParty.csproj b/projecttemplates/WebFormsRelyingParty/WebFormsRelyingParty.csproj index 8faeef5..eb81910 100644 --- a/projecttemplates/WebFormsRelyingParty/WebFormsRelyingParty.csproj +++ b/projecttemplates/WebFormsRelyingParty/WebFormsRelyingParty.csproj @@ -153,8 +153,8 @@ <Compile Include="Members\Default.aspx.designer.cs"> <DependentUpon>Default.aspx</DependentUpon> </Compile> - <Compile Include="OAuth.ashx.cs"> - <DependentUpon>OAuth.ashx</DependentUpon> + <Compile Include="OAuthTokenEndpoint.ashx.cs"> + <DependentUpon>OAuthTokenEndpoint.ashx</DependentUpon> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Setup.aspx.cs"> @@ -235,7 +235,7 @@ <ItemGroup> <Content Include="images\verisign.gif" /> <Content Include="Members\OAuthAuthorize.aspx" /> - <Content Include="OAuth.ashx" /> + <Content Include="OAuthTokenEndpoint.ashx" /> <Content Include="PrivacyPolicy.aspx" /> </ItemGroup> <ItemGroup> diff --git a/samples/OAuthConsumerWpf/Authorize2.xaml.cs b/samples/OAuthConsumerWpf/Authorize2.xaml.cs index d407a51..8cf9f6f 100644 --- a/samples/OAuthConsumerWpf/Authorize2.xaml.cs +++ b/samples/OAuthConsumerWpf/Authorize2.xaml.cs @@ -22,14 +22,16 @@ public partial class Authorize2 : Window { private UserAgentClient client; - internal Authorize2(UserAgentClient client) { + internal Authorize2(UserAgentClient client, IAuthorizationState authorizationState) { Contract.Requires(client != null, "client"); + Contract.Requires(authorizationState != null, "authorizationState"); InitializeComponent(); this.client = client; - this.Authorization = new AuthorizationState(); - this.webBrowser.Navigate(this.client.RequestUserAuthorization(this.Authorization)); + this.Authorization = authorizationState; + Uri authorizationUrl = this.client.RequestUserAuthorization(this.Authorization); + this.webBrowser.Navigate(authorizationUrl.AbsoluteUri); // use AbsoluteUri to workaround bug in WebBrowser that calls Uri.ToString instead of Uri.AbsoluteUri leading to escaping errors. } public IAuthorizationState Authorization { get; set; } diff --git a/samples/OAuthConsumerWpf/MainWindow.xaml b/samples/OAuthConsumerWpf/MainWindow.xaml index b4a6959..825de07 100644 --- a/samples/OAuthConsumerWpf/MainWindow.xaml +++ b/samples/OAuthConsumerWpf/MainWindow.xaml @@ -144,6 +144,7 @@ <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> + <RowDefinition Height="auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> @@ -151,41 +152,43 @@ <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> - <Label Grid.Row="1">Token Endpoint URL</Label> - <TextBox Grid.Row="1" Grid.Column="1" x:Name="wrapTokenUrlBox" Text="https://graph.facebook.com/oauth/access_token" /> - <Label Grid.Row="1" Grid.Column="2">POST</Label> - <Label Grid.Row="2">User Authorization URL</Label> - <TextBox Grid.Row="2" Grid.Column="1" x:Name="wrapAuthorizationUrlBox" Text="https://graph.facebook.com/oauth/authorize?display=popup" /> - <Label Grid.Row="2" Grid.Column="2">GET</Label> - <Label Grid.Row="0">Grant Type</Label> - <ComboBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" x:Name="flowBox" SelectedIndex="0"> + <Label Grid.Row="1" TabIndex="202">Token Endpoint URL</Label> + <TextBox Grid.Row="1" Grid.Column="1" x:Name="wrapTokenUrlBox" Text="http://localhost:18916/OAuthTokenEndpoint.ashx" TabIndex="203" /> + <Label Grid.Row="1" Grid.Column="2" TabIndex="204">POST</Label> + <Label Grid.Row="2" TabIndex="205">User Authorization URL</Label> + <TextBox Grid.Row="2" Grid.Column="1" x:Name="wrapAuthorizationUrlBox" Text="http://localhost:18916/Account/Authorize" TabIndex="206" /> + <Label Grid.Row="2" Grid.Column="2" TabIndex="207">GET</Label> + <Label Grid.Row="0" TabIndex="200">Grant Type</Label> + <ComboBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" x:Name="flowBox" SelectedIndex="0" TabIndex="201"> <ComboBox.Items> <ComboBoxItem>Authorization Code</ComboBoxItem> <ComboBoxItem>Resource Owner Basic Credentials</ComboBoxItem> <ComboBoxItem>Access Code (direct)</ComboBoxItem> </ComboBox.Items> </ComboBox> - <Label Grid.Row="3">Resource URL</Label> - <TextBox Grid.Row="3" Grid.Column="1" x:Name="wrapResourceUrlBox" Text="https://graph.facebook.com/me" /> - <ComboBox Grid.Row="3" Grid.Column="2" x:Name="wrapResourceHttpMethodList" SelectedIndex="0"> + <Label Grid.Row="3" TabIndex="207">Resource URL</Label> + <TextBox Grid.Row="3" Grid.Column="1" x:Name="wrapResourceUrlBox" Text="http://localhost:18916/" TabIndex="208" /> + <ComboBox Grid.Row="3" Grid.Column="2" x:Name="wrapResourceHttpMethodList" SelectedIndex="0" TabIndex="209"> <ComboBox.Items> <ComboBoxItem>GET w/ header</ComboBoxItem> <ComboBoxItem>GET w/ querystring</ComboBoxItem> <ComboBoxItem>POST</ComboBoxItem> </ComboBox.Items> </ComboBox> - <Label Grid.Row="4">Client Identifier</Label> - <TextBox Grid.Row="4" Grid.Column="1" x:Name="wrapClientIdentifierBox" Grid.ColumnSpan="2" Text="367207604173" /> - <Label Grid.Row="5">Client Secret</Label> - <TextBox Grid.Row="5" Grid.Column="1" x:Name="wrapClientSecretBox" Grid.ColumnSpan="2" Text="1df77e64055c4d7d3583cefdf2bc62d7"/> - <Label Grid.Row="6">OAuth 2.0 version</Label> - <ComboBox Grid.Row="6" Grid.Column="1" SelectedIndex="0" x:Name="wrapVersion"> + <Label Grid.Row="4" TabIndex="210">Client Identifier</Label> + <TextBox Grid.Row="4" Grid.Column="1" x:Name="wrapClientIdentifierBox" Grid.ColumnSpan="2" Text="a" TabIndex="211" /> + <Label Grid.Row="5" TabIndex="212">Client Secret</Label> + <TextBox Grid.Row="5" Grid.Column="1" x:Name="wrapClientSecretBox" Grid.ColumnSpan="2" Text="b" TabIndex="213" /> + <Label Grid.Row="6" TabIndex="214">Scope</Label> + <TextBox Grid.Row="6" Grid.Column="1" x:Name="wrapScopeBox" TabIndex="215" Text="some scope" /> + <Label Grid.Row="7" TabIndex="216">OAuth 2.0 version</Label> + <ComboBox Grid.Row="7" Grid.Column="1" SelectedIndex="0" x:Name="wrapVersion" TabIndex="217"> <ComboBox.Items> <ComboBoxItem>2.0 DRAFT 9</ComboBoxItem> </ComboBox.Items> </ComboBox> - <Button Grid.Row="7" Grid.Column="1" x:Name="wrapBeginButton" Click="wrapBeginButton_Click">Begin</Button> - <TextBox Grid.Column="0" Grid.Row="8" Grid.ColumnSpan="3" Name="wrapResultsBox" IsReadOnly="True" /> + <Button Grid.Row="8" Grid.Column="1" x:Name="wrapBeginButton" Click="wrapBeginButton_Click" TabIndex="218">Begin</Button> + <TextBox Grid.Column="0" Grid.Row="9" Grid.ColumnSpan="3" Name="wrapResultsBox" IsReadOnly="True" TabIndex="219"/> </Grid> </TabItem> </TabControl> diff --git a/samples/OAuthConsumerWpf/MainWindow.xaml.cs b/samples/OAuthConsumerWpf/MainWindow.xaml.cs index d698ce0..46a5f06 100644 --- a/samples/OAuthConsumerWpf/MainWindow.xaml.cs +++ b/samples/OAuthConsumerWpf/MainWindow.xaml.cs @@ -29,7 +29,11 @@ using DotNetOpenAuth.OAuth; using DotNetOpenAuth.OAuth.ChannelElements; using DotNetOpenAuth.Samples.OAuthConsumerWpf.WcfSampleService; + + using OAuth2; + using OAuth2 = DotNetOpenAuth.OAuth2; + using ProtocolVersion = DotNetOpenAuth.OAuth.ProtocolVersion; /// <summary> /// Interaction logic for MainWindow.xaml @@ -213,8 +217,10 @@ ////var client = new DotNetOpenAuth.OAuth2.WebAppClient(authServer); ////client.PrepareRequestUserAuthorization(); var client = new OAuth2.UserAgentClient(authServer, wrapClientIdentifierBox.Text); + client.ClientSecret = wrapClientSecretBox.Text; - var authorizePopup = new Authorize2(client); + var authorization = new AuthorizationState { Scope = wrapScopeBox.Text }; + var authorizePopup = new Authorize2(client, authorization); authorizePopup.Owner = this; bool? result = authorizePopup.ShowDialog(); if (result.HasValue && result.Value) { @@ -237,6 +243,8 @@ } } catch (DotNetOpenAuth.Messaging.ProtocolException ex) { MessageBox.Show(this, ex.Message); + } catch (WebException ex) { + MessageBox.Show(this, ex.Message); } } } diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs index ffbacda..b229bb8 100644 --- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs +++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs @@ -209,6 +209,15 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Cuts off precision beyond a second on a DateTime value. + /// </summary> + /// <param name="value">The value.</param> + /// <returns>A DateTime with a 0 millisecond component.</returns> + public static DateTime CutToSecond(this DateTime value) { + return value - TimeSpan.FromMilliseconds(value.Millisecond); + } + + /// <summary> /// Strips any and all URI query parameters that serve as parts of a message. /// </summary> /// <param name="uri">The URI that may contain query parameters to remove.</param> diff --git a/src/DotNetOpenAuth/OAuth2/ChannelElements/AccessRequestBindingElement.cs b/src/DotNetOpenAuth/OAuth2/ChannelElements/AccessRequestBindingElement.cs index b71b66d..eaa444d 100644 --- a/src/DotNetOpenAuth/OAuth2/ChannelElements/AccessRequestBindingElement.cs +++ b/src/DotNetOpenAuth/OAuth2/ChannelElements/AccessRequestBindingElement.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { using System; using System.Collections.Generic; + using System.Globalization; using System.Linq; using System.Text; using DotNetOpenAuth.Messaging; @@ -52,12 +53,18 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. /// </remarks> public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { - var tokenRequest = message as ITokenCarryingRequest; - if (tokenRequest != null) { - ErrorUtilities.VerifyInternal(tokenRequest.CodeOrTokenType == CodeOrTokenType.AuthorizationCode, "Only verification codes are expected here."); - var tokenBag = (AuthorizationCode)tokenRequest.AuthorizationDescription; - var formatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer); - tokenRequest.CodeOrToken = formatter.Serialize(tokenBag); + var response = message as ITokenCarryingRequest; + if (response != null) { + switch (response.CodeOrTokenType) + { + case CodeOrTokenType.AuthorizationCode: + var codeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer); + var code = (AuthorizationCode)response.AuthorizationDescription; + response.CodeOrToken = codeFormatter.Serialize(code); + break; + default: + throw ErrorUtilities.ThrowInternal(string.Format(CultureInfo.CurrentCulture, "Unexpected outgoing code or token type: {0}", response.CodeOrTokenType)); + } return MessageProtections.None; } diff --git a/src/DotNetOpenAuth/OAuth2/ChannelElements/ITokenCarryingRequest.cs b/src/DotNetOpenAuth/OAuth2/ChannelElements/ITokenCarryingRequest.cs index 0f4d84f..4c8d33f 100644 --- a/src/DotNetOpenAuth/OAuth2/ChannelElements/ITokenCarryingRequest.cs +++ b/src/DotNetOpenAuth/OAuth2/ChannelElements/ITokenCarryingRequest.cs @@ -5,6 +5,8 @@ //----------------------------------------------------------------------- namespace DotNetOpenAuth.OAuth2.ChannelElements { + using System.Security.Cryptography; + using Messaging; /// <summary> diff --git a/src/DotNetOpenAuth/OAuth2/ClientBase.cs b/src/DotNetOpenAuth/OAuth2/ClientBase.cs index b2b63aa..46b6af4 100644 --- a/src/DotNetOpenAuth/OAuth2/ClientBase.cs +++ b/src/DotNetOpenAuth/OAuth2/ClientBase.cs @@ -184,6 +184,28 @@ namespace DotNetOpenAuth.OAuth2 { authorizationState.SaveChanges(); } + internal void UpdateAuthorizationWithResponse(IAuthorizationState authorizationState, EndUserAuthorizationSuccessAuthCodeResponse authorizationSuccess) { + Contract.Requires<ArgumentNullException>(authorizationState != null, "authorizationState"); + Contract.Requires<ArgumentNullException>(authorizationSuccess != null, "authorizationSuccess"); + + var accessTokenRequest = new AccessTokenAuthorizationCodeRequest(this.AuthorizationServer) { + ClientIdentifier = this.ClientIdentifier, + ClientSecret = this.ClientSecret, + Callback = authorizationState.Callback, + AuthorizationCode = authorizationSuccess.AuthorizationCode, + }; + IProtocolMessage accessTokenResponse = this.Channel.Request(accessTokenRequest); + var accessTokenSuccess = accessTokenResponse as AccessTokenSuccessResponse; + var failedAccessTokenResponse = accessTokenResponse as AccessTokenFailedResponse; + if (accessTokenSuccess != null) { + this.UpdateAuthorizationWithResponse(authorizationState, accessTokenSuccess); + } else { + authorizationState.Delete(); + string error = failedAccessTokenResponse != null ? failedAccessTokenResponse.Error : "(unknown)"; + ErrorUtilities.ThrowProtocol(OAuthWrapStrings.CannotObtainAccessTokenWithReason, error); + } + } + /// <summary> /// Calculates the fraction of life remaining in an access token. /// </summary> diff --git a/src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs b/src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs index c99fbc3..83b5191 100644 --- a/src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs +++ b/src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs @@ -20,7 +20,7 @@ namespace DotNetOpenAuth.OAuth2 { [ContractClass(typeof(IAuthorizationServerContract))] public interface IAuthorizationServer { /// <summary> - /// Gets the secret used to symmetrically encrypt and sign verification codes and refresh tokens. + /// Gets the secret used to symmetrically encrypt and sign authorization codes and refresh tokens. /// </summary> /// <remarks> /// This secret should be kept strictly confidential in the authorization server(s) @@ -39,9 +39,9 @@ namespace DotNetOpenAuth.OAuth2 { RSAParameters AccessTokenSigningPrivateKey { get; } /// <summary> - /// Gets the verification code nonce store to use to ensure that verification codes can only be used once. + /// Gets the authorization code nonce store to use to ensure that authorization codes can only be used once. /// </summary> - /// <value>The verification code nonce store.</value> + /// <value>The authorization code nonce store.</value> INonceStore VerificationCodeNonceStore { get; } /// <summary> @@ -89,7 +89,7 @@ namespace DotNetOpenAuth.OAuth2 { } /// <summary> - /// Gets the secret used to symmetrically encrypt and sign verification codes and refresh tokens. + /// Gets the secret used to symmetrically encrypt and sign authorization codes and refresh tokens. /// </summary> /// <value></value> /// <remarks> @@ -117,9 +117,9 @@ namespace DotNetOpenAuth.OAuth2 { } /// <summary> - /// Gets the verification code nonce store to use to ensure that verification codes can only be used once. + /// Gets the authorization code nonce store to use to ensure that authorization codes can only be used once. /// </summary> - /// <value>The verification code nonce store.</value> + /// <value>The authorization code nonce store.</value> INonceStore IAuthorizationServer.VerificationCodeNonceStore { get { Contract.Ensures(Contract.Result<INonceStore>() != null); diff --git a/src/DotNetOpenAuth/OAuth2/IConsumerDescription.cs b/src/DotNetOpenAuth/OAuth2/IConsumerDescription.cs index f0fc20a..4e2bc4f 100644 --- a/src/DotNetOpenAuth/OAuth2/IConsumerDescription.cs +++ b/src/DotNetOpenAuth/OAuth2/IConsumerDescription.cs @@ -6,19 +6,18 @@ namespace DotNetOpenAuth.OAuth2 { using System; - using System.Security.Cryptography.X509Certificates; /// <summary> - /// A description of a consumer from a Service Provider's point of view. + /// A description of a client from an Authorization Server's point of view. /// </summary> public interface IConsumerDescription { /// <summary> - /// Gets the consumer secret. + /// Gets the client secret. /// </summary> string Secret { get; } /// <summary> - /// Gets the callback URI that this consumer has pre-registered with the service provider, if any. + /// Gets the callback URI that this client has pre-registered with the service provider, if any. /// </summary> /// <value>A URI that user authorization responses should be directed to; or <c>null</c> if no preregistered callback was arranged.</value> Uri Callback { get; } diff --git a/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs b/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs index 6cfd715..b125c67 100644 --- a/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs +++ b/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationFailedResponse.cs @@ -13,7 +13,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { using System.Text; using DotNetOpenAuth.Messaging; - internal class EndUserAuthorizationFailedResponse : MessageBase, IMessageWithClientState { + public class EndUserAuthorizationFailedResponse : MessageBase, IMessageWithClientState { /// <summary> /// Initializes a new instance of the <see cref="EndUserAuthorizationSuccessResponseBase"/> class. /// </summary> diff --git a/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationRequest.cs b/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationRequest.cs index 2faa33b..d870aba 100644 --- a/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationRequest.cs +++ b/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationRequest.cs @@ -84,27 +84,5 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// <value>The scope of the access request expressed as a list of space-delimited strings. The value of the scope parameter is defined by the authorization server. If the value contains multiple space-delimited strings, their order does not matter, and each string adds an additional access range to the requested scope.</value> [MessagePart(Protocol.scope, IsRequired = false, AllowEmpty = true)] public string Scope { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether the authorization server is - /// allowed to interact with the user before responding to the client's request. - /// </summary> - /// <remarks> - /// This is internal because it doesn't appear in recent drafts of the spec. - /// </remarks> - internal bool IsUserInteractionAllowed { - get { return !this.Immediate.HasValue || !this.Immediate.Value; } - set { this.Immediate = value ? (bool?)null : true; } - } - - /// <summary> - /// Gets or sets a value indicating whether the authorization server is - /// required to redirect the browser back to the client immediately. - /// </summary> - /// <remarks> - /// OPTIONAL. The parameter value must be set to true or false. If set to true, the authorization server MUST NOT prompt the end-user to authenticate or approve access. Instead, the authorization server attempts to establish the end-user's identity via other means (e.g. browser cookies) and checks if the end-user has previously approved an identical access request by the same client and if that access grant is still active. If the authorization server does not support an immediate check or if it is unable to establish the end-user's identity or approval status, it MUST deny the request without prompting the end-user. Defaults to false if omitted. - /// </remarks> - [MessagePart(Protocol.immediate, IsRequired = false, AllowEmpty = false)] - internal bool? Immediate { get; set; } } } diff --git a/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs b/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs index d66c2d8..a02c050 100644 --- a/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs +++ b/src/DotNetOpenAuth/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs @@ -7,6 +7,8 @@ namespace DotNetOpenAuth.OAuth2.Messages { using System; using System.Diagnostics.Contracts; + using System.Security.Cryptography; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth2.ChannelElements; @@ -15,7 +17,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// to indicate that user authorization was granted, and to return the user /// to the Client where they started their experience. /// </summary> - internal abstract class EndUserAuthorizationSuccessResponseBase : MessageBase, IMessageWithClientState { + public abstract class EndUserAuthorizationSuccessResponseBase : MessageBase, IMessageWithClientState { /// <summary> /// Initializes a new instance of the <see cref="EndUserAuthorizationSuccessResponseBase"/> class. /// </summary> diff --git a/src/DotNetOpenAuth/OAuth2/Messages/UnauthorizedResponse.cs b/src/DotNetOpenAuth/OAuth2/Messages/UnauthorizedResponse.cs index 90ef662..0f12a8c 100644 --- a/src/DotNetOpenAuth/OAuth2/Messages/UnauthorizedResponse.cs +++ b/src/DotNetOpenAuth/OAuth2/Messages/UnauthorizedResponse.cs @@ -19,6 +19,17 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// <summary> /// Initializes a new instance of the <see cref="UnauthorizedResponse"/> class. /// </summary> + /// <param name="exception">The exception.</param> + /// <param name="version">The protocol version.</param> + internal UnauthorizedResponse(ProtocolException exception, Version version = null) + : base(version ?? Protocol.Default.Version) { + Contract.Requires<ArgumentNullException>(exception != null, "exception"); + this.ErrorMessage = exception.Message; + } + + /// <summary> + /// Initializes a new instance of the <see cref="UnauthorizedResponse"/> class. + /// </summary> /// <param name="request">The request.</param> internal UnauthorizedResponse(IDirectedProtocolMessage request) : base(request) { diff --git a/src/DotNetOpenAuth/OAuth2/OAuthUtilities.cs b/src/DotNetOpenAuth/OAuth2/OAuthUtilities.cs index ccc7e8d..609e0a6 100644 --- a/src/DotNetOpenAuth/OAuth2/OAuthUtilities.cs +++ b/src/DotNetOpenAuth/OAuth2/OAuthUtilities.cs @@ -17,7 +17,63 @@ namespace DotNetOpenAuth.OAuth2 { /// <summary> /// Some common utility methods for OAuth 2.0. /// </summary> - internal static class OAuthUtilities { + public static class OAuthUtilities { + /// <summary> + /// The delimiter between scope elements. + /// </summary> + private static char[] scopeDelimiter = new char[] { ' ' }; + + /// <summary> + /// The characters that may appear in an access token that is included in an HTTP Authorization header. + /// </summary> + /// <remarks> + /// This is defined in OAuth 2.0 DRAFT 10, section 5.1.1. (http://tools.ietf.org/id/draft-ietf-oauth-v2-10.html#authz-header) + /// </remarks> + private static string accessTokenAuthorizationHeaderAllowedCharacters = MessagingUtilities.UppercaseLetters + + MessagingUtilities.LowercaseLetters + + MessagingUtilities.Digits + + @"!#$%&'()*+-./:<=>?@[]^_`{|}~\,;"; + + /// <summary> + /// Determines whether one given scope is a subset of another scope. + /// </summary> + /// <param name="requestedScope">The requested scope, which may be a subset of <paramref name="grantedScope"/>.</param> + /// <param name="grantedScope">The granted scope, the suspected superset.</param> + /// <returns> + /// <c>true</c> if all the elements that appear in <paramref name="requestedScope"/> also appear in <paramref name="grantedScope"/>; + /// <c>false</c> otherwise. + /// </returns> + public static bool IsScopeSubset(string requestedScope, string grantedScope) { + if (string.IsNullOrEmpty(requestedScope)) { + return true; + } + + if (string.IsNullOrEmpty(grantedScope)) { + return false; + } + + var requestedScopes = new HashSet<string>(requestedScope.Split(scopeDelimiter, StringSplitOptions.RemoveEmptyEntries)); + var grantedScopes = new HashSet<string>(grantedScope.Split(scopeDelimiter, StringSplitOptions.RemoveEmptyEntries)); + return requestedScopes.IsSubsetOf(grantedScopes); + } + + /// <summary> + /// Identifies individual scope elements + /// </summary> + /// <param name="scope">The scope.</param> + /// <param name="scopeComparer">The scope comparer, allowing scopes to be case sensitive or insensitive. + /// Usually <see cref="StringComparer.Ordinal"/> or <see cref="StringComparer.OrdinalIgnoreCase"/>.</param> + /// <returns></returns> + public static HashSet<string> BreakUpScopes(string scope, StringComparer scopeComparer) { + Contract.Requires<ArgumentNullException>(scopeComparer != null, "scopeComparer"); + + if (string.IsNullOrEmpty(scope)) { + return new HashSet<string>(); + } + + return new HashSet<string>(scope.Split(scopeDelimiter, StringSplitOptions.RemoveEmptyEntries), scopeComparer); + } + /// <summary> /// Authorizes an HTTP request using an OAuth 2.0 access token in an HTTP Authorization header. /// </summary> @@ -26,10 +82,12 @@ namespace DotNetOpenAuth.OAuth2 { internal static void AuthorizeWithOAuthWrap(this HttpWebRequest request, string accessToken) { Contract.Requires<ArgumentNullException>(request != null); Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(accessToken)); + ErrorUtilities.VerifyProtocol(accessToken.All(ch => accessTokenAuthorizationHeaderAllowedCharacters.IndexOf(ch) >= 0), "The access token contains characters that must not appear in the HTTP Authorization header."); + request.Headers[HttpRequestHeader.Authorization] = string.Format( CultureInfo.InvariantCulture, Protocol.HttpAuthorizationHeaderFormat, - Uri.EscapeDataString(accessToken)); + accessToken); } /// <summary> diff --git a/src/DotNetOpenAuth/OAuth2/Protocol.cs b/src/DotNetOpenAuth/OAuth2/Protocol.cs index c33f79c..a8a67bb 100644 --- a/src/DotNetOpenAuth/OAuth2/Protocol.cs +++ b/src/DotNetOpenAuth/OAuth2/Protocol.cs @@ -24,14 +24,14 @@ namespace DotNetOpenAuth.OAuth2 { /// </summary> internal class Protocol { /// <summary> - /// The HTTP authorization scheme "Token"; + /// The HTTP authorization scheme "OAuth"; /// </summary> - internal const string HttpAuthorizationScheme = "Token"; + internal const string HttpAuthorizationScheme = "OAuth"; /// <summary> /// The format of the HTTP Authorization header value that authorizes OAuth 2.0 requests. /// </summary> - internal const string HttpAuthorizationHeaderFormat = "Token token=\"{0}\""; + internal const string HttpAuthorizationHeaderFormat = "OAuth token=\"{0}\""; /// <summary> /// The "type" string. diff --git a/src/DotNetOpenAuth/OAuth2/ResourceServer.cs b/src/DotNetOpenAuth/OAuth2/ResourceServer.cs index 534f741..f013a5e 100644 --- a/src/DotNetOpenAuth/OAuth2/ResourceServer.cs +++ b/src/DotNetOpenAuth/OAuth2/ResourceServer.cs @@ -10,6 +10,8 @@ namespace DotNetOpenAuth.OAuth2 { using System.Diagnostics.Contracts; using System.Linq; using System.Net; + using System.Security.Principal; + using System.ServiceModel.Channels; using System.Text; using System.Text.RegularExpressions; using System.Web; @@ -87,15 +89,55 @@ namespace DotNetOpenAuth.OAuth2 { throw ErrorUtilities.ThrowProtocol("Bad access token"); } else { - throw ErrorUtilities.ThrowProtocol("Missing access token."); + var response = new UnauthorizedResponse(new ProtocolException("Missing access token")); + + username = null; + scope = null; + return this.Channel.PrepareResponse(response); } } catch (ProtocolException ex) { - var response = new UnauthorizedResponse(request, ex); + var response = request != null ? new UnauthorizedResponse(request, ex) : new UnauthorizedResponse(ex); username = null; scope = null; return this.Channel.PrepareResponse(response); } } + + /// <summary> + /// Discovers what access the client should have considering the access token in the current request. + /// </summary> + /// <param name="httpRequestInfo">The HTTP request info.</param> + /// <param name="principal">The principal that contains the user and roles that the access token is authorized for.</param> + /// <returns> + /// An error to return to the client if access is not authorized; <c>null</c> if access is granted. + /// </returns> + public virtual OutgoingWebResponse VerifyAccess(HttpRequestInfo httpRequestInfo, out IPrincipal principal) { + string username, scope; + var result = this.VerifyAccess(httpRequestInfo, out username, out scope); + if (result == null) { + principal = new OAuth.ChannelElements.OAuthPrincipal(username, scope != null ? scope.Split(' ') : new string[0]); + } else { + principal = null; + } + + return result; + } + + /// <summary> + /// Discovers what access the client should have considering the access token in the current request. + /// </summary> + /// <param name="request">HTTP details from an incoming WCF message.</param> + /// <param name="requestUri">The URI of the WCF service endpoint.</param> + /// <param name="principal">The principal that contains the user and roles that the access token is authorized for.</param> + /// <returns> + /// An error to return to the client if access is not authorized; <c>null</c> if access is granted. + /// </returns> + public virtual OutgoingWebResponse VerifyAccess(HttpRequestMessageProperty request, Uri requestUri, out IPrincipal principal) { + Contract.Requires<ArgumentNullException>(request != null, "request"); + Contract.Requires<ArgumentNullException>(requestUri != null, "requestUri"); + + return this.VerifyAccess(new HttpRequestInfo(request, requestUri), out principal); + } } } diff --git a/src/DotNetOpenAuth/OAuth2/StandardAccessTokenAnalyzer.cs b/src/DotNetOpenAuth/OAuth2/StandardAccessTokenAnalyzer.cs index f292af5..5e0ea94 100644 --- a/src/DotNetOpenAuth/OAuth2/StandardAccessTokenAnalyzer.cs +++ b/src/DotNetOpenAuth/OAuth2/StandardAccessTokenAnalyzer.cs @@ -50,7 +50,7 @@ namespace DotNetOpenAuth.OAuth2 { /// This method also responsible to throw a <see cref="ProtocolException"/> or return /// <c>false</c> when the access token is expired, invalid, or from an untrusted authorization server. /// </remarks> - public bool TryValidateAccessToken(IDirectedProtocolMessage message, string accessToken, out string user, out string scope) { + public virtual bool TryValidateAccessToken(IDirectedProtocolMessage message, string accessToken, out string user, out string scope) { var accessTokenFormatter = AccessToken.CreateFormatter(this.AuthorizationServerPublicSigningKey, this.ResourceServerPrivateEncryptionKey); var token = accessTokenFormatter.Deserialize(message, accessToken); user = token.User; diff --git a/src/DotNetOpenAuth/OAuth2/UserAgentClient.cs b/src/DotNetOpenAuth/OAuth2/UserAgentClient.cs index 1a30af0..db73cd9 100644 --- a/src/DotNetOpenAuth/OAuth2/UserAgentClient.cs +++ b/src/DotNetOpenAuth/OAuth2/UserAgentClient.cs @@ -36,6 +36,12 @@ namespace DotNetOpenAuth.OAuth2 { Contract.Requires<ArgumentNullException>(authorizationEndpoint != null, "authorizationEndpoint"); } + // TODO: remove this. user agent clients can't keep secrets. + public new string ClientSecret { + get { return base.ClientSecret; } + set { base.ClientSecret = value; } + } + /// <summary> /// Generates a URL that the user's browser can be directed to in order to authorize /// this client to access protected data at some resource server. @@ -65,7 +71,8 @@ namespace DotNetOpenAuth.OAuth2 { ClientIdentifier = this.ClientIdentifier, Scope = authorization.Scope, Callback = authorization.Callback, - ResponseType = EndUserAuthorizationResponseType.AccessToken, + // TODO: bring back ResponseType = AccessToken, since user agents can't keep secrets, thus can't process authorization codes. + //ResponseType = EndUserAuthorizationResponseType.AccessToken, }; return this.Channel.PrepareResponse(request).GetDirectUriRequest(this.Channel); @@ -90,10 +97,13 @@ namespace DotNetOpenAuth.OAuth2 { return null; } - EndUserAuthorizationSuccessAccessTokenResponse success; + EndUserAuthorizationSuccessAccessTokenResponse accessTokenSuccess; + EndUserAuthorizationSuccessAuthCodeResponse authCodeSuccess; EndUserAuthorizationFailedResponse failure; - if ((success = response as EndUserAuthorizationSuccessAccessTokenResponse) != null) { - this.UpdateAuthorizationWithResponse(authorizationState, success); + if ((accessTokenSuccess = response as EndUserAuthorizationSuccessAccessTokenResponse) != null) { + this.UpdateAuthorizationWithResponse(authorizationState, accessTokenSuccess); + } else if ((authCodeSuccess = response as EndUserAuthorizationSuccessAuthCodeResponse) != null) { + this.UpdateAuthorizationWithResponse(authorizationState, authCodeSuccess); } else if ((failure = response as EndUserAuthorizationFailedResponse) != null) { authorizationState.Delete(); return null; diff --git a/src/DotNetOpenAuth/OAuth2/WebServerAuthorizationServer.cs b/src/DotNetOpenAuth/OAuth2/WebServerAuthorizationServer.cs index 67ea1d6..d8e0190 100644 --- a/src/DotNetOpenAuth/OAuth2/WebServerAuthorizationServer.cs +++ b/src/DotNetOpenAuth/OAuth2/WebServerAuthorizationServer.cs @@ -45,11 +45,16 @@ namespace DotNetOpenAuth.OAuth2 { return message; } - public void ApproveAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, string username, Uri callback = null) { + public void ApproveAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, string username, string scope = null, Uri callback = null) { Contract.Requires<ArgumentNullException>(authorizationRequest != null, "authorizationRequest"); - var response = this.PrepareApproveAuthorizationRequest(authorizationRequest, callback); - response.AuthorizingUsername = username; + var response = this.PrepareApproveAuthorizationRequest(authorizationRequest, username, callback); + + // Customize the approved scope if the authorization server has decided to do so. + if (scope != null) { + response.Scope = scope; + } + this.Channel.Send(response); } @@ -71,7 +76,8 @@ namespace DotNetOpenAuth.OAuth2 { if (request != null) { // This convenience method only encrypts access tokens assuming that this auth server // doubles as the resource server. - response = this.PrepareAccessTokenResponse(request, this.AuthorizationServer.AccessTokenSigningPrivateKey); + RSAParameters resourceServerPublicKey = this.AuthorizationServer.AccessTokenSigningPrivateKey; + response = this.PrepareAccessTokenResponse(request, resourceServerPublicKey); return true; } @@ -89,7 +95,7 @@ namespace DotNetOpenAuth.OAuth2 { return request; } - internal EndUserAuthorizationFailedResponse PrepareRejectAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, Uri callback = null) { + public EndUserAuthorizationFailedResponse PrepareRejectAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, Uri callback = null) { Contract.Requires<ArgumentNullException>(authorizationRequest != null, "authorizationRequest"); Contract.Ensures(Contract.Result<EndUserAuthorizationFailedResponse>() != null); @@ -101,8 +107,9 @@ namespace DotNetOpenAuth.OAuth2 { return response; } - internal EndUserAuthorizationSuccessResponseBase PrepareApproveAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, Uri callback = null) { + public EndUserAuthorizationSuccessResponseBase PrepareApproveAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, string username, Uri callback = null) { Contract.Requires<ArgumentNullException>(authorizationRequest != null, "authorizationRequest"); + Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(username)); Contract.Ensures(Contract.Result<EndUserAuthorizationSuccessResponseBase>() != null); if (callback == null) { @@ -111,8 +118,7 @@ namespace DotNetOpenAuth.OAuth2 { var client = this.AuthorizationServer.GetClientOrThrow(authorizationRequest.ClientIdentifier); EndUserAuthorizationSuccessResponseBase response; - switch (authorizationRequest.ResponseType) - { + switch (authorizationRequest.ResponseType) { case EndUserAuthorizationResponseType.AccessToken: response = new EndUserAuthorizationSuccessAccessTokenResponse(callback, authorizationRequest); break; @@ -123,7 +129,8 @@ namespace DotNetOpenAuth.OAuth2 { default: throw ErrorUtilities.ThrowInternal("Unexpected response type."); } - + + response.AuthorizingUsername = username; return response; } diff --git a/src/DotNetOpenAuth/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth/OAuth2/WebServerClient.cs index d7116df..9b95677 100644 --- a/src/DotNetOpenAuth/OAuth2/WebServerClient.cs +++ b/src/DotNetOpenAuth/OAuth2/WebServerClient.cs @@ -120,22 +120,7 @@ namespace DotNetOpenAuth.OAuth2 { var failure = response as EndUserAuthorizationFailedResponse; ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany); if (success != null) { - var accessTokenRequest = new AccessTokenAuthorizationCodeRequest(this.AuthorizationServer) { - ClientIdentifier = this.ClientIdentifier, - ClientSecret = this.ClientSecret, - Callback = authorizationState.Callback, - AuthorizationCode = success.AuthorizationCode, - }; - IProtocolMessage accessTokenResponse = this.Channel.Request(accessTokenRequest); - var accessTokenSuccess = accessTokenResponse as AccessTokenSuccessResponse; - var failedAccessTokenResponse = accessTokenResponse as AccessTokenFailedResponse; - if (accessTokenSuccess != null) { - this.UpdateAuthorizationWithResponse(authorizationState, accessTokenSuccess); - } else { - authorizationState.Delete(); - string error = failedAccessTokenResponse != null ? failedAccessTokenResponse.Error : "(unknown)"; - ErrorUtilities.ThrowProtocol(OAuthWrapStrings.CannotObtainAccessTokenWithReason, error); - } + UpdateAuthorizationWithResponse(authorizationState, success); } else { // failure Logger.OAuth.Info("User refused to grant the requested authorization at the Authorization Server."); authorizationState.Delete(); |