1
//-----------------------------------------------------------------------
2 // <copyright file="OpenIdProvider.cs" company="Andrew Arnott">
3 // Copyright (c) Andrew Arnott. All rights reserved.
5 //-----------------------------------------------------------------------
7 namespace DotNetOpenAuth
.OpenId
.Provider
{
9 using System
.ComponentModel
;
11 using DotNetOpenAuth
.Configuration
;
12 using DotNetOpenAuth
.Messaging
;
13 using DotNetOpenAuth
.Messaging
.Bindings
;
14 using DotNetOpenAuth
.OpenId
.ChannelElements
;
15 using DotNetOpenAuth
.OpenId
.Messages
;
18 /// Offers services for a web page that is acting as an OpenID identity server.
20 public sealed class OpenIdProvider
{
22 /// The name of the key to use in the HttpApplication cache to store the
23 /// instance of <see cref="StandardProviderApplicationStore"/> to use.
25 private const string ApplicationStoreKey
= "DotNetOpenAuth.OpenId.Provider.OpenIdProvider.ApplicationStore";
28 /// Backing field for the <see cref="SecuritySettings"/> property.
30 private ProviderSecuritySettings securitySettings
;
33 /// Initializes a new instance of the <see cref="OpenIdProvider"/> class.
35 public OpenIdProvider()
36 : this(DotNetOpenAuth
.Configuration
.ProviderSection
.Configuration
.ApplicationStore
.CreateInstance(HttpApplicationStore
)) {
40 /// Initializes a new instance of the <see cref="OpenIdProvider"/> class.
42 /// <param name="applicationStore">The application store to use. Cannot be null.</param>
43 public OpenIdProvider(IProviderApplicationStore applicationStore
)
44 : this(applicationStore
, applicationStore
) {
48 /// Initializes a new instance of the <see cref="OpenIdProvider"/> class.
50 /// <param name="associationStore">The association store to use. Cannot be null.</param>
51 /// <param name="nonceStore">The nonce store to use. Cannot be null.</param>
52 private OpenIdProvider(IAssociationStore
<AssociationRelyingPartyType
> associationStore
, INonceStore nonceStore
) {
53 ErrorUtilities
.VerifyArgumentNotNull(associationStore
, "associationStore");
54 ErrorUtilities
.VerifyArgumentNotNull(nonceStore
, "nonceStore");
56 this.Channel
= new OpenIdChannel(associationStore
, nonceStore
);
57 this.AssociationStore
= associationStore
;
58 this.SecuritySettings
= ProviderSection
.Configuration
.SecuritySettings
.CreateSecuritySettings();
62 /// Gets the standard state storage mechanism that uses ASP.NET's
63 /// HttpApplication state dictionary to store associations and nonces.
65 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
66 public static IProviderApplicationStore HttpApplicationStore
{
68 HttpContext context
= HttpContext
.Current
;
69 ErrorUtilities
.VerifyOperation(context
!= null, OpenIdStrings
.StoreRequiredWhenNoHttpContextAvailable
, typeof(IProviderApplicationStore
).Name
);
70 var store
= (IProviderApplicationStore
)context
.Application
[ApplicationStoreKey
];
72 context
.Application
.Lock();
74 if ((store
= (IProviderApplicationStore
)context
.Application
[ApplicationStoreKey
]) == null) {
75 context
.Application
[ApplicationStoreKey
] = store
= new StandardProviderApplicationStore();
78 context
.Application
.UnLock();
87 /// Gets the channel to use for sending/receiving messages.
89 public Channel Channel { get; internal set; }
92 /// Gets the security settings used by this Provider.
94 public ProviderSecuritySettings SecuritySettings
{
96 return this.securitySettings
;
100 ErrorUtilities
.VerifyArgumentNotNull(value, "value");
101 this.securitySettings
= value;
106 /// Gets the association store.
108 internal IAssociationStore
<AssociationRelyingPartyType
> AssociationStore { get; private set; }
111 /// Gets the web request handler to use for discovery and the part of
112 /// authentication where direct messages are sent to an untrusted remote party.
114 internal IDirectWebRequestHandler WebRequestHandler
{
115 get { return this.Channel.WebRequestHandler; }
119 /// Gets the incoming OpenID request if there is one, or null if none was detected.
121 /// <returns>The request that the hosting Provider should possibly process and then transmit the response for.</returns>
123 /// <para>Requests may be infrastructural to OpenID and allow auto-responses, or they may
124 /// be authentication requests where the Provider site has to make decisions based
125 /// on its own user database and policies.</para>
126 /// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
128 /// <exception cref="InvalidOperationException">Thrown if <see cref="HttpContext.Current">HttpContext.Current</see> == <c>null</c>.</exception>
129 /// <exception cref="ProtocolException">Thrown if the incoming message is recognized but deviates from the protocol specification irrecoverably.</exception>
130 public IRequest
GetRequest() {
131 return this.GetRequest(this.Channel
.GetRequestFromContext());
135 /// Gets the incoming OpenID request if there is one, or null if none was detected.
137 /// <param name="httpRequestInfo">The incoming HTTP request to extract the message from.</param>
139 /// The request that the hosting Provider should process and then transmit the response for.
140 /// Null if no valid OpenID request was detected in the given HTTP request.
143 /// Requests may be infrastructural to OpenID and allow auto-responses, or they may
144 /// be authentication requests where the Provider site has to make decisions based
145 /// on its own user database and policies.
147 /// <exception cref="ProtocolException">Thrown if the incoming message is recognized but deviates from the protocol specification irrecoverably.</exception>
148 public IRequest
GetRequest(HttpRequestInfo httpRequestInfo
) {
149 ErrorUtilities
.VerifyArgumentNotNull(httpRequestInfo
, "httpRequestInfo");
151 IDirectedProtocolMessage incomingMessage
= this.Channel
.ReadFromRequest(httpRequestInfo
);
152 if (incomingMessage
== null) {
156 var checkIdMessage
= incomingMessage
as CheckIdRequest
;
157 if (checkIdMessage
!= null) {
158 return new AuthenticationRequest(this, checkIdMessage
);
161 var checkAuthMessage
= incomingMessage
as CheckAuthenticationRequest
;
162 if (checkAuthMessage
!= null) {
163 return new AutoResponsiveRequest(this, incomingMessage
, new CheckAuthenticationResponse(checkAuthMessage
, this));
166 var associateMessage
= incomingMessage
as AssociateRequest
;
167 if (associateMessage
!= null) {
168 return new AutoResponsiveRequest(this, incomingMessage
, associateMessage
.CreateResponse(this.AssociationStore
));
171 throw ErrorUtilities
.ThrowProtocol(MessagingStrings
.UnexpectedMessageReceivedOfMany
);