/// <summary> /// Determine if the request is within throttling limits on this server. /// </summary> /// <param name="authModule">The authentication module instance to use to authenticate the user for the operation.</param> /// <param name="operation">The operation that is being requested.</param> /// <returns>An errordetail instance holding any error that was encountered, or null if no errors were encountered.</returns> private static errordetail ValidateThrottleForUser(OttaMattaAuthentication authModule, string operation) { errordetail result = null; // // Todo: apply throttling limits // return(result); }
/// <summary> /// Validate whether the user is authenticated and whether the user is authorized for this operation. /// </summary> /// <remarks> /// This function will not return if the request is invalid. An error is thrown and the appropriate response returned to the client. /// If this function does return, the request can safely be considered valid. /// </remarks> public static void Validate() { // // Variables required for authentication and authorization. // System.ServiceModel.Web.IncomingWebRequestContext context = System.ServiceModel.Web.WebOperationContext.Current.IncomingRequest; errordetail currentException = null; AuthenticationConfig auth = AuthenticationConfig.Instance; WebHeaderCollection headers = null; string ipAddress = string.Empty; string operation = string.Empty; bool isSSL = false; AuthenticationMethod operationAuthenticationMethod = AuthenticationMethod.Unknown; bool opRequiresCredentials = true; OttaMattaAuthentication authModule = null; // // Test for credentials // currentException = GatherBasicInfo(context, out headers, out operation, out isSSL); if (currentException == null) { currentException = GetCredentialStatus(auth, operation, out opRequiresCredentials, out operationAuthenticationMethod); } // // Validate SSL status // if (currentException == null) { currentException = ValidateSSLStatus(auth, operation, isSSL, operationAuthenticationMethod); } // // Authenticate the user // if (currentException == null) { currentException = ValidateAuthenticationCredentials(opRequiresCredentials, auth, context, operationAuthenticationMethod, out authModule); } // // Authorize the user for this operation // if (currentException == null) { currentException = AuthorizeUserForOperation(opRequiresCredentials, auth, authModule, operation); } // // Validate IP address // if (currentException == null) { currentException = AuthorizeIPAddressForUser(auth, authModule, operation, System.ServiceModel.OperationContext.Current); } // // Validate throttling // if (currentException == null) { currentException = ValidateThrottleForUser(authModule, operation); } // // Can't continue - return the response. // if (currentException != null) { throw new WebFaultException <errordetail>(currentException, currentException.statuscode); } }
/// <summary> /// For the request, get the credentials (if required) and determine if the user is authorized. /// </summary> /// <param name="opRequiresCredentials">Whether the operation requires credentials or not.</param> /// <param name="auth">An authentication configuration instance.</param> /// <param name="authModule">The authentication module instance to use to authenticate the user for the operation.</param> /// <param name="operation">The operation that is being requested.</param> /// <returns>An errordetail instance holding any error that was encountered, or null if no errors were encountered.</returns> private static errordetail AuthorizeUserForOperation(bool opRequiresCredentials, AuthenticationConfig auth, OttaMattaAuthentication authModule, string operation) { errordetail result = null; if (opRequiresCredentials) { // // UID and PW good. Authorize the user for this operation // bool userAllowed = false; if (auth.UserAllowedOperations.ContainsKey(authModule.Username)) { userAllowed = auth.UserAllowedOperations[authModule.Username].Contains(operation); } if (!userAllowed) { result = new errordetail(string.Format("Operation \"{0}\" not authorized for user \"{1}\"", operation, authModule.Username), HttpStatusCode.Forbidden); } } return(result); }
/// <summary> /// For the request, determine if the requestor's IP address is valid. /// </summary> /// <param name="auth">An authentication configuration instance.</param> /// <param name="authModule">The authentication module instance to use to authenticate the user for the operation.</param> /// <param name="operation">The operation that is being requested.</param> /// <param name="opContext">The OperationContext for the request (note: this is not the WebOperationContext used for other calls).</param> /// <returns>An errordetail instance holding any error that was encountered, or null if no errors were encountered.</returns> private static errordetail AuthorizeIPAddressForUser(AuthenticationConfig auth, OttaMattaAuthentication authModule, string operation, System.ServiceModel.OperationContext opContext) { errordetail result = null; const string endpointPropertyName = "System.ServiceModel.Channels.RemoteEndpointMessageProperty"; bool failIfNoIP = false; System.ServiceModel.Channels.MessageProperties properties = opContext.IncomingMessageProperties; if (properties.ContainsKey(endpointPropertyName)) { RemoteEndpointMessageProperty endpoint = properties[endpointPropertyName] as RemoteEndpointMessageProperty; // // Note: on local dev machines this is the IPv6 address, like "fe80::c513:967d:1b57:8c33%11". // string ipAddress = endpoint.Address; // // We have an IP address. Let's see if it's authorized for this user. // if (authModule != null && auth.UserAllowedIps.ContainsKey(authModule.Username)) { bool ipOK = auth.UserAllowedIps[authModule.Username].Contains(ipAddress); if (!ipOK) { result = new errordetail(string.Format("The IP address \"{0}\" is not authorized for user account \"{1}\"", ipAddress, authModule.Username), HttpStatusCode.Forbidden); } } else { // // There are no IP address restrictions for this account. // } } else { // // Can't get the remote IP from the system. We can assume that something has changed in the WCF .NET codebase, and allow it for now. // Or, we can fail the request. // if (failIfNoIP) { result = new errordetail("Unable to determine request IP address", HttpStatusCode.InternalServerError); } } return(result); }
/// <summary> /// From the current context, determine if we have enough information to authenticate the user/request. /// </summary> /// <param name="opRequiresCredentials">Whether the operation requires credentials or not.</param> /// <param name="auth">An authentication configuration instance.</param> /// <param name="context">The server request context.</param> /// <param name="operationAuthenticationMethod">The authentication method required for the current operation.</param> /// <param name="authModule">(out) A authentication module that can be used to authenticate this user.</param> /// <returns>An errordetail instance holding any error that was encountered, or null if no errors were encountered.</returns> private static errordetail ValidateAuthenticationCredentials(bool opRequiresCredentials, AuthenticationConfig auth, System.ServiceModel.Web.IncomingWebRequestContext context, AuthenticationMethod operationAuthenticationMethod, out OttaMattaAuthentication authModule) { errordetail result = null; authModule = null; if (opRequiresCredentials) { if (operationAuthenticationMethod == AuthenticationMethod.Basic) { authModule = new BasicAuthentication(); } else { authModule = new DigestAuthentication(); } authModule.Context = context; authModule.Auth = auth; result = authModule.Authenticate(); } return(result); }