// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Net.Http; using Microsoft.AspNet.Builder; using Microsoft.AspNet.DataProtection; using Microsoft.AspNet.Security.DataHandler; using Microsoft.AspNet.Security.DataHandler.Encoder; using Microsoft.AspNet.Security.Infrastructure; using Microsoft.AspNet.Security.Twitter.Messages; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; namespace Microsoft.AspNet.Security.Twitter { /// /// ASP.NET middleware for authenticating users using Twitter /// [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Middleware are not disposable.")] public class TwitterAuthenticationMiddleware : AuthenticationMiddleware { private readonly ILogger _logger; private readonly HttpClient _httpClient; /// /// Initializes a /// /// The next middleware in the HTTP pipeline to invoke /// /// /// /// Configuration options for the middleware public TwitterAuthenticationMiddleware( RequestDelegate next, IServiceProvider services, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, IOptions externalOptions, IOptions options, ConfigureOptions configureOptions = null) : base(next, services, options, configureOptions) { if (string.IsNullOrWhiteSpace(Options.ConsumerSecret)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "ConsumerSecret")); } if (string.IsNullOrWhiteSpace(Options.ConsumerKey)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "ConsumerKey")); } _logger = loggerFactory.Create(typeof(TwitterAuthenticationMiddleware).FullName); if (Options.Notifications == null) { Options.Notifications = new TwitterAuthenticationNotifications(); } if (Options.StateDataFormat == null) { IDataProtector dataProtector = dataProtectionProvider.CreateProtector( typeof(TwitterAuthenticationMiddleware).FullName, Options.AuthenticationType, "v1"); Options.StateDataFormat = new SecureDataFormat( Serializers.RequestToken, dataProtector, TextEncodings.Base64Url); } if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType)) { Options.SignInAsAuthenticationType = externalOptions.Options.SignInAsAuthenticationType; } if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "SignInAsAuthenticationType")); } _httpClient = new HttpClient(ResolveHttpMessageHandler(Options)); _httpClient.Timeout = Options.BackchannelTimeout; _httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB _httpClient.DefaultRequestHeaders.Accept.ParseAdd("*/*"); _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Twitter middleware"); _httpClient.DefaultRequestHeaders.ExpectContinue = false; } /// /// Provides the object for processing authentication-related requests. /// /// An configured with the supplied to the constructor. protected override AuthenticationHandler CreateHandler() { return new TwitterAuthenticationHandler(_httpClient, _logger); } [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] private static HttpMessageHandler ResolveHttpMessageHandler(TwitterAuthenticationOptions options) { HttpMessageHandler handler = options.BackchannelHttpHandler ?? #if ASPNET50 new WebRequestHandler(); // If they provided a validator, apply it or fail. if (options.BackchannelCertificateValidator != null) { // Set the cert validate callback var webRequestHandler = handler as WebRequestHandler; if (webRequestHandler == null) { throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch); } webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate; } #else new WinHttpHandler(); #endif return handler; } } }