diff options
Diffstat (limited to 'samples')
49 files changed, 717 insertions, 599 deletions
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj b/samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj index 570d91f..976a325 100644 --- a/samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj +++ b/samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj @@ -59,11 +59,7 @@ <Compile Include="CustomExtensions\AcmeRequest.cs" /> <Compile Include="CustomExtensions\AcmeResponse.cs" /> <Compile Include="GoogleConsumer.cs" /> - <Compile Include="OAuthIdentity.cs" /> - <Compile Include="OAuthPrincipal.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="Provider\AnonymousIdentifierProviderBase.cs" /> - <Compile Include="Provider\AuthenticationRequestExtensions.cs" /> <Compile Include="TwitterConsumer.cs" /> <Compile Include="Util.cs" /> </ItemGroup> diff --git a/samples/DotNetOpenAuth.ApplicationBlock/OAuthIdentity.cs b/samples/DotNetOpenAuth.ApplicationBlock/OAuthIdentity.cs deleted file mode 100644 index ea9ec0b..0000000 --- a/samples/DotNetOpenAuth.ApplicationBlock/OAuthIdentity.cs +++ /dev/null @@ -1,63 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuthIdentity.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.ApplicationBlock { - using System; - using System.Runtime.InteropServices; - using System.Security.Principal; - - /// <summary> - /// Represents an OAuth consumer that is impersonating a known user on the system. - /// </summary> - [Serializable] - [ComVisible(true)] - internal class OAuthIdentity : IIdentity { - /// <summary> - /// Initializes a new instance of the <see cref="OAuthIdentity"/> class. - /// </summary> - /// <param name="username">The username.</param> - internal OAuthIdentity(string username) { - if (String.IsNullOrEmpty(username)) { - throw new ArgumentNullException("username"); - } - - this.Name = username; - } - - #region IIdentity Members - - /// <summary> - /// Gets the type of authentication used. - /// </summary> - /// <value>The constant "OAuth"</value> - /// <returns> - /// The type of authentication used to identify the user. - /// </returns> - public string AuthenticationType { - get { return "OAuth"; } - } - - /// <summary> - /// Gets a value indicating whether the user has been authenticated. - /// </summary> - /// <value>The value <c>true</c></value> - /// <returns>true if the user was authenticated; otherwise, false. - /// </returns> - public bool IsAuthenticated { - get { return true; } - } - - /// <summary> - /// Gets the name of the user who authorized the OAuth token the consumer is using for authorization. - /// </summary> - /// <returns> - /// The name of the user on whose behalf the code is running. - /// </returns> - public string Name { get; private set; } - - #endregion - } -} diff --git a/samples/DotNetOpenAuth.ApplicationBlock/OAuthPrincipal.cs b/samples/DotNetOpenAuth.ApplicationBlock/OAuthPrincipal.cs deleted file mode 100644 index 88f3b83..0000000 --- a/samples/DotNetOpenAuth.ApplicationBlock/OAuthPrincipal.cs +++ /dev/null @@ -1,67 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuthPrincipal.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.ApplicationBlock { - using System; - using System.Linq; - using System.Runtime.InteropServices; - using System.Security.Principal; - - /// <summary> - /// Represents an OAuth consumer that is impersonating a known user on the system. - /// </summary> - [Serializable] - [ComVisible(true)] - internal class OAuthPrincipal : IPrincipal { - /// <summary> - /// The roles this user belongs to. - /// </summary> - private string[] roles; - - /// <summary> - /// Initializes a new instance of the <see cref="OAuthPrincipal"/> class. - /// </summary> - /// <param name="identity">The identity.</param> - /// <param name="roles">The roles this user belongs to.</param> - internal OAuthPrincipal(OAuthIdentity identity, string[] roles) { - this.Identity = identity; - this.roles = roles; - } - - /// <summary> - /// Initializes a new instance of the <see cref="OAuthPrincipal"/> class. - /// </summary> - /// <param name="username">The username.</param> - /// <param name="roles">The roles this user belongs to.</param> - internal OAuthPrincipal(string username, string[] roles) - : this(new OAuthIdentity(username), roles) { - } - - #region IPrincipal Members - - /// <summary> - /// Gets the identity of the current principal. - /// </summary> - /// <value></value> - /// <returns> - /// The <see cref="T:System.Security.Principal.IIdentity"/> object associated with the current principal. - /// </returns> - public IIdentity Identity { get; private set; } - - /// <summary> - /// Determines whether the current principal belongs to the specified role. - /// </summary> - /// <param name="role">The name of the role for which to check membership.</param> - /// <returns> - /// true if the current principal is a member of the specified role; otherwise, false. - /// </returns> - public bool IsInRole(string role) { - return this.roles.Contains(role); - } - - #endregion - } -} diff --git a/samples/DotNetOpenAuth.ApplicationBlock/Provider/AnonymousIdentifierProviderBase.cs b/samples/DotNetOpenAuth.ApplicationBlock/Provider/AnonymousIdentifierProviderBase.cs deleted file mode 100644 index 1df7267..0000000 --- a/samples/DotNetOpenAuth.ApplicationBlock/Provider/AnonymousIdentifierProviderBase.cs +++ /dev/null @@ -1,122 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="AnonymousIdentifierProviderBase.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.ApplicationBlock.Provider { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Security.Cryptography; - using System.Text; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OpenId; - - public abstract class AnonymousIdentifierProviderBase { - private int newSaltLength = 20; - - /// <summary> - /// Initializes a new instance of the <see cref="AnonymousIdentifierProviderBase"/> class. - /// </summary> - /// <param name="baseIdentifier">The base URI on which to append the anonymous part.</param> - public AnonymousIdentifierProviderBase(Uri baseIdentifier) { - if (baseIdentifier == null) { - throw new ArgumentNullException("baseIdentifier"); - } - - this.Hasher = HashAlgorithm.Create("SHA256"); - this.Encoder = Encoding.UTF8; - this.BaseIdentifier = baseIdentifier; - } - - public Uri BaseIdentifier { get; private set; } - - protected HashAlgorithm Hasher { get; private set; } - - protected Encoding Encoder { get; private set; } - - protected int NewSaltLength { - get { - return this.newSaltLength; - } - - set { - if (value <= 0) { - throw new ArgumentOutOfRangeException("value"); - } - - this.newSaltLength = value; - } - } - - #region IAnonymousIdentifierProvider Members - - public Uri GetAnonymousIdentifier(Identifier localIdentifier, Realm relyingPartyRealm) { - byte[] salt = this.GetHashSaltForLocalIdentifier(localIdentifier); - string valueToHash = localIdentifier + "#" + (relyingPartyRealm ?? string.Empty); - byte[] valueAsBytes = this.Encoder.GetBytes(valueToHash); - byte[] bytesToHash = new byte[valueAsBytes.Length + salt.Length]; - valueAsBytes.CopyTo(bytesToHash, 0); - salt.CopyTo(bytesToHash, valueAsBytes.Length); - byte[] hash = this.Hasher.ComputeHash(bytesToHash); - string base64Hash = Convert.ToBase64String(hash); - Uri anonymousIdentifier = this.AppendIdentifiers(this.BaseIdentifier, base64Hash); - return anonymousIdentifier; - } - - #endregion - - protected virtual byte[] GetNewSalt() { - // We COULD use a crypto random function, but for a salt it seems overkill. - return Util.GetNonCryptoRandomData(this.NewSaltLength); - } - - protected Uri AppendIdentifiers(Uri baseIdentifier, string uriHash) { - if (baseIdentifier == null) { - throw new ArgumentNullException("baseIdentifier"); - } - if (String.IsNullOrEmpty(uriHash)) { - throw new ArgumentNullException("uriHash"); - } - - if (string.IsNullOrEmpty(baseIdentifier.Query)) { - // The uriHash will appear on the path itself. - string pathEncoded = Uri.EscapeUriString(uriHash.Replace('/', '_')); - return new Uri(baseIdentifier, pathEncoded); - } else { - // The uriHash will appear on the query string. - string dataEncoded = Uri.EscapeDataString(uriHash); - return new Uri(baseIdentifier + dataEncoded); - } - } - - /// <summary> - /// Gets the salt to use for generating an anonymous identifier for a given OP local identifier. - /// </summary> - /// <param name="localIdentifier">The OP local identifier.</param> - /// <returns>The salt to use in the hash.</returns> - /// <remarks> - /// It is important that this method always return the same value for a given - /// <paramref name="localIdentifier"/>. - /// New salts can be generated for local identifiers without previously assigned salt - /// values by calling <see cref="GetNewSalt"/> or by a custom method. - /// </remarks> - protected abstract byte[] GetHashSaltForLocalIdentifier(Identifier localIdentifier); - -#if CONTRACTS_FULL - /// <summary> - /// Verifies conditions that should be true for any valid state of this object. - /// </summary> - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by code contracts.")] - [ContractInvariantMethod] - protected void ObjectInvariant() { - Contract.Invariant(this.Hasher != null); - Contract.Invariant(this.Encoder != null); - Contract.Invariant(this.BaseIdentifier != null); - Contract.Invariant(this.NewHashLength > 0); - } -#endif - } -} diff --git a/samples/DotNetOpenAuth.ApplicationBlock/Provider/AuthenticationRequestExtensions.cs b/samples/DotNetOpenAuth.ApplicationBlock/Provider/AuthenticationRequestExtensions.cs deleted file mode 100644 index a737d30..0000000 --- a/samples/DotNetOpenAuth.ApplicationBlock/Provider/AuthenticationRequestExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace DotNetOpenAuth.ApplicationBlock.Provider { - using System; - using DotNetOpenAuth.OpenId; - using DotNetOpenAuth.OpenId.Provider; - - public static class AuthenticationRequestExtensions { - /// <summary> - /// Removes all personally identifiable information from the positive assertion. - /// </summary> - /// <param name="request">The incoming authentication request.</param> - /// <param name="localIdentifier">The OP local identifier, before the anonymous hash is applied to it.</param> - /// <param name="anonymousIdentifierProvider">The anonymous identifier provider.</param> - /// <param name="pairwiseUnique">if set to <c>true</c> the anonymous identifier will be unique to the requesting relying party's realm.</param> - /// <remarks> - /// The openid.claimed_id and openid.identity values are hashed. - /// </remarks> - public static void ScrubPersonallyIdentifiableInformation(this IAuthenticationRequest request, Identifier localIdentifier, AnonymousIdentifierProviderBase anonymousIdentifierProvider, bool pairwiseUnique) { - if (request == null) { - throw new ArgumentNullException("request"); - } - if (!request.IsDirectedIdentity) { - throw new InvalidOperationException("This operation is supported only under identifier select (directed identity) scenarios."); - } - if (anonymousIdentifierProvider == null) { - throw new ArgumentNullException("anonymousIdentifierProvider"); - } - if (localIdentifier == null) { - throw new ArgumentNullException("localIdentifier"); - } - - // When generating the anonymous identifiers, the openid.identity and openid.claimed_id - // will always end up with matching values. - var anonymousIdentifier = anonymousIdentifierProvider.GetAnonymousIdentifier(localIdentifier, pairwiseUnique ? request.Realm : null); - request.ClaimedIdentifier = anonymousIdentifier; - request.LocalIdentifier = anonymousIdentifier; - } - } -} diff --git a/samples/DotNetOpenAuth.ApplicationBlock/Util.cs b/samples/DotNetOpenAuth.ApplicationBlock/Util.cs index 8a188ac..ea7da97 100644 --- a/samples/DotNetOpenAuth.ApplicationBlock/Util.cs +++ b/samples/DotNetOpenAuth.ApplicationBlock/Util.cs @@ -5,8 +5,6 @@ using DotNetOpenAuth.Messaging; internal static class Util { - internal static readonly Random NonCryptoRandomDataGenerator = new Random(); - /// <summary> /// Enumerates through the individual set bits in a flag enum. /// </summary> @@ -30,17 +28,6 @@ } /// <summary> - /// Gets a buffer of random data (not cryptographically strong). - /// </summary> - /// <param name="length">The length of the sequence to generate.</param> - /// <returns>The generated values, which may contain zeros.</returns> - internal static byte[] GetNonCryptoRandomData(int length) { - byte[] buffer = new byte[length]; - NonCryptoRandomDataGenerator.NextBytes(buffer); - return buffer; - } - - /// <summary> /// Copies the contents of one stream to another. /// </summary> /// <param name="copyFrom">The stream to copy from, at the position where copying should begin.</param> diff --git a/samples/OAuthServiceProvider/App_Code/DataApi.cs b/samples/OAuthServiceProvider/App_Code/DataApi.cs index a765159..00876f6 100644 --- a/samples/OAuthServiceProvider/App_Code/DataApi.cs +++ b/samples/OAuthServiceProvider/App_Code/DataApi.cs @@ -1,20 +1,26 @@ 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 Global.LoggedInUser 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; } - } - public int? GetAge() { - return AccessToken.User.Age; + return Global.LoggedInUser.Age; } public string GetName() { - return AccessToken.User.FullName; + return Global.LoggedInUser.FullName; } public string[] GetFavoriteSites() { - return AccessToken.User.FavoriteSites.Select(site => site.SiteUrl).ToArray(); + return Global.LoggedInUser.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..1ec2cb5 100644 --- a/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs +++ b/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Generic; +using System.IdentityModel.Policy; using System.Linq; using System.ServiceModel; using System.ServiceModel.Channels; +using System.ServiceModel.Security; using DotNetOpenAuth; using DotNetOpenAuth.OAuth; @@ -24,10 +27,22 @@ public class OAuthAuthorizationManager : ServiceAuthorizationManager { if (auth != null) { var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken); + var policy = new OAuthPrincipalAuthorizationPolicy(sp.CreatePrincipal(auth)); + 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, + }; + } + // 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 ec9b31e..fc1d6c5 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/Web.config b/samples/OAuthServiceProvider/Web.config index 894ad38..d039daa 100644 --- a/samples/OAuthServiceProvider/Web.config +++ b/samples/OAuthServiceProvider/Web.config @@ -143,7 +143,9 @@ <behavior name="DataApiBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> - <serviceAuthorization serviceAuthorizationManagerType="OAuthAuthorizationManager, __code"/> + <serviceAuthorization + serviceAuthorizationManagerType="OAuthAuthorizationManager, __code" + principalPermissionMode="Custom" /> </behavior> </serviceBehaviors> </behaviors> diff --git a/samples/OpenIdOfflineProvider/CheckIdWindow.xaml.cs b/samples/OpenIdOfflineProvider/CheckIdWindow.xaml.cs index 597f72f..5b4dd24 100644 --- a/samples/OpenIdOfflineProvider/CheckIdWindow.xaml.cs +++ b/samples/OpenIdOfflineProvider/CheckIdWindow.xaml.cs @@ -40,7 +40,7 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { this.immediateModeLabel.Visibility = request.Immediate ? Visibility.Visible : Visibility.Collapsed; this.setupModeLabel.Visibility = request.Immediate ? Visibility.Collapsed : Visibility.Visible; - bool isRPDiscoverable = request.IsReturnUrlDiscoverable(provider.Provider.Channel.WebRequestHandler); + bool isRPDiscoverable = request.IsReturnUrlDiscoverable(provider.Provider) == RelyingPartyDiscoveryResult.Success; this.discoverableYesLabel.Visibility = isRPDiscoverable ? Visibility.Visible : Visibility.Collapsed; this.discoverableNoLabel.Visibility = isRPDiscoverable ? Visibility.Collapsed : Visibility.Visible; diff --git a/samples/OpenIdProviderMvc/Code/AnonymousIdentifierProvider.cs b/samples/OpenIdProviderMvc/Code/AnonymousIdentifierProvider.cs index 2b9e01c..6dc210d 100644 --- a/samples/OpenIdProviderMvc/Code/AnonymousIdentifierProvider.cs +++ b/samples/OpenIdProviderMvc/Code/AnonymousIdentifierProvider.cs @@ -1,15 +1,29 @@ namespace OpenIdProviderMvc.Code { using System; using System.Web.Security; - using DotNetOpenAuth.ApplicationBlock.Provider; using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.Provider; using OpenIdProviderMvc.Models; - internal class AnonymousIdentifierProvider : AnonymousIdentifierProviderBase { + internal class AnonymousIdentifierProvider : PrivatePersonalIdentifierProviderBase { + /// <summary> + /// Initializes a new instance of the <see cref="AnonymousIdentifierProvider"/> class. + /// </summary> internal AnonymousIdentifierProvider() : base(Util.GetAppPathRootedUri("anon?id=")) { } + /// <summary> + /// Gets the salt to use for generating an anonymous identifier for a given OP local identifier. + /// </summary> + /// <param name="localIdentifier">The OP local identifier.</param> + /// <returns>The salt to use in the hash.</returns> + /// <remarks> + /// It is important that this method always return the same value for a given + /// <paramref name="localIdentifier"/>. + /// New salts can be generated for local identifiers without previously assigned salt + /// values by calling <see cref="CreateSalt"/> or by a custom method. + /// </remarks> protected override byte[] GetHashSaltForLocalIdentifier(Identifier localIdentifier) { // This is just a sample with no database... a real web app MUST return // a reasonable salt here and have that salt be persistent for each user. @@ -17,7 +31,12 @@ string username = User.GetUserFromClaimedIdentifier(new Uri(localIdentifier)); string salt = membership.GetSalt(username); return Convert.FromBase64String(salt); - ////return AnonymousIdentifierProviderBase.GetNewSalt(5); + + // If users were encountered without a salt, one could be generated like this, + // and would also need to be saved to the user's account. + //// var newSalt = AnonymousIdentifierProviderBase.GetNewSalt(5); + //// user.Salt = newSalt; + //// return newSalt; } } } diff --git a/samples/OpenIdProviderMvc/Controllers/HomeController.cs b/samples/OpenIdProviderMvc/Controllers/HomeController.cs index 346e838..5ba08b3 100644 --- a/samples/OpenIdProviderMvc/Controllers/HomeController.cs +++ b/samples/OpenIdProviderMvc/Controllers/HomeController.cs @@ -23,9 +23,5 @@ public ActionResult Xrds() { return View(); } - - public ActionResult PpidXrds() { - return View(); - } } } diff --git a/samples/OpenIdProviderMvc/Controllers/OpenIdController.cs b/samples/OpenIdProviderMvc/Controllers/OpenIdController.cs index e353268..bd0fdbf 100644 --- a/samples/OpenIdProviderMvc/Controllers/OpenIdController.cs +++ b/samples/OpenIdProviderMvc/Controllers/OpenIdController.cs @@ -5,9 +5,10 @@ namespace OpenIdProviderMvc.Controllers { using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; - using DotNetOpenAuth.ApplicationBlock.Provider; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.Behaviors; + using DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy; using DotNetOpenAuth.OpenId.Provider; using OpenIdProviderMvc.Code; @@ -20,67 +21,18 @@ namespace OpenIdProviderMvc.Controllers { } [ValidateInput(false)] - public ActionResult PpidProvider() { - return this.DoProvider(true); - } - - [ValidateInput(false)] public ActionResult Provider() { - return this.DoProvider(false); - } - - [Authorize] - public ActionResult SendAssertion(bool pseudonymous) { - IAuthenticationRequest authReq = PendingAuthenticationRequest; - PendingAuthenticationRequest = null; - if (authReq == null) { - throw new InvalidOperationException(); - } - - Identifier localIdentifier = Models.User.GetClaimedIdentifierForUser(User.Identity.Name); - - if (pseudonymous) { - if (!authReq.IsDirectedIdentity) { - throw new InvalidOperationException("Directed identity is the only supported scenario for anonymous identifiers."); - } - - var anonProvider = new AnonymousIdentifierProvider(); - authReq.ScrubPersonallyIdentifiableInformation(localIdentifier, anonProvider, true); - authReq.IsAuthenticated = true; - } else { - if (authReq.IsDirectedIdentity) { - authReq.LocalIdentifier = localIdentifier; - authReq.ClaimedIdentifier = localIdentifier; - authReq.IsAuthenticated = true; - } else { - if (authReq.LocalIdentifier == localIdentifier) { - authReq.IsAuthenticated = true; - if (!authReq.IsDelegatedIdentifier) { - authReq.ClaimedIdentifier = authReq.LocalIdentifier; - } - } else { - authReq.IsAuthenticated = false; - } - } - - // TODO: Respond to AX/sreg extension requests here. - // We don't want to add these extension responses for anonymous identifiers - // because they could leak information about the user's identity. - } - - return OpenIdProvider.PrepareResponse(authReq).AsActionResult(); - } - - private ActionResult DoProvider(bool pseudonymous) { IRequest request = OpenIdProvider.GetRequest(); if (request != null) { var authRequest = request as IAuthenticationRequest; if (authRequest != null) { PendingAuthenticationRequest = authRequest; - if (User.Identity.IsAuthenticated && (authRequest.IsDirectedIdentity || Models.User.GetClaimedIdentifierForUser(User.Identity.Name) == authRequest.LocalIdentifier)) { - return this.SendAssertion(pseudonymous); + if (authRequest.IsReturnUrlDiscoverable(OpenIdProvider) == RelyingPartyDiscoveryResult.Success && + User.Identity.IsAuthenticated && + (authRequest.IsDirectedIdentity || this.UserControlsIdentifier(authRequest))) { + return this.SendAssertion(); } else { - return RedirectToAction("LogOn", "Account", new { returnUrl = Url.Action("SendAssertion", new { pseudonymous = pseudonymous }) }); + return RedirectToAction("LogOn", "Account", new { returnUrl = Url.Action("SendAssertion") }); } } @@ -93,5 +45,46 @@ namespace OpenIdProviderMvc.Controllers { return View(); } } + + [Authorize] + public ActionResult SendAssertion() { + IAuthenticationRequest authReq = PendingAuthenticationRequest; + PendingAuthenticationRequest = null; // clear session static so we don't do this again + if (authReq == null) { + throw new InvalidOperationException("There's no pending authentication request!"); + } + + if (authReq.IsDirectedIdentity) { + authReq.LocalIdentifier = Models.User.GetClaimedIdentifierForUser(User.Identity.Name); + } + if (!authReq.IsDelegatedIdentifier) { + authReq.ClaimedIdentifier = authReq.LocalIdentifier; + } + + // Respond to AX/sreg extension requests. + //// Real web sites would have code here + + authReq.IsAuthenticated = this.UserControlsIdentifier(authReq); + return OpenIdProvider.PrepareResponse(authReq).AsActionResult(); + } + + /// <summary> + /// Checks whether the logged in user controls the OP local identifier in the given authentication request. + /// </summary> + /// <param name="authReq">The authentication request.</param> + /// <returns><c>true</c> if the user controls the identifier; <c>false</c> otherwise.</returns> + private bool UserControlsIdentifier(IAuthenticationRequest authReq) { + if (authReq == null) { + throw new ArgumentNullException("authReq"); + } + + if (User == null || User.Identity == null) { + return false; + } + + Uri userLocalIdentifier = Models.User.GetClaimedIdentifierForUser(User.Identity.Name); + return authReq.LocalIdentifier == userLocalIdentifier || + authReq.LocalIdentifier == PpidGeneration.PpidIdentifierProvider.GetIdentifier(userLocalIdentifier, authReq.Realm); + } } } diff --git a/samples/OpenIdProviderMvc/Controllers/UserController.cs b/samples/OpenIdProviderMvc/Controllers/UserController.cs index c160fce..3cb87ae 100644 --- a/samples/OpenIdProviderMvc/Controllers/UserController.cs +++ b/samples/OpenIdProviderMvc/Controllers/UserController.cs @@ -9,7 +9,7 @@ namespace OpenIdProviderMvc.Controllers { public class UserController : Controller { public ActionResult PpidIdentity() { if (Request.AcceptTypes.Contains("application/xrds+xml")) { - return View("PpidXrds"); + return View("Xrds"); } return View(); @@ -33,10 +33,6 @@ namespace OpenIdProviderMvc.Controllers { return View(); } - public ActionResult PpidXrds() { - return View(); - } - private ActionResult RedirectIfNotNormalizedRequestUri() { Uri normalized = Models.User.GetNormalizedClaimedIdentifier(Request.Url); if (Request.Url != normalized) { diff --git a/samples/OpenIdProviderMvc/Global.asax.cs b/samples/OpenIdProviderMvc/Global.asax.cs index 8c57961..a2bcfb2 100644 --- a/samples/OpenIdProviderMvc/Global.asax.cs +++ b/samples/OpenIdProviderMvc/Global.asax.cs @@ -26,10 +26,6 @@ "anon", new { controller = "User", action = "PpidIdentity", id = string.Empty }); routes.MapRoute( - "PpidXrds", - "PpidXrds", - new { controller = "Home", action = "PpidXrds" }); // Parameter defaults - routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = string.Empty }); // Parameter defaults @@ -37,6 +33,7 @@ protected void Application_Start() { RegisterRoutes(RouteTable.Routes); + DotNetOpenAuth.OpenId.Behaviors.PpidGeneration.PpidIdentifierProvider = new Code.AnonymousIdentifierProvider(); } } }
\ No newline at end of file diff --git a/samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj b/samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj index 5caf26d..f568538 100644 --- a/samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj +++ b/samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj @@ -92,10 +92,8 @@ <Content Include="Views\Account\ChangePassword.aspx" /> <Content Include="Views\Account\ChangePasswordSuccess.aspx" /> <Content Include="Views\Account\Register.aspx" /> - <Content Include="Views\Home\PpidXrds.aspx" /> <Content Include="Views\Home\Xrds.aspx" /> <Content Include="Views\OpenId\Provider.aspx" /> - <Content Include="Views\User\PpidXrds.aspx" /> <Content Include="Views\User\PpidIdentity.aspx" /> <Content Include="Views\User\Identity.aspx" /> <Content Include="Views\User\Xrds.aspx" /> diff --git a/samples/OpenIdProviderMvc/Views/Home/PpidXrds.aspx b/samples/OpenIdProviderMvc/Views/Home/PpidXrds.aspx deleted file mode 100644 index 990a3df..0000000 --- a/samples/OpenIdProviderMvc/Views/Home/PpidXrds.aspx +++ /dev/null @@ -1,18 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" ContentType="application/xrds+xml" %><?xml version="1.0" encoding="UTF-8"?> -<%-- -This page is a required as part of the service discovery phase of the openid -protocol (step 1). It simply renders the xml for doing service discovery of -server.aspx using the xrds mechanism. -This XRDS doc is discovered via the user.aspx page. ---%> -<xrds:XRDS - xmlns:xrds="xri://$xrds" - xmlns:openid="http://openid.net/xmlns/1.0" - xmlns="xri://$xrd*($v*2.0)"> - <XRD> - <Service priority="10"> - <Type>http://specs.openid.net/auth/2.0/server</Type> - <URI><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/OpenId/PpidProvider"))%></URI> - </Service> - </XRD> -</xrds:XRDS> diff --git a/samples/OpenIdProviderMvc/Views/User/PpidIdentity.aspx b/samples/OpenIdProviderMvc/Views/User/PpidIdentity.aspx index f33a694..655e5d6 100644 --- a/samples/OpenIdProviderMvc/Views/User/PpidIdentity.aspx +++ b/samples/OpenIdProviderMvc/Views/User/PpidIdentity.aspx @@ -9,7 +9,7 @@ <op:IdentityEndpoint ID="IdentityEndpoint11" runat="server" ProviderEndpointUrl="~/OpenId/PpidProvider" ProviderVersion="V11" /> <op:IdentityEndpoint ID="IdentityEndpoint20" runat="server" ProviderEndpointUrl="~/OpenId/PpidProvider" - XrdsUrl="~/User/all/ppidxrds" XrdsAutoAnswer="false" /> + XrdsUrl="~/User/all/xrds" XrdsAutoAnswer="false" /> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>OpenID identity page </h2> diff --git a/samples/OpenIdProviderMvc/Views/User/PpidXrds.aspx b/samples/OpenIdProviderMvc/Views/User/PpidXrds.aspx deleted file mode 100644 index 67256bd..0000000 --- a/samples/OpenIdProviderMvc/Views/User/PpidXrds.aspx +++ /dev/null @@ -1,13 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" ContentType="application/xrds+xml" %><?xml version="1.0" encoding="UTF-8"?> -<XRDS xmlns="xri://$xrds" xmlns:openid="http://openid.net/xmlns/1.0"> - <XRD xmlns="xri://$xrd*($v*2.0)"> - <Service priority="10"> - <Type>http://specs.openid.net/auth/2.0/signon</Type> - <URI><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/OpenId/PpidProvider"))%></URI> - </Service> - <Service priority="20"> - <Type>http://openid.net/signon/1.0</Type> - <URI><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/OpenId/PpidProvider"))%></URI> - </Service> - </XRD> -</XRDS> diff --git a/samples/OpenIdProviderMvc/Web.config b/samples/OpenIdProviderMvc/Web.config index 029414a..6f0fdd1 100644 --- a/samples/OpenIdProviderMvc/Web.config +++ b/samples/OpenIdProviderMvc/Web.config @@ -46,11 +46,17 @@ <!-- this is an optional configuration section where aspects of dotnetopenauth can be customized --> <dotNetOpenAuth> <openid> - <relyingParty> - <security requireSsl="false"/> + <provider> + <security requireSsl="false" /> + <behaviors> + <!-- Behaviors activate themselves automatically for individual matching requests. + The first one in this list to match an incoming request "owns" the request. If no + profile matches, the default behavior is assumed. --> + <add type="DotNetOpenAuth.OpenId.Behaviors.PpidGeneration, DotNetOpenAuth" /> + </behaviors> <!-- Uncomment the following to activate the sample custom store. --> <!--<store type="RelyingPartyWebForms.CustomStore, RelyingPartyWebForms" />--> - </relyingParty> + </provider> </openid> <messaging> <untrustedWebRequest> diff --git a/samples/OpenIdProviderWebForms/Code/Util.cs b/samples/OpenIdProviderWebForms/Code/Util.cs index 84d3c63..8700dbd 100644 --- a/samples/OpenIdProviderWebForms/Code/Util.cs +++ b/samples/OpenIdProviderWebForms/Code/Util.cs @@ -6,10 +6,6 @@ namespace OpenIdProviderWebForms.Code { using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Net; - using System.Text; using System.Web; using DotNetOpenAuth.OpenId; using DotNetOpenAuth.OpenId.Provider; @@ -51,6 +47,26 @@ namespace OpenIdProviderWebForms.Code { // to know the answer. idrequest.IsAuthenticated = userOwningOpenIdUrl == HttpContext.Current.User.Identity.Name; } + + if (idrequest.IsAuthenticated.Value) { + // add extension responses here. + } + } else { + HttpContext.Current.Response.Redirect("~/decide.aspx", true); + } + } + + internal static void ProcessAnonymousRequest(IAnonymousRequest request) { + if (request.Immediate) { + // NOTE: in a production provider site, you may want to only + // respond affirmatively if the user has already authorized this consumer + // to know the answer. + request.IsApproved = HttpContext.Current.User.Identity.IsAuthenticated; + + if (request.IsApproved.Value) { + // Add extension responses here. + // These would typically be filled in from a user database + } } else { HttpContext.Current.Response.Redirect("~/decide.aspx", true); } diff --git a/samples/OpenIdProviderWebForms/Provider.ashx.cs b/samples/OpenIdProviderWebForms/Provider.ashx.cs index 40acc04..c8441cf 100644 --- a/samples/OpenIdProviderWebForms/Provider.ashx.cs +++ b/samples/OpenIdProviderWebForms/Provider.ashx.cs @@ -24,17 +24,20 @@ // But authentication requests cannot be responded to until something on // this site decides whether to approve or disapprove the authentication. if (!request.IsResponseReady) { - var idrequest = (IAuthenticationRequest)request; - - // We store the authentication request in the user's session so that + // We store the request in the user's session so that // redirects and user prompts can appear and eventually some page can decide // to respond to the OpenID authentication request either affirmatively or // negatively. - ProviderEndpoint.PendingAuthenticationRequest = idrequest; + ProviderEndpoint.PendingAnonymousRequest = request as IAnonymousRequest; + ProviderEndpoint.PendingAuthenticationRequest = request as IAuthenticationRequest; // We delegate that approval process to our utility method that we share // with our other Provider sample page server.aspx. - Code.Util.ProcessAuthenticationChallenge(idrequest); + if (ProviderEndpoint.PendingAuthenticationRequest != null) { + Code.Util.ProcessAuthenticationChallenge(ProviderEndpoint.PendingAuthenticationRequest); + } else if (ProviderEndpoint.PendingAnonymousRequest != null) { + Code.Util.ProcessAnonymousRequest(ProviderEndpoint.PendingAnonymousRequest); + } // As part of authentication approval, the user may need to authenticate // to this Provider and/or decide whether to allow the requesting RP site @@ -52,7 +55,7 @@ ProviderEndpoint.Provider.SendResponse(request); // Make sure that any PendingAuthenticationRequest that MAY be set is cleared. - ProviderEndpoint.PendingAuthenticationRequest = null; + ProviderEndpoint.PendingRequest = null; } } } diff --git a/samples/OpenIdProviderWebForms/Web.config b/samples/OpenIdProviderWebForms/Web.config index 745cb2c..66cf12a 100644 --- a/samples/OpenIdProviderWebForms/Web.config +++ b/samples/OpenIdProviderWebForms/Web.config @@ -47,6 +47,13 @@ <dotNetOpenAuth> <openid> <provider> + <security requireSsl="false" /> + <behaviors> + <!-- Behaviors activate themselves automatically for individual matching requests. + The first one in this list to match an incoming request "owns" the request. If no + profile matches, the default behavior is assumed. --> + <!--<add type="DotNetOpenAuth.OpenId.Behaviors.PpidGeneration, DotNetOpenAuth" />--> + </behaviors> <!-- Uncomment the following to activate the sample custom store. --> <!--<store type="OpenIdProviderWebForms.Code.CustomStore, OpenIdProviderWebForms" />--> </provider> diff --git a/samples/OpenIdProviderWebForms/decide.aspx b/samples/OpenIdProviderWebForms/decide.aspx index 54c2f01..4a6e2d8 100644 --- a/samples/OpenIdProviderWebForms/decide.aspx +++ b/samples/OpenIdProviderWebForms/decide.aspx @@ -1,34 +1,24 @@ -<%@ Page Language="C#" AutoEventWireup="true" Inherits="OpenIdProviderWebForms.decide" CodeBehind="decide.aspx.cs" MasterPageFile="~/Site.Master" %> +<%@ Page Language="C#" AutoEventWireup="true" Inherits="OpenIdProviderWebForms.decide" + CodeBehind="decide.aspx.cs" MasterPageFile="~/Site.Master" %> <%@ Register Src="ProfileFields.ascx" TagName="ProfileFields" TagPrefix="uc1" %> <asp:Content runat="server" ContentPlaceHolderID="Main"> - <p> - A site has asked to authenticate that you own the identifier below. You should - only do this if you wish to log in to the site given by the Realm.</p> - <p> - This site - <asp:Label ID="relyingPartyVerificationResultLabel" runat="server" - Font-Bold="True" Text="failed" /> verification. </p> + <p><asp:Label ID="siteRequestLabel" runat="server" Text="A site has asked to authenticate that you own the identifier below." /> + You should only do this if you wish to log in to the site given by the Realm.</p> + <p>This site <asp:Label ID="relyingPartyVerificationResultLabel" runat="server" Font-Bold="True" + Text="failed" /> verification. </p> <table> <tr> - <td> - Identifier: </td> - <td> - <asp:Label runat="server" ID='identityUrlLabel' /> - </td> + <td>Identifier: </td> + <td><asp:Label runat="server" ID='identityUrlLabel' /> </td> </tr> <tr> - <td> - Realm: </td> - <td> - <asp:Label runat="server" ID='realmLabel' /> - </td> + <td>Realm: </td> + <td><asp:Label runat="server" ID='realmLabel' /> </td> </tr> </table> - <p> - Allow this authentication to proceed? - </p> + <p>Allow this to proceed? </p> <uc1:ProfileFields ID="profileFields" runat="server" Visible="false" /> <asp:Button ID="yes_button" OnClick="Yes_Click" Text=" yes " runat="Server" /> <asp:Button ID="no_button" OnClick="No_Click" Text=" no " runat="Server" /> -</asp:Content>
\ No newline at end of file +</asp:Content> diff --git a/samples/OpenIdProviderWebForms/decide.aspx.cs b/samples/OpenIdProviderWebForms/decide.aspx.cs index 777a688..3a14cf7 100644 --- a/samples/OpenIdProviderWebForms/decide.aspx.cs +++ b/samples/OpenIdProviderWebForms/decide.aspx.cs @@ -12,61 +12,75 @@ namespace OpenIdProviderWebForms { /// </summary> public partial class decide : Page { protected void Page_Load(object src, EventArgs e) { - if (ProviderEndpoint.PendingAuthenticationRequest == null) { + if (ProviderEndpoint.PendingRequest == null) { Response.Redirect("~/"); } - if (ProviderEndpoint.PendingAuthenticationRequest.IsDirectedIdentity) { - ProviderEndpoint.PendingAuthenticationRequest.LocalIdentifier = Code.Util.BuildIdentityUrl(); - } this.relyingPartyVerificationResultLabel.Text = - ProviderEndpoint.PendingAuthenticationRequest.IsReturnUrlDiscoverable(ProviderEndpoint.Provider.Channel.WebRequestHandler) ? "passed" : "failed"; + ProviderEndpoint.PendingRequest.IsReturnUrlDiscoverable(ProviderEndpoint.Provider) == RelyingPartyDiscoveryResult.Success ? "passed" : "failed"; + + this.realmLabel.Text = ProviderEndpoint.PendingRequest.Realm.ToString(); - this.identityUrlLabel.Text = ProviderEndpoint.PendingAuthenticationRequest.LocalIdentifier.ToString(); - this.realmLabel.Text = ProviderEndpoint.PendingAuthenticationRequest.Realm.ToString(); + if (ProviderEndpoint.PendingAuthenticationRequest != null) { + if (ProviderEndpoint.PendingAuthenticationRequest.IsDirectedIdentity) { + ProviderEndpoint.PendingAuthenticationRequest.LocalIdentifier = Code.Util.BuildIdentityUrl(); + } + this.identityUrlLabel.Text = ProviderEndpoint.PendingAuthenticationRequest.LocalIdentifier.ToString(); - // check that the logged in user is the same as the user requesting authentication to the consumer. If not, then log them out. - if (string.Equals(User.Identity.Name, Code.Util.ExtractUserName(ProviderEndpoint.PendingAuthenticationRequest.LocalIdentifier), StringComparison.OrdinalIgnoreCase)) { - // if simple registration fields were used, then prompt the user for them - var requestedFields = ProviderEndpoint.PendingAuthenticationRequest.GetExtension<ClaimsRequest>(); - if (requestedFields != null) { - this.profileFields.Visible = true; - this.profileFields.SetRequiredFieldsFromRequest(requestedFields); - if (!IsPostBack) { - var sregResponse = requestedFields.CreateResponse(); - sregResponse.Email = Membership.GetUser().Email; - this.profileFields.SetOpenIdProfileFields(sregResponse); - } + // check that the logged in user is the same as the user requesting authentication to the consumer. If not, then log them out. + if (!string.Equals(User.Identity.Name, Code.Util.ExtractUserName(ProviderEndpoint.PendingAuthenticationRequest.LocalIdentifier), StringComparison.OrdinalIgnoreCase)) { + FormsAuthentication.SignOut(); + Response.Redirect(Request.Url.AbsoluteUri); } } else { - FormsAuthentication.SignOut(); - Response.Redirect(Request.Url.AbsoluteUri); + this.identityUrlLabel.Text = "(not applicable)"; + this.siteRequestLabel.Text = "A site has asked for information about you."; + } + + // if simple registration fields were used, then prompt the user for them + var requestedFields = ProviderEndpoint.PendingRequest.GetExtension<ClaimsRequest>(); + if (requestedFields != null) { + this.profileFields.Visible = true; + this.profileFields.SetRequiredFieldsFromRequest(requestedFields); + if (!IsPostBack) { + var sregResponse = requestedFields.CreateResponse(); + sregResponse.Email = Membership.GetUser().Email; + this.profileFields.SetOpenIdProfileFields(sregResponse); + } } } protected void Yes_Click(object sender, EventArgs e) { - var sregRequest = ProviderEndpoint.PendingAuthenticationRequest.GetExtension<ClaimsRequest>(); + var sregRequest = ProviderEndpoint.PendingRequest.GetExtension<ClaimsRequest>(); ClaimsResponse sregResponse = null; if (sregRequest != null) { sregResponse = this.profileFields.GetOpenIdProfileFields(sregRequest); - ProviderEndpoint.PendingAuthenticationRequest.AddResponseExtension(sregResponse); + ProviderEndpoint.PendingRequest.AddResponseExtension(sregResponse); } - var papeRequest = ProviderEndpoint.PendingAuthenticationRequest.GetExtension<PolicyRequest>(); + var papeRequest = ProviderEndpoint.PendingRequest.GetExtension<PolicyRequest>(); PolicyResponse papeResponse = null; if (papeRequest != null) { papeResponse = new PolicyResponse(); papeResponse.NistAssuranceLevel = NistAssuranceLevel.InsufficientForLevel1; - ProviderEndpoint.PendingAuthenticationRequest.AddResponseExtension(papeResponse); + ProviderEndpoint.PendingRequest.AddResponseExtension(papeResponse); } - ProviderEndpoint.PendingAuthenticationRequest.IsAuthenticated = true; - Debug.Assert(ProviderEndpoint.PendingAuthenticationRequest.IsResponseReady, "Setting authentication should be all that's necessary."); + if (ProviderEndpoint.PendingAuthenticationRequest != null) { + ProviderEndpoint.PendingAuthenticationRequest.IsAuthenticated = true; + } else { + ProviderEndpoint.PendingAnonymousRequest.IsApproved = true; + } + Debug.Assert(ProviderEndpoint.PendingRequest.IsResponseReady, "Setting authentication should be all that's necessary."); ProviderEndpoint.SendResponse(); } protected void No_Click(object sender, EventArgs e) { - ProviderEndpoint.PendingAuthenticationRequest.IsAuthenticated = false; - Debug.Assert(ProviderEndpoint.PendingAuthenticationRequest.IsResponseReady, "Setting authentication should be all that's necessary."); + if (ProviderEndpoint.PendingAuthenticationRequest != null) { + ProviderEndpoint.PendingAuthenticationRequest.IsAuthenticated = false; + } else { + ProviderEndpoint.PendingAnonymousRequest.IsApproved = false; + } + Debug.Assert(ProviderEndpoint.PendingRequest.IsResponseReady, "Setting authentication should be all that's necessary."); ProviderEndpoint.SendResponse(); } } diff --git a/samples/OpenIdProviderWebForms/decide.aspx.designer.cs b/samples/OpenIdProviderWebForms/decide.aspx.designer.cs index 795d1c7..05386cd 100644 --- a/samples/OpenIdProviderWebForms/decide.aspx.designer.cs +++ b/samples/OpenIdProviderWebForms/decide.aspx.designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:2.0.50727.3521 +// Runtime Version:2.0.50727.4918 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -14,6 +14,15 @@ namespace OpenIdProviderWebForms { public partial class decide { /// <summary> + /// siteRequestLabel 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 siteRequestLabel; + + /// <summary> /// relyingPartyVerificationResultLabel control. /// </summary> /// <remarks> diff --git a/samples/OpenIdProviderWebForms/server.aspx b/samples/OpenIdProviderWebForms/server.aspx index 10030a6..d3ce78d 100644 --- a/samples/OpenIdProviderWebForms/server.aspx +++ b/samples/OpenIdProviderWebForms/server.aspx @@ -14,7 +14,7 @@ This server.aspx page is the default provider endpoint to use. To switch to the .ashx handler, change the user_xrds.aspx and op_xrds.aspx files to point to provider.ashx instead of server.aspx. --%> - <openid:ProviderEndpoint runat="server" OnAuthenticationChallenge="provider_AuthenticationChallenge" /> + <openid:ProviderEndpoint runat="server" OnAuthenticationChallenge="provider_AuthenticationChallenge" OnAnonymousRequest="provider_AnonymousRequest" /> <p> <asp:Label ID="serverEndpointUrl" runat="server" EnableViewState="false" /> is an OpenID server endpoint. diff --git a/samples/OpenIdProviderWebForms/server.aspx.cs b/samples/OpenIdProviderWebForms/server.aspx.cs index c0af0b4..89e14f4 100644 --- a/samples/OpenIdProviderWebForms/server.aspx.cs +++ b/samples/OpenIdProviderWebForms/server.aspx.cs @@ -14,5 +14,9 @@ namespace OpenIdProviderWebForms { protected void provider_AuthenticationChallenge(object sender, AuthenticationChallengeEventArgs e) { Code.Util.ProcessAuthenticationChallenge(e.Request); } + + protected void provider_AnonymousRequest(object sender, AnonymousRequestEventArgs e) { + Code.Util.ProcessAnonymousRequest(e.Request); + } } }
\ No newline at end of file diff --git a/samples/OpenIdRelyingPartyClassicAsp/login.asp b/samples/OpenIdRelyingPartyClassicAsp/login.asp index 878ab39..d222e57 100644 --- a/samples/OpenIdRelyingPartyClassicAsp/login.asp +++ b/samples/OpenIdRelyingPartyClassicAsp/login.asp @@ -17,23 +17,37 @@ thisPageUrl = "http://" + Request.ServerVariables("HTTP_HOST") + Request.ServerVariables("URL") requestUrl = "http://" + Request.ServerVariables("HTTP_HOST") + Request.ServerVariables("HTTP_URL") Set dnoi = server.CreateObject("DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty") + On Error Resume Next Set authentication = dnoi.ProcessAuthentication(requestUrl, Request.Form) + If Err.number <> 0 Then + Response.Write "<p>" + Server.HTMLEncode(Err.Description) + "</p>" + End If + On Error Goto 0 if Not authentication Is Nothing then If authentication.Successful Then Session("ClaimedIdentifier") = authentication.ClaimedIdentifier - Session("Email") = authentication.ClaimsResponse.Email - Session("Nickname") = authentication.ClaimsResponse.Nickname - Session("FullName") = authentication.ClaimsResponse.FullName + If Not authentication.ClaimsResponse Is Nothing Then + Session("Email") = authentication.ClaimsResponse.Email + Session("Nickname") = authentication.ClaimsResponse.Nickname + Session("FullName") = authentication.ClaimsResponse.FullName + End If Response.Redirect "MembersOnly.asp" else Response.Write "Authentication failed: " + authentication.ExceptionMessage end if elseif Request.Form("openid_identifier") <> "" then dim redirectUrl + On Error Resume Next ' redirectUrl = dnoi.CreateRequest(Request.Form("openid_identifier"), realm, thisPageUrl) redirectUrl = dnoi.CreateRequestWithSimpleRegistration(Request.Form("openid_identifier"), realm, thisPageUrl, "nickname,email", "fullname") - Response.Redirect redirectUrl + If Err.number <> 0 Then + Response.Write "<p>" + Server.HTMLEncode(Err.Description) + "</p>" + Else + Response.Redirect redirectUrl + End If + On Error Goto 0 End If + %> <form action="login.asp" method="post"> OpenID Login: diff --git a/samples/OpenIdRelyingPartyMvc/Global.asax.cs b/samples/OpenIdRelyingPartyMvc/Global.asax.cs index a43b734..d57a13f 100644 --- a/samples/OpenIdRelyingPartyMvc/Global.asax.cs +++ b/samples/OpenIdRelyingPartyMvc/Global.asax.cs @@ -17,6 +17,11 @@ "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = string.Empty }); // Parameter defaults + + routes.MapRoute( + "Root", + string.Empty, + new { controller = "Home", action = "Index", id = string.Empty }); } protected void Application_Start(object sender, EventArgs e) { diff --git a/samples/OpenIdRelyingPartyMvc/Web.config b/samples/OpenIdRelyingPartyMvc/Web.config index bb9f8e1..c3bfa41 100644 --- a/samples/OpenIdRelyingPartyMvc/Web.config +++ b/samples/OpenIdRelyingPartyMvc/Web.config @@ -47,6 +47,11 @@ <openid> <relyingParty> <security requireSsl="false" /> + <behaviors> + <!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible + with OPs that use Attribute Exchange (in various formats). --> + <add type="DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform, DotNetOpenAuth" /> + </behaviors> </relyingParty> </openid> <messaging> diff --git a/samples/OpenIdRelyingPartyWebForms/MembersOnly/Default.aspx b/samples/OpenIdRelyingPartyWebForms/MembersOnly/Default.aspx index 46458e8..cbc13ee 100644 --- a/samples/OpenIdRelyingPartyWebForms/MembersOnly/Default.aspx +++ b/samples/OpenIdRelyingPartyWebForms/MembersOnly/Default.aspx @@ -1,6 +1,6 @@ <%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/Site.Master" %> <%@ Import Namespace="OpenIdRelyingPartyWebForms" %> - +<%@ Register Src="~/MembersOnly/ProfileFieldsDisplay.ascx" TagPrefix="cc1" TagName="ProfileFieldsDisplay" %> <asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Main"> <h2> Members Only Area @@ -22,85 +22,13 @@ </ul> <% } %> -<% if (State.ProfileFields != null) { %> +<% if (State.ProfileFields != null) { + profileFieldsDisplay.ProfileValues = State.ProfileFields; %> <p> In addition to authenticating you, your OpenID Provider may have told us something about you using the Simple Registration extension: </p> - <table id="profileFieldsTable" runat="server"> - <tr> - <td> - Nickname - </td> - <td> - <%=State.ProfileFields.Nickname %> - </td> - </tr> - <tr> - <td> - Email - </td> - <td> - <%=State.ProfileFields.Email%> - </td> - </tr> - <tr> - <td> - FullName - </td> - <td> - <%=State.ProfileFields.FullName%> - </td> - </tr> - <tr> - <td> - Date of Birth - </td> - <td> - <%=State.ProfileFields.BirthDate.ToString()%> - </td> - </tr> - <tr> - <td> - Gender - </td> - <td> - <%=State.ProfileFields.Gender.ToString()%> - </td> - </tr> - <tr> - <td> - Post Code - </td> - <td> - <%=State.ProfileFields.PostalCode%> - </td> - </tr> - <tr> - <td> - Country - </td> - <td> - <%=State.ProfileFields.Country%> - </td> - </tr> - <tr> - <td> - Language - </td> - <td> - <%=State.ProfileFields.Language%> - </td> - </tr> - <tr> - <td> - Timezone - </td> - <td> - <%=State.ProfileFields.TimeZone%> - </td> - </tr> - </table> + <cc1:ProfileFieldsDisplay runat="server" ID="profileFieldsDisplay" /> <% } %> </asp:Content> diff --git a/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx b/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx new file mode 100644 index 0000000..b2e5f7e --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx @@ -0,0 +1,75 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ProfileFieldsDisplay.ascx.cs" Inherits="OpenIdRelyingPartyWebForms.MembersOnly.ProfileFieldsDisplay" %> +<table id="profileFieldsTable" runat="server"> + <tr> + <td> + Nickname + </td> + <td> + <%=ProfileValues.Nickname %> + </td> + </tr> + <tr> + <td> + Email + </td> + <td> + <%=ProfileValues.Email%> + </td> + </tr> + <tr> + <td> + FullName + </td> + <td> + <%=ProfileValues.FullName%> + </td> + </tr> + <tr> + <td> + Date of Birth + </td> + <td> + <%=ProfileValues.BirthDate.ToString()%> + </td> + </tr> + <tr> + <td> + Gender + </td> + <td> + <%=ProfileValues.Gender.ToString()%> + </td> + </tr> + <tr> + <td> + Post Code + </td> + <td> + <%=ProfileValues.PostalCode%> + </td> + </tr> + <tr> + <td> + Country + </td> + <td> + <%=ProfileValues.Country%> + </td> + </tr> + <tr> + <td> + Language + </td> + <td> + <%=ProfileValues.Language%> + </td> + </tr> + <tr> + <td> + Timezone + </td> + <td> + <%=ProfileValues.TimeZone%> + </td> + </tr> +</table> diff --git a/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx.cs b/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx.cs new file mode 100644 index 0000000..4fb127e --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx.cs @@ -0,0 +1,13 @@ +namespace OpenIdRelyingPartyWebForms.MembersOnly { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using System.Web.UI; + using System.Web.UI.WebControls; + using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration; + + public partial class ProfileFieldsDisplay : System.Web.UI.UserControl { + public ClaimsResponse ProfileValues { get; set; } + } +}
\ No newline at end of file diff --git a/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx.designer.cs b/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx.designer.cs new file mode 100644 index 0000000..4a5dc8a --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/MembersOnly/ProfileFieldsDisplay.ascx.designer.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:2.0.50727.4918 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OpenIdRelyingPartyWebForms.MembersOnly { + + + public partial class ProfileFieldsDisplay { + + /// <summary> + /// profileFieldsTable control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.HtmlControls.HtmlTable profileFieldsTable; + } +} diff --git a/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx b/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx new file mode 100644 index 0000000..dc0c2bb --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx @@ -0,0 +1,41 @@ +<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NoIdentityOpenId.aspx.cs" + MasterPageFile="~/Site.Master" Inherits="OpenIdRelyingPartyWebForms.NoIdentityOpenId" %> + +<asp:Content runat="server" ContentPlaceHolderID="Main"> + <h2>No-login OpenID extension Page </h2> + <p>This demonstrates an RP sending an extension-only request to an OP that carries + extensions that request anonymous information about you. In this scenario, the OP + would still authenticate the user, but would not assert any OpenID Identifier back + to the RP, but might provide information regarding the user such as age or membership + in an organization. </p> + <p><b>Note: </b>At time of this writing, most OPs do not support this feature, although + it is documented in the OpenID 2.0 spec. </p> + <asp:Label ID="Label1" runat="server" Text="OpenID Identifier" /> <asp:TextBox ID="openIdBox" + runat="server" /> + <asp:Button ID="beginButton" runat="server" Text="Begin" OnClick="beginButton_Click" /> + <asp:CustomValidator runat="server" ID="openidValidator" ErrorMessage="Invalid OpenID Identifier" + ControlToValidate="openIdBox" EnableViewState="false" Display="Dynamic" OnServerValidate="openidValidator_ServerValidate" /> + <asp:Label runat="server" EnableViewState="false" ID="resultMessage" /> + <asp:Panel runat="server" ID="ExtensionResponsesPanel" EnableViewState="false" Visible="false"> + <p>We have received a reasonable response from the Provider. Below is the Simple Registration + response we received, if any: </p> + <table id="profileFieldsTable" runat="server"> + <tr> + <td>Gender </td> + <td><asp:Label runat="server" ID="genderLabel" /> </td> + </tr> + <tr> + <td>Post Code </td> + <td><asp:Label runat="server" ID="postalCodeLabel" /> </td> + </tr> + <tr> + <td>Country </td> + <td><asp:Label runat="server" ID="countryLabel" /> </td> + </tr> + <tr> + <td>Timezone </td> + <td><asp:Label runat="server" ID="timeZoneLabel" /> </td> + </tr> + </table> + </asp:Panel> +</asp:Content> diff --git a/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx.cs b/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx.cs new file mode 100644 index 0000000..37a5515 --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx.cs @@ -0,0 +1,79 @@ +namespace OpenIdRelyingPartyWebForms { + using System; + using System.Web.UI.WebControls; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration; + using DotNetOpenAuth.OpenId.RelyingParty; + + public partial class NoIdentityOpenId : System.Web.UI.Page { + protected void Page_Load(object sender, EventArgs e) { + this.openIdBox.Focus(); + using (OpenIdRelyingParty rp = new OpenIdRelyingParty()) { + IAuthenticationResponse response = rp.GetResponse(); + if (response != null) { + switch (response.Status) { + case AuthenticationStatus.ExtensionsOnly: + this.ExtensionResponsesPanel.Visible = true; + + // This is the "success" status we get when no authentication was requested. + var sreg = response.GetExtension<ClaimsResponse>(); + if (sreg != null) { + this.timeZoneLabel.Text = sreg.TimeZone; + this.postalCodeLabel.Text = sreg.PostalCode; + this.countryLabel.Text = sreg.Country; + if (sreg.Gender.HasValue) { + this.genderLabel.Text = sreg.Gender.Value.ToString(); + } + } + break; + case AuthenticationStatus.Canceled: + this.resultMessage.Text = "Canceled at OP. This may be a sign that the OP doesn't support this message."; + break; + case AuthenticationStatus.Failed: + this.resultMessage.Text = "OP returned a failure: " + response.Exception; + break; + case AuthenticationStatus.SetupRequired: + case AuthenticationStatus.Authenticated: + default: + this.resultMessage.Text = "OP returned an unexpected response."; + break; + } + } + } + } + + protected void beginButton_Click(object sender, EventArgs e) { + if (!this.Page.IsValid) { + return; // don't login if custom validation failed. + } + try { + using (OpenIdRelyingParty rp = new OpenIdRelyingParty()) { + var request = rp.CreateRequest(this.openIdBox.Text); + request.IsExtensionOnly = true; + + // This is where you would add any OpenID extensions you wanted + // to include in the request. + request.AddExtension(new ClaimsRequest { + Country = DemandLevel.Request, + Gender = DemandLevel.Require, + PostalCode = DemandLevel.Require, + TimeZone = DemandLevel.Require, + }); + + request.RedirectToProvider(); + } + } catch (ProtocolException ex) { + // The user probably entered an Identifier that + // was not a valid OpenID endpoint. + this.openidValidator.Text = ex.Message; + this.openidValidator.IsValid = false; + } + } + + protected void openidValidator_ServerValidate(object source, ServerValidateEventArgs args) { + // This catches common typos that result in an invalid OpenID Identifier. + args.IsValid = Identifier.IsValid(args.Value); + } + } +} diff --git a/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx.designer.cs b/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx.designer.cs new file mode 100644 index 0000000..fb959a3 --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/NoIdentityOpenId.aspx.designer.cs @@ -0,0 +1,115 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:2.0.50727.4918 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OpenIdRelyingPartyWebForms { + + + public partial class NoIdentityOpenId { + + /// <summary> + /// Label1 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 Label1; + + /// <summary> + /// openIdBox 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.TextBox openIdBox; + + /// <summary> + /// beginButton 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.Button beginButton; + + /// <summary> + /// openidValidator 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.CustomValidator openidValidator; + + /// <summary> + /// resultMessage 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 resultMessage; + + /// <summary> + /// ExtensionResponsesPanel 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 ExtensionResponsesPanel; + + /// <summary> + /// profileFieldsTable control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::System.Web.UI.HtmlControls.HtmlTable profileFieldsTable; + + /// <summary> + /// genderLabel 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 genderLabel; + + /// <summary> + /// postalCodeLabel 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 postalCodeLabel; + + /// <summary> + /// countryLabel 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 countryLabel; + + /// <summary> + /// timeZoneLabel 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 timeZoneLabel; + } +} diff --git a/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj b/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj index c45f007..d3bf92c 100644 --- a/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj +++ b/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj @@ -132,6 +132,13 @@ <Compile Include="MembersOnly\DisplayGoogleContacts.aspx.designer.cs"> <DependentUpon>DisplayGoogleContacts.aspx</DependentUpon> </Compile> + <Compile Include="MembersOnly\ProfileFieldsDisplay.ascx.cs"> + <DependentUpon>ProfileFieldsDisplay.ascx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="MembersOnly\ProfileFieldsDisplay.ascx.designer.cs"> + <DependentUpon>ProfileFieldsDisplay.ascx</DependentUpon> + </Compile> <Compile Include="m\Login.aspx.cs"> <DependentUpon>Login.aspx</DependentUpon> <SubType>ASPXCodeBehind</SubType> @@ -139,6 +146,13 @@ <Compile Include="m\Login.aspx.designer.cs"> <DependentUpon>Login.aspx</DependentUpon> </Compile> + <Compile Include="NoIdentityOpenId.aspx.cs"> + <DependentUpon>NoIdentityOpenId.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="NoIdentityOpenId.aspx.designer.cs"> + <DependentUpon>NoIdentityOpenId.aspx</DependentUpon> + </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="TracePage.aspx.cs"> <DependentUpon>TracePage.aspx</DependentUpon> @@ -161,8 +175,10 @@ <Content Include="images\yahoo.png" /> <Content Include="loginPlusOAuth.aspx" /> <Content Include="MembersOnly\DisplayGoogleContacts.aspx" /> + <Content Include="MembersOnly\ProfileFieldsDisplay.ascx" /> <Content Include="MembersOnly\Web.config" /> <Content Include="m\Login.aspx" /> + <Content Include="NoIdentityOpenId.aspx" /> </ItemGroup> <ItemGroup> <None Include="Code\CustomStoreDataSet.xsc"> diff --git a/samples/OpenIdRelyingPartyWebForms/Web.config b/samples/OpenIdRelyingPartyWebForms/Web.config index 4408ebf..20ac864 100644 --- a/samples/OpenIdRelyingPartyWebForms/Web.config +++ b/samples/OpenIdRelyingPartyWebForms/Web.config @@ -29,6 +29,11 @@ <openid> <relyingParty> <security requireSsl="false" /> + <behaviors> + <!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible + with OPs that use Attribute Exchange (in various formats). --> + <add type="DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform, DotNetOpenAuth" /> + </behaviors> <!-- Uncomment the following to activate the sample custom store. --> <!--<store type="OpenIdRelyingPartyWebForms.CustomStore, OpenIdRelyingPartyWebForms" />--> </relyingParty> diff --git a/samples/OpenIdRelyingPartyWebForms/login.aspx b/samples/OpenIdRelyingPartyWebForms/login.aspx index 6e66fd3..281725c 100644 --- a/samples/OpenIdRelyingPartyWebForms/login.aspx +++ b/samples/OpenIdRelyingPartyWebForms/login.aspx @@ -5,7 +5,7 @@ <asp:Content runat="server" ContentPlaceHolderID="Main"> <h2>Login Page </h2> <rp:OpenIdLogin ID="OpenIdLogin1" runat="server" CssClass="openid_login" RequestCountry="Request" - RequestEmail="Request" RequestGender="Require" RequestPostalCode="Require" RequestTimeZone="Require" + RequestEmail="Require" RequestGender="Require" RequestPostalCode="Require" RequestTimeZone="Require" RememberMeVisible="True" PolicyUrl="~/PrivacyPolicy.aspx" TabIndex="1" OnLoggedIn="OpenIdLogin1_LoggedIn" OnLoggingIn="OpenIdLogin1_LoggingIn" OnSetupRequired="OpenIdLogin1_SetupRequired" /> @@ -13,18 +13,20 @@ <asp:CheckBox ID="requireSslCheckBox" runat="server" Text="RequireSsl (high security) mode" oncheckedchanged="requireSslCheckBox_CheckedChanged" /><br /> - <asp:CheckBox ID="immediateCheckBox" runat="server" Text="Immediate mode" /><br /> + <h4 style="margin-top: 0; margin-bottom: 0">PAPE policies</h4> <asp:CheckBoxList runat="server" ID="papePolicies"> <asp:ListItem Text="Request phishing resistant authentication" Value="http://schemas.openid.net/pape/policies/2007/06/phishing-resistant" /> <asp:ListItem Text="Request multi-factor authentication" Value="http://schemas.openid.net/pape/policies/2007/06/multi-factor" /> <asp:ListItem Text="Request physical multi-factor authentication" Value="http://schemas.openid.net/pape/policies/2007/06/multi-factor-physical" /> + <asp:ListItem Text="Request PPID identifier" Value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" /> </asp:CheckBoxList> + <p>Try the PPID identifier functionality against the OpenIDProviderMvc sample.</p> </fieldset> <br /> <asp:Label ID="setupRequiredLabel" runat="server" EnableViewState="False" Text="You must log into your Provider first to use Immediate mode." Visible="False" /> <p> - <asp:ImageButton runat="server" ImageUrl="~/images/yahoo.png" ID="yahooLoginButton" - OnClick="yahooLoginButton_Click" /> + <rp:OpenIdButton runat="server" ImageUrl="~/images/yahoo.png" Text="Login with Yahoo!" ID="yahooLoginButton" + Identifier="https://me.yahoo.com/" /> </p> </asp:Content> diff --git a/samples/OpenIdRelyingPartyWebForms/login.aspx.cs b/samples/OpenIdRelyingPartyWebForms/login.aspx.cs index 37a714c..1de942a 100644 --- a/samples/OpenIdRelyingPartyWebForms/login.aspx.cs +++ b/samples/OpenIdRelyingPartyWebForms/login.aspx.cs @@ -39,20 +39,7 @@ namespace OpenIdRelyingPartyWebForms { this.setupRequiredLabel.Visible = true; } - protected void yahooLoginButton_Click(object sender, ImageClickEventArgs e) { - OpenIdRelyingParty openid = new OpenIdRelyingParty(); - var req = openid.CreateRequest("yahoo.com"); - this.prepareRequest(req); - req.RedirectToProvider(); - - // We don't listen for the response from the provider explicitly - // because the OpenIdLogin control is already doing that for us. - } - private void prepareRequest(IAuthenticationRequest request) { - // Setup is the default for the login control. But the user may have checked the box to override that. - request.Mode = this.immediateCheckBox.Checked ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup; - // Collect the PAPE policies requested by the user. List<string> policies = new List<string>(); foreach (ListItem item in this.papePolicies.Items) { diff --git a/samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs b/samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs index 436ef7b..944f5ff 100644 --- a/samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs +++ b/samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:2.0.50727.4912 +// Runtime Version:2.0.50727.4918 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -32,15 +32,6 @@ namespace OpenIdRelyingPartyWebForms { protected global::System.Web.UI.WebControls.CheckBox requireSslCheckBox; /// <summary> - /// immediateCheckBox 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.CheckBox immediateCheckBox; - - /// <summary> /// papePolicies control. /// </summary> /// <remarks> @@ -65,6 +56,6 @@ namespace OpenIdRelyingPartyWebForms { /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// </remarks> - protected global::System.Web.UI.WebControls.ImageButton yahooLoginButton; + protected global::DotNetOpenAuth.OpenId.RelyingParty.OpenIdButton yahooLoginButton; } } diff --git a/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx b/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx index a00eccd..78179f7 100644 --- a/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx +++ b/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx @@ -12,4 +12,5 @@ Visible="False" /> <asp:Label ID="loginCanceledLabel" runat="server" EnableViewState="False" Text="Login canceled" Visible="False" /> + <asp:CheckBox ID="noLoginCheckBox" runat="server" Text="Extensions only (no login) -- most OPs don't yet support this" /> </asp:Content>
\ No newline at end of file diff --git a/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx.designer.cs b/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx.designer.cs index 0363be7..239d7b8 100644 --- a/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx.designer.cs +++ b/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx.designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:2.0.50727.4912 +// Runtime Version:2.0.50727.4918 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -66,5 +66,14 @@ namespace OpenIdRelyingPartyWebForms { /// To modify move field declaration from designer file to code-behind file. /// </remarks> protected global::System.Web.UI.WebControls.Label loginCanceledLabel; + + /// <summary> + /// noLoginCheckBox 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.CheckBox noLoginCheckBox; } } diff --git a/samples/OpenIdRelyingPartyWebForms/xrds.aspx b/samples/OpenIdRelyingPartyWebForms/xrds.aspx index e169bc7..9e201d0 100644 --- a/samples/OpenIdRelyingPartyWebForms/xrds.aspx +++ b/samples/OpenIdRelyingPartyWebForms/xrds.aspx @@ -17,6 +17,7 @@ is default.aspx. <URI priority="1"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/login.aspx"))%></URI> <URI priority="2"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginProgrammatic.aspx"))%></URI> <URI priority="3"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/ajaxlogin.aspx"))%></URI> + <URI priority="3"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/NoIdentityOpenId.aspx"))%></URI> </Service> </XRD> </xrds:XRDS> |