diff options
Diffstat (limited to 'samples/OpenIdOfflineProvider/HostedProvider.cs')
-rw-r--r-- | samples/OpenIdOfflineProvider/HostedProvider.cs | 127 |
1 files changed, 85 insertions, 42 deletions
diff --git a/samples/OpenIdOfflineProvider/HostedProvider.cs b/samples/OpenIdOfflineProvider/HostedProvider.cs index 7a8cf01..3d50dd9 100644 --- a/samples/OpenIdOfflineProvider/HostedProvider.cs +++ b/samples/OpenIdOfflineProvider/HostedProvider.cs @@ -9,9 +9,11 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { using System.Collections.Generic; using System.Diagnostics.Contracts; using System.IO; + using System.Linq; using System.Net; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId.Provider; + using log4net; /// <summary> /// The OpenID Provider host. @@ -25,17 +27,12 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { /// <summary> /// The path to the OP Identifier. /// </summary> - private const string OPIdentifier = "/"; + private const string OPIdentifierPath = "/"; /// <summary> - /// The path to the user identity page that always generates a positive assertion. + /// The URL path with which all user identities must start. /// </summary> - private const string YesIdentity = "/user"; - - /// <summary> - /// The path to the user identity page that always generates a negative response. - /// </summary> - private const string NoIdentity = "/no"; + private const string UserIdentifierPath = "/user/"; /// <summary> /// The <see cref="OpenIdProvider"/> instance that processes incoming requests. @@ -51,8 +48,6 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { /// Initializes a new instance of the <see cref="HostedProvider"/> class. /// </summary> internal HostedProvider() { - this.AffirmativeIdentities = new HashSet<Uri>(); - this.NegativeIdentitities = new HashSet<Uri>(); } /// <summary> @@ -66,14 +61,16 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { } /// <summary> - /// Gets a collection of identity URLs that always produce positive assertions. + /// Gets the <see cref="OpenIdProvider"/> instance that processes incoming requests. /// </summary> - internal ICollection<Uri> AffirmativeIdentities { get; private set; } + internal OpenIdProvider Provider { + get { return this.provider; } + } /// <summary> - /// Gets a collection of identity URLs that always produce cancellation responses. + /// Gets or sets the delegate that handles authentication requests. /// </summary> - internal ICollection<Uri> NegativeIdentitities { get; private set; } + internal Action<HttpRequestInfo, HttpListenerResponse> ProcessRequest { get; set; } /// <summary> /// Gets the provider endpoint. @@ -86,6 +83,26 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { } /// <summary> + /// Gets the base URI that all user identities must start with. + /// </summary> + internal Uri UserIdentityPageBase { + get { + Contract.Requires(this.IsRunning); + return new Uri(this.httpHost.BaseUri, UserIdentifierPath); + } + } + + /// <summary> + /// Gets the OP identifier. + /// </summary> + internal Uri OPIdentifier { + get { + Contract.Requires(this.IsRunning); + return new Uri(this.httpHost.BaseUri, OPIdentifierPath); + } + } + + /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { @@ -98,8 +115,6 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { internal void StartProvider() { Contract.Ensures(this.IsRunning); this.httpHost = HttpHost.CreateHost(this.RequestHandler); - this.AffirmativeIdentities.Add(new Uri(this.httpHost.BaseUri, YesIdentity)); - this.NegativeIdentitities.Add(new Uri(this.httpHost.BaseUri, NoIdentity)); } /// <summary> @@ -138,8 +153,8 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { /// <param name="providerEndpoint">The provider endpoint.</param> /// <param name="localId">The local id.</param> /// <returns>The HTML document to return to the RP.</returns> - private static string GenerateHtmlDiscoveryDocument(string providerEndpoint, string localId) { - Contract.Requires(providerEndpoint != null && providerEndpoint.Length > 0); + private static string GenerateHtmlDiscoveryDocument(Uri providerEndpoint, string localId) { + Contract.Requires(providerEndpoint != null); const string DelegatedHtmlDiscoveryFormat = @"<html><head> <link rel=""openid.server"" href=""{0}"" /> @@ -155,51 +170,79 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { return string.Format( localId != null ? DelegatedHtmlDiscoveryFormat : NonDelegatedHtmlDiscoveryFormat, - providerEndpoint, + providerEndpoint.AbsoluteUri, localId); } /// <summary> + /// Generates the OP Identifier XRDS document. + /// </summary> + /// <param name="providerEndpoint">The provider endpoint.</param> + /// <param name="supportedExtensions">The supported extensions.</param> + /// <returns>The content of the XRDS document.</returns> + private static string GenerateXrdsOPIdentifierDocument(Uri providerEndpoint, IEnumerable<string> supportedExtensions) { + Contract.Requires(providerEndpoint != null); + Contract.Requires(supportedExtensions != null); + + const string OPIdentifierDiscoveryFormat = @"<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> + {1} + <URI>{0}</URI> + </Service> + </XRD> +</xrds:XRDS>"; + + string extensions = string.Join( + "\n\t\t\t", + supportedExtensions.Select(ext => "<Type>" + ext + "</Type>").ToArray()); + return string.Format( + OPIdentifierDiscoveryFormat, + providerEndpoint.AbsoluteUri, + extensions); + } + + /// <summary> /// Handles incoming HTTP requests. /// </summary> /// <param name="context">The HttpListener context.</param> private void RequestHandler(HttpListenerContext context) { Contract.Requires(context != null); Contract.Requires(context.Response.OutputStream != null); + Contract.Requires(this.ProcessRequest != null); Stream outputStream = context.Response.OutputStream; Contract.Assume(outputStream != null); // CC static verification shortcoming. + UriBuilder providerEndpointBuilder = new UriBuilder(); + providerEndpointBuilder.Scheme = Uri.UriSchemeHttp; + providerEndpointBuilder.Host = "localhost"; + providerEndpointBuilder.Port = context.Request.Url.Port; + providerEndpointBuilder.Path = ProviderPath; + Uri providerEndpoint = providerEndpointBuilder.Uri; + if (context.Request.Url.AbsolutePath == ProviderPath) { HttpRequestInfo requestInfo = new HttpRequestInfo(context.Request); - IRequest providerRequest = this.provider.GetRequest(requestInfo); - if (providerRequest == null) { - App.Logger.Error("A request came in that did not carry an OpenID message."); - context.Response.StatusCode = (int)HttpStatusCode.BadRequest; - using (StreamWriter sw = new StreamWriter(outputStream)) { - sw.WriteLine("<html><body>This is an OpenID Provider endpoint.</body></html>"); - } - return; - } - - if (!providerRequest.IsResponseReady) { - var authRequest = providerRequest as IAuthenticationRequest; - if (authRequest.IsDirectedIdentity) { - throw new NotImplementedException(); - } - - authRequest.IsAuthenticated = new Uri(authRequest.ClaimedIdentifier).AbsolutePath == YesIdentity; - } - - this.provider.PrepareResponse(providerRequest).Send(context.Response); - } else if (context.Request.Url.AbsolutePath == YesIdentity || context.Request.Url.AbsolutePath == NoIdentity) { + this.ProcessRequest(requestInfo, context.Response); + } else if (context.Request.Url.AbsolutePath.StartsWith(UserIdentifierPath, StringComparison.Ordinal)) { using (StreamWriter sw = new StreamWriter(outputStream)) { - string providerEndpoint = string.Format("http://localhost:{0}{1}", context.Request.Url.Port, ProviderPath); + context.Response.StatusCode = (int)HttpStatusCode.OK; + string localId = null; // string.Format("http://localhost:{0}/user", context.Request.Url.Port); string html = GenerateHtmlDiscoveryDocument(providerEndpoint, localId); sw.WriteLine(html); } - + context.Response.OutputStream.Close(); + } else if (context.Request.Url == this.OPIdentifier) { + context.Response.ContentType = "application/xrds+xml"; context.Response.StatusCode = (int)HttpStatusCode.OK; + App.Logger.Info("Discovery on OP Identifier detected."); + using (StreamWriter sw = new StreamWriter(outputStream)) { + sw.Write(GenerateXrdsOPIdentifierDocument(providerEndpoint, Enumerable.Empty<string>())); + } context.Response.OutputStream.Close(); } else { context.Response.StatusCode = (int)HttpStatusCode.NotFound; |