diff options
Diffstat (limited to 'samples/OAuthServiceProvider/App_Code')
6 files changed, 140 insertions, 8 deletions
diff --git a/samples/OAuthServiceProvider/App_Code/DataApi.cs b/samples/OAuthServiceProvider/App_Code/DataApi.cs index a765159..d5adb10 100644 --- a/samples/OAuthServiceProvider/App_Code/DataApi.cs +++ b/samples/OAuthServiceProvider/App_Code/DataApi.cs @@ -1,20 +1,31 @@ using System.Linq; using System.ServiceModel; +/// <summary> +/// The WCF service API. +/// </summary> +/// <remarks> +/// Note how there is no code here that is bound to OAuth or any other +/// credential/authorization scheme. That's all part of the channel/binding elsewhere. +/// And the reference to OperationContext.Current.ServiceSecurityContext.PrimaryIdentity +/// is the user being impersonated by the WCF client. +/// In the OAuth case, it is the user who authorized the OAuth access token that was used +/// to gain access to the service. +/// </remarks> public class DataApi : IDataApi { - private static OAuthToken AccessToken { - get { return OperationContext.Current.IncomingMessageProperties["OAuthAccessToken"] as OAuthToken; } + private User User { + get { return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.GetUser(); } } public int? GetAge() { - return AccessToken.User.Age; + return User.Age; } public string GetName() { - return AccessToken.User.FullName; + return User.FullName; } public string[] GetFavoriteSites() { - return AccessToken.User.FavoriteSites.Select(site => site.SiteUrl).ToArray(); + return User.FavoriteSites.Select(site => site.SiteUrl).ToArray(); } } diff --git a/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs b/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs index 8ca4539..710508d 100644 --- a/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs +++ b/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs @@ -26,7 +26,15 @@ public class DatabaseTokenManager : IServiceProviderTokenManager { public IServiceProviderRequestToken GetRequestToken(string token) { try { - return Global.DataContext.OAuthTokens.First(t => t.Token == token); + return Global.DataContext.OAuthTokens.First(t => t.Token == token && t.State != TokenAuthorizationState.AccessToken); + } catch (InvalidOperationException ex) { + throw new KeyNotFoundException("Unrecognized token", ex); + } + } + + public IServiceProviderAccessToken GetAccessToken(string token) { + try { + return Global.DataContext.OAuthTokens.First(t => t.Token == token && t.State == TokenAuthorizationState.AccessToken); } catch (InvalidOperationException ex) { throw new KeyNotFoundException("Unrecognized token", ex); } diff --git a/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs b/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs index fce1ad4..8589932 100644 --- a/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs +++ b/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs @@ -1,7 +1,11 @@ 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; @@ -24,10 +28,28 @@ public class OAuthAuthorizationManager : ServiceAuthorizationManager { if (auth != null) { var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken); + var principal = sp.CreatePrincipal(auth); + var policy = new OAuthPrincipalAuthorizationPolicy(principal); + var policies = new List<IAuthorizationPolicy> { + policy, + }; + + var securityContext = new ServiceSecurityContext(policies.AsReadOnly()); + if (operationContext.IncomingMessageProperties.Security != null) { + operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext; + } else { + operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty { + ServiceSecurityContext = securityContext, + }; + } + + securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> { + principal.Identity, + }; + // Only allow this method call if the access token scope permits it. string[] scopes = accessToken.Scope.Split('|'); if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { - operationContext.IncomingMessageProperties["OAuthAccessToken"] = accessToken; return true; } } diff --git a/samples/OAuthServiceProvider/App_Code/OAuthPrincipalAuthorizationPolicy.cs b/samples/OAuthServiceProvider/App_Code/OAuthPrincipalAuthorizationPolicy.cs new file mode 100644 index 0000000..5bd6b05 --- /dev/null +++ b/samples/OAuthServiceProvider/App_Code/OAuthPrincipalAuthorizationPolicy.cs @@ -0,0 +1,45 @@ +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 +} diff --git a/samples/OAuthServiceProvider/App_Code/OAuthToken.cs b/samples/OAuthServiceProvider/App_Code/OAuthToken.cs index 2f26799..ea18b2b 100644 --- a/samples/OAuthServiceProvider/App_Code/OAuthToken.cs +++ b/samples/OAuthServiceProvider/App_Code/OAuthToken.cs @@ -10,7 +10,7 @@ using System.Linq; using System.Web; using DotNetOpenAuth.OAuth.ChannelElements; -public partial class OAuthToken : IServiceProviderRequestToken { +public partial class OAuthToken : IServiceProviderRequestToken, IServiceProviderAccessToken { #region IServiceProviderRequestToken Members string IServiceProviderRequestToken.Token { @@ -41,4 +41,24 @@ public partial class OAuthToken : IServiceProviderRequestToken { } #endregion + + #region IServiceProviderAccessToken Members + + string IServiceProviderAccessToken.Token { + get { return this.Token; } + } + + DateTime? IServiceProviderAccessToken.ExpirationDate { + get { return null; } + } + + string IServiceProviderAccessToken.Username { + get { return this.User.OpenIDClaimedIdentifier; } + } + + string[] IServiceProviderAccessToken.Roles { + get { return this.Scope.Split('|'); } + } + + #endregion } diff --git a/samples/OAuthServiceProvider/App_Code/Utilities.cs b/samples/OAuthServiceProvider/App_Code/Utilities.cs new file mode 100644 index 0000000..2c25fe8 --- /dev/null +++ b/samples/OAuthServiceProvider/App_Code/Utilities.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Web; + +/// <summary> +/// Extension methods and other helpful utility methods. +/// </summary> +public static class Utilities { + /// <summary> + /// Gets the database entity representing the user identified by a given <see cref="IIdentity"/> instance. + /// </summary> + /// <param name="identity">The identity of the user.</param> + /// <returns> + /// The database object for that user; or <c>null</c> if the user could not + /// be found or if <paramref name="identity"/> is <c>null</c> or represents an anonymous identity. + /// </returns> + public static User GetUser(this IIdentity identity) { + if (identity == null || !identity.IsAuthenticated) { + return null; + } + + return Global.DataContext.Users.SingleOrDefault(user => user.OpenIDClaimedIdentifier == identity.Name); + } +} |