<commit_before>﻿using System;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using D2L.Security.OAuth2.Validation.AccessTokens;
using D2L.Security.OAuth2.Validation.Request;
using D2L.Security.WebApiAuth.Principal;
using SimpleLogInterface;

namespace D2L.Security.WebApiAuth.Handler {
	
	internal sealed class AuthenticationMessageHandler : DelegatingHandler {

		private readonly IRequestAuthenticator m_requestAuthenticator;
		private readonly ILog m_log;
		private readonly AuthenticationMode m_authenticationMode;
		private readonly HttpClient m_httpClient;

		private bool m_isDisposed = false;

		public AuthenticationMessageHandler(
			HttpConfiguration httpConfiguration,
			Uri authenticationEndpoint,
			bool verifyCsrf,
			ILogProvider logProvider
			) {

			InnerHandler = new HttpControllerDispatcher( httpConfiguration );
			m_authenticationMode = verifyCsrf ? AuthenticationMode.Full : AuthenticationMode.SkipXsrfValidation;

			m_httpClient = new HttpClient();
			IAccessTokenValidator accessTokenValidator = AccessTokenValidatorFactory.CreateRemoteValidator(
				m_httpClient,
				authenticationEndpoint
				);

			m_requestAuthenticator = RequestAuthenticatorFactory.Create( accessTokenValidator );

			m_log = logProvider.Get( typeof( AuthenticationMessageHandler ) );
		}

		protected override Task<HttpResponseMessage> SendAsync(
			HttpRequestMessage request,
			CancellationToken cancellationToken
			) {

			try {
				Authenticate( request );
			} catch( AuthenticationException ex ) {
				m_log.Warn( "Authentication failed", ex );
				return Task.FromResult( request.CreateResponse( HttpStatusCode.Unauthorized ) );
			} catch( Exception ex ) {
				m_log.Error( "An unknown error occurred during authentication", ex );
				return Task.FromResult( request.CreateResponse( HttpStatusCode.Unauthorized ) );
			}

			return base.SendAsync( request, cancellationToken );
		}

		protected override void Dispose( bool disposing ) {
			if( !m_isDisposed ) {
				if( disposing ) {
					m_httpClient.Dispose();
				}
				<commit_msg>Reference MSDN article on patterns for derived classes when the base class is Disposable<commit_after>﻿using System;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using D2L.Security.OAuth2.Validation.AccessTokens;
using D2L.Security.OAuth2.Validation.Request;
using D2L.Security.WebApiAuth.Principal;
using SimpleLogInterface;

namespace D2L.Security.WebApiAuth.Handler {
	
	internal sealed class AuthenticationMessageHandler : DelegatingHandler {

		private readonly IRequestAuthenticator m_requestAuthenticator;
		private readonly ILog m_log;
		private readonly AuthenticationMode m_authenticationMode;
		private readonly HttpClient m_httpClient;

		private bool m_isDisposed = false;

		public AuthenticationMessageHandler(
			HttpConfiguration httpConfiguration,
			Uri authenticationEndpoint,
			bool verifyCsrf,
			ILogProvider logProvider
			) {

			InnerHandler = new HttpControllerDispatcher( httpConfiguration );
			m_authenticationMode = verifyCsrf ? AuthenticationMode.Full : AuthenticationMode.SkipXsrfValidation;

			m_httpClient = new HttpClient();
			IAccessTokenValidator accessTokenValidator = AccessTokenValidatorFactory.CreateRemoteValidator(
				m_httpClient,
				authenticationEndpoint
				);

			m_requestAuthenticator = RequestAuthenticatorFactory.Create( accessTokenValidator );

			m_log = logProvider.Get( typeof( AuthenticationMessageHandler ) );
		}

		protected override Task<HttpResponseMessage> SendAsync(
			HttpRequestMessage request,
			CancellationToken cancellationToken
			) {

			try {
				Authenticate( request );
			} catch( AuthenticationException ex ) {
				m_log.Warn( "Authentication failed", ex );
				return Task.FromResult( request.CreateResponse( HttpStatusCode.Unauthorized ) );
			} catch( Exception ex ) {
				m_log.Error( "An unknown error occurred during authentication", ex );
				return Task.FromResult( request.CreateResponse( HttpStatusCode.Unauthorized ) );
			}

			return base.SendAsync( request, cancellationToken );
		}

		/// <summary>
		/// See https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=VS.100).aspx 
		/// (MSDN patterns for dealing with disposables; covers derived class scenarios.
		/// This is relevant because we're also inheriting from a disposable base class.)
		/// </summary>
		protected override void Dispose( bool disposing ) {
			if( !m_isDisposed ) {
				if( disposing ) {
					m_httpClient.Dispose();
				}
				
{'fraction_non_alphanumeric': 0.07641967489972556, 'fraction_numerical': 0.0035887692632467806, 'mean_word_length': 4.778048780487805, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6201587', 'n_tokens_mistral': 1482, 'n_tokens_neox': 1272, 'n_words': 311}