diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-11-11 02:00:13 -0800 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-11-11 02:00:13 -0800 |
commit | 4789a04cd525189364f5e9062d8ef27882ce7ea0 (patch) | |
tree | 07deabd29b6ef72a9bd631f3b875d565495e2b46 | |
parent | 175bd8ea3e95649b4be51dce17ae175db3400c3c (diff) | |
download | DotNetOpenAuth-4789a04cd525189364f5e9062d8ef27882ce7ea0.zip DotNetOpenAuth-4789a04cd525189364f5e9062d8ef27882ce7ea0.tar.gz DotNetOpenAuth-4789a04cd525189364f5e9062d8ef27882ce7ea0.tar.bz2 |
Added OAuth authorization modules so that incoming requests signed with OAuth get proper delegation rights.
5 files changed, 204 insertions, 0 deletions
diff --git a/projecttemplates/WebFormsRelyingParty/Code/OAuthAuthenticationModule.cs b/projecttemplates/WebFormsRelyingParty/Code/OAuthAuthenticationModule.cs new file mode 100644 index 0000000..57d442f --- /dev/null +++ b/projecttemplates/WebFormsRelyingParty/Code/OAuthAuthenticationModule.cs @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthAuthenticationModule.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace WebFormsRelyingParty.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Principal; + using System.Web; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + public class OAuthAuthenticationModule : IHttpModule { + private HttpApplication application; + + #region IHttpModule Members + + /// <summary> + /// Initializes a module and prepares it to handle requests. + /// </summary> + /// <param name="context">An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application</param> + public void Init(HttpApplication context) { + this.application = context; + this.application.AuthenticateRequest += new EventHandler(context_AuthenticateRequest); + } + + /// <summary> + /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>. + /// </summary> + public void Dispose() { + } + + /// <summary> + /// Handles the AuthenticateRequest event of the HttpApplication. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> + private void context_AuthenticateRequest(object sender, EventArgs e) { + // Don't read OAuth messages directed at the OAuth controller or else we'll fail nonce checks. + if (this.IsOAuthControllerRequest()) { + return; + } + + IDirectedProtocolMessage incomingMessage = OAuthServiceProvider.ServiceProvider.ReadRequest(new HttpRequestInfo(this.application.Context.Request)); + var authorization = incomingMessage as AccessProtectedResourceRequest; + if (authorization != null) { + this.application.Context.User = OAuthServiceProvider.ServiceProvider.CreatePrincipal(authorization); + } + } + + #endregion + + private bool IsOAuthControllerRequest() { + return string.Equals(this.application.Context.Request.Url.AbsolutePath, "/OAuth.ashx", StringComparison.OrdinalIgnoreCase); + } + } +} diff --git a/projecttemplates/WebFormsRelyingParty/Code/OAuthAuthorizationManager.cs b/projecttemplates/WebFormsRelyingParty/Code/OAuthAuthorizationManager.cs new file mode 100644 index 0000000..480e1b9 --- /dev/null +++ b/projecttemplates/WebFormsRelyingParty/Code/OAuthAuthorizationManager.cs @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthAuthorizationManager.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace WebFormsRelyingParty.Code { + using System; + using System.Collections.Generic; + using System.IdentityModel.Policy; + using System.Linq; + using System.Security.Principal; + using System.ServiceModel; + using System.ServiceModel.Channels; + using System.ServiceModel.Security; + using DotNetOpenAuth; + using DotNetOpenAuth.OAuth; + + /// <summary> + /// A WCF extension to authenticate incoming messages using OAuth. + /// </summary> + public class OAuthAuthorizationManager : ServiceAuthorizationManager { + public OAuthAuthorizationManager() { + } + + protected override bool CheckAccessCore(OperationContext operationContext) { + if (!base.CheckAccessCore(operationContext)) { + return false; + } + + HttpRequestMessageProperty httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; + Uri requestUri = operationContext.RequestContext.RequestMessage.Properties["OriginalHttpRequestUri"] as Uri; + ServiceProvider sp = OAuthServiceProvider.ServiceProvider; + var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri); + if (auth != null) { + var accessToken = Global.DataContext.IssuedToken.OfType<IssuedAccessToken>().First(token => token.Token == auth.AccessToken); + + var principal = sp.CreatePrincipal(auth); + var policy = new OAuthPrincipalAuthorizationPolicy(principal); + var policies = new List<IAuthorizationPolicy> { + policy, + }; + + var securityContext = new ServiceSecurityContext(policies.AsReadOnly()); + if (operationContext.IncomingMessageProperties.Security != null) { + operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext; + } else { + operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty { + ServiceSecurityContext = securityContext, + }; + } + + securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> { + principal.Identity, + }; + + // Only allow this method call if the access token scope permits it. + string[] scopes = accessToken.Scope.Split('|'); + if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { + return true; + } + } + + return false; + } + } +}
\ No newline at end of file diff --git a/projecttemplates/WebFormsRelyingParty/Code/OAuthPrincipalAuthorizationPolicy.cs b/projecttemplates/WebFormsRelyingParty/Code/OAuthPrincipalAuthorizationPolicy.cs new file mode 100644 index 0000000..b2c9a2d --- /dev/null +++ b/projecttemplates/WebFormsRelyingParty/Code/OAuthPrincipalAuthorizationPolicy.cs @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthPrincipalAuthorizationPolicy.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace WebFormsRelyingParty.Code { + using System; + using System.Collections.Generic; + using System.IdentityModel.Claims; + using System.IdentityModel.Policy; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public class OAuthPrincipalAuthorizationPolicy : IAuthorizationPolicy { + private readonly Guid uniqueId = Guid.NewGuid(); + private readonly OAuthPrincipal principal; + + /// <summary> + /// Initializes a new instance of the <see cref="OAuthPrincipalAuthorizationPolicy"/> class. + /// </summary> + /// <param name="principal">The principal.</param> + public OAuthPrincipalAuthorizationPolicy(OAuthPrincipal principal) { + this.principal = principal; + } + + #region IAuthorizationComponent Members + + /// <summary> + /// Gets a unique ID for this instance. + /// </summary> + public string Id { + get { return this.uniqueId.ToString(); } + } + + #endregion + + #region IAuthorizationPolicy Members + + public ClaimSet Issuer { + get { return ClaimSet.System; } + } + + public bool Evaluate(EvaluationContext evaluationContext, ref object state) { + evaluationContext.AddClaimSet(this, new DefaultClaimSet(Claim.CreateNameClaim(this.principal.Identity.Name))); + evaluationContext.Properties["Principal"] = this.principal; + return true; + } + + #endregion + } +}
\ No newline at end of file diff --git a/projecttemplates/WebFormsRelyingParty/Web.config b/projecttemplates/WebFormsRelyingParty/Web.config index 3c7aaae..8773a5d 100644 --- a/projecttemplates/WebFormsRelyingParty/Web.config +++ b/projecttemplates/WebFormsRelyingParty/Web.config @@ -122,6 +122,7 @@ </httpHandlers> <httpModules> <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> + <add name="OAuthAuthenticationModule" type="WebFormsRelyingParty.Code.OAuthAuthenticationModule"/> </httpModules> <roleManager enabled="true" defaultProvider="Database"> <providers> @@ -146,6 +147,7 @@ <modules> <remove name="ScriptModule" /> <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> + <add name="OAuthAuthenticationModule" type="WebFormsRelyingParty.Code.OAuthAuthenticationModule"/> </modules> <handlers> <remove name="WebServiceHandlerFactory-Integrated" /> @@ -169,6 +171,23 @@ </dependentAssembly> </assemblyBinding> </runtime> + <system.serviceModel> + <behaviors> + <serviceBehaviors> + <behavior name="DataApiBehavior"> + <serviceMetadata httpGetEnabled="true"/> + <serviceDebug includeExceptionDetailInFaults="true"/> + <serviceAuthorization + serviceAuthorizationManagerType="OAuthAuthorizationManager, __code" + principalPermissionMode="Custom" /> + </behavior> + </serviceBehaviors> + </behaviors> + <services> + <!--<service behaviorConfiguration="DataApiBehavior" name="DataApi"> + </service>--> + </services> + </system.serviceModel> <location path="default.aspx"> <system.web> <authorization> diff --git a/projecttemplates/WebFormsRelyingParty/WebFormsRelyingParty.csproj b/projecttemplates/WebFormsRelyingParty/WebFormsRelyingParty.csproj index 0129010..4f6cdc6 100644 --- a/projecttemplates/WebFormsRelyingParty/WebFormsRelyingParty.csproj +++ b/projecttemplates/WebFormsRelyingParty/WebFormsRelyingParty.csproj @@ -87,7 +87,10 @@ <Content Include="Web.config" /> </ItemGroup> <ItemGroup> + <Compile Include="Code\OAuthAuthenticationModule.cs" /> + <Compile Include="Code\OAuthAuthorizationManager.cs" /> <Compile Include="Code\OAuthConsumerTokenManager.cs" /> + <Compile Include="Code\OAuthPrincipalAuthorizationPolicy.cs" /> <Compile Include="Code\OAuthServiceProvider.cs" /> <Compile Include="Code\OAuthServiceProviderTokenManager.cs" /> <Compile Include="Code\OAuthTokenManager.cs" /> |