summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenId/Provider/ProviderEndpoint.cs
blob: 40d8dea4eef4ce27923ba83cd7797f0886e81784 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using IProviderAssociationStore = DotNetOpenId.IAssociationStore<DotNetOpenId.AssociationRelyingPartyType>;

namespace DotNetOpenId.Provider {
	/// <summary>
	/// An OpenID Provider control that automatically responds to certain
	/// automated OpenID messages, and routes authentication requests to
	/// custom code via an event handler.
	/// </summary>
	[DefaultEvent("AuthenticationChallenge")]
	[ToolboxData("<{0}:ProviderEndpoint runat='server' />")]
	public class ProviderEndpoint : Control {

		const string pendingAuthenticationRequestKey = "pendingAuthenticationRequestKey";
		/// <summary>
		/// An incoming OpenID authentication request that has not yet been responded to.
		/// </summary>
		/// <remarks>
		/// This request is stored in the ASP.NET Session state, so it will survive across
		/// redirects, postbacks, and transfers.  This allows you to authenticate the user
		/// yourself, and confirm his/her desire to authenticate to the relying party site
		/// before responding to the relying party's authentication request.
		/// </remarks>
		public static IAuthenticationRequest PendingAuthenticationRequest {
			get { return HttpContext.Current.Session[pendingAuthenticationRequestKey] as IAuthenticationRequest; }
			set { HttpContext.Current.Session[pendingAuthenticationRequestKey] = value; }
		}

		const bool enabledDefault = true;
		const string enabledViewStateKey = "Enabled";
		/// <summary>
		/// Whether or not this control should be listening for and responding
		/// to incoming OpenID requests.
		/// </summary>
		[Category("Behavior")]
		[DefaultValue(enabledDefault)]
		public bool Enabled {
			get {
				return ViewState[enabledViewStateKey] == null ?
				enabledDefault : (bool)ViewState[enabledViewStateKey];
			}
			set { ViewState[enabledViewStateKey] = value; }
		}

		/// <summary>
		/// A custom application store to use.  Null to use the default.
		/// </summary>
		/// <remarks>
		/// If set, this property must be set in each Page Load event
		/// as it is not persisted across postbacks.
		/// </remarks>
		public IProviderAssociationStore CustomApplicationStore { get; set; }

		/// <summary>
		/// Checks for incoming OpenID requests, responds to ones it can
		/// respond to without policy checks, and fires events for custom
		/// handling of the ones it cannot decide on automatically.
		/// </summary>
		protected override void OnLoad(EventArgs e) {
			base.OnLoad(e);

			if (Enabled) {
				// Use the explicitly given state store on this control if there is one.  
				// Then try the configuration file specified one.  Finally, use the default
				// in-memory one that's built into OpenIdProvider.
				OpenIdProvider provider = new OpenIdProvider(
					CustomApplicationStore ?? OpenIdProvider.Configuration.Store.CreateInstanceOfStore(OpenIdProvider.HttpApplicationStore),
					OpenIdProvider.DefaultProviderEndpoint,
					OpenIdProvider.DefaultRequestUrl,
					OpenIdProvider.DefaultQuery);

				// determine what incoming message was received
				if (provider.Request != null) {
					// process the incoming message appropriately and send the response
					if (!provider.Request.IsResponseReady) {
						var idrequest = (CheckIdRequest)provider.Request;
						PendingAuthenticationRequest = idrequest;
						OnAuthenticationChallenge(idrequest);
					} else {
						PendingAuthenticationRequest = null;
					}
					if (provider.Request.IsResponseReady) {
						provider.Request.Response.Send();
						Page.Response.End();
						PendingAuthenticationRequest = null;
					}
				}
			}
		}

		/// <summary>
		/// Fired when an incoming OpenID request is an authentication challenge
		/// that must be responded to by the Provider web site according to its
		/// own user database and policies.
		/// </summary>
		public event EventHandler<AuthenticationChallengeEventArgs> AuthenticationChallenge;
		/// <summary>
		/// Fires the <see cref="AuthenticationChallenge"/> event.
		/// </summary>
		protected virtual void OnAuthenticationChallenge(IAuthenticationRequest request) {
			var authenticationChallenge = AuthenticationChallenge;
			if (authenticationChallenge != null)
				authenticationChallenge(this, new AuthenticationChallengeEventArgs(request));
		}
	}

	/// <summary>
	/// The event arguments that include details of the incoming request.
	/// </summary>
	public class AuthenticationChallengeEventArgs : EventArgs {
		internal AuthenticationChallengeEventArgs(IAuthenticationRequest request) {
			Request = request;
		}
		/// <summary>
		/// The incoming authentication request.
		/// </summary>
		public IAuthenticationRequest Request { get; set; }
	}

}