// Copyright (c) .NET Foundation. 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.Globalization; using System.Net.Http; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Authentication.OAuth { /// /// An ASP.NET Core middleware for authenticating users using OAuth services. /// public class OAuthMiddleware : AuthenticationMiddleware where TOptions : OAuthOptions, new() { /// /// Initializes a new . /// /// The next middleware in the HTTP pipeline to invoke. /// /// /// The . /// The configuration options for this middleware. /// Configuration options for the middleware. public OAuthMiddleware( RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions sharedOptions, IOptions options) : base(next, options, loggerFactory, encoder) { if (next == null) { throw new ArgumentNullException(nameof(next)); } if (dataProtectionProvider == null) { throw new ArgumentNullException(nameof(dataProtectionProvider)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } if (encoder == null) { throw new ArgumentNullException(nameof(encoder)); } if (sharedOptions == null) { throw new ArgumentNullException(nameof(sharedOptions)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } // todo: review error handling if (string.IsNullOrEmpty(Options.AuthenticationScheme)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(Options.AuthenticationScheme))); } if (string.IsNullOrEmpty(Options.ClientId)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(Options.ClientId))); } if (string.IsNullOrEmpty(Options.ClientSecret)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(Options.ClientSecret))); } if (string.IsNullOrEmpty(Options.AuthorizationEndpoint)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(Options.AuthorizationEndpoint))); } if (string.IsNullOrEmpty(Options.TokenEndpoint)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(Options.TokenEndpoint))); } if (!Options.CallbackPath.HasValue) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(Options.CallbackPath))); } if (Options.Events == null) { Options.Events = new OAuthEvents(); } if (Options.StateDataFormat == null) { var dataProtector = dataProtectionProvider.CreateProtector( GetType().FullName, Options.AuthenticationScheme, "v1"); Options.StateDataFormat = new PropertiesDataFormat(dataProtector); } Backchannel = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler()); Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core OAuth middleware"); Backchannel.Timeout = Options.BackchannelTimeout; Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB if (string.IsNullOrEmpty(Options.SignInScheme)) { Options.SignInScheme = sharedOptions.Value.SignInScheme; } if (string.IsNullOrEmpty(Options.SignInScheme)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(Options.SignInScheme))); } } protected HttpClient Backchannel { get; private set; } /// /// Provides the object for processing authentication-related requests. /// /// An configured with the supplied to the constructor. protected override AuthenticationHandler CreateHandler() { return new OAuthHandler(Backchannel); } } }