Beispiel #1
0
            private BWebServiceResponse OnRequest_CreateTestUser(HttpListenerContext _Context, Action <string> _ErrorMessageAction)
            {
                string OptionalName        = BUtility.RandomString(12, true) + "_test";
                string EmailWithoutPostfix = OptionalName + "@test.com";

                var AccumulatedSSOMethodRightsOrDefault = new JArray()
                {
                    JObject.Parse(JsonConvert.SerializeObject(
                                      new AccessScope()
                    {
                        WildcardPath = "*",
                        AccessRights = new List <string>()
                        {
                            "GET", "POST", "PUT", "DELETE"
                        }
                    }))
                };

                if (!CreateUser(out string _UserID, EmailWithoutPostfix, _ErrorMessageAction, OptionalName))
                {
                    return(BWebResponse.InternalError("User creation process has been failed."));
                }

                if (!CreateAuthMethod(out string _ApiKey, _UserID, _ErrorMessageAction))
                {
                    return(BWebResponse.InternalError("Auth method creation process has been failed."));
                }

                if (!Controller_Rights_Internal.Get().GrantUserWithRights(false, _UserID, AccumulatedSSOMethodRightsOrDefault, _ErrorMessageAction))
                {
                    return(BWebResponse.InternalError("Grant user with rights process has been failed."));
                }

                return(BWebResponse.StatusCreated("User has been created.", new JObject()
                {
                    [UserDBEntry.KEY_NAME_USER_ID] = _UserID,
                    [AuthMethod.API_KEY_PROPERTY] = _ApiKey,
                    [AuthMethod.USER_EMAIL_PROPERTY] = EmailWithoutPostfix
                }));
            }
Beispiel #2
0
        private BWebServiceResponse CreateAccessMethodForUser(HttpListenerContext _Context, out bool _bSetClearanceForApiKey, out string _ApiKey, Action <string> _ErrorMessageAction)
        {
            _bSetClearanceForApiKey = false;
            _ApiKey = null;

            AuthMethod NewMethod = null;

            using (var InputStream = _Context.Request.InputStream)
            {
                using (var ResponseReader = new StreamReader(InputStream))
                {
                    try
                    {
                        NewMethod = JsonConvert.DeserializeObject <AuthMethod>(ResponseReader.ReadToEnd());
                    }
                    catch (Exception e)
                    {
                        _ErrorMessageAction?.Invoke("User_CreateListAccessMethods_ForUser->CreateAccessMethodForUser: Read request body stage has failed. Exception: " + e.Message + ", Trace: " + e.StackTrace);
                        return(BWebResponse.BadRequest("Malformed request body. Request must be a valid json form."));
                    }
                }
            }

            if (NewMethod == null)
            {
                return(BWebResponse.BadRequest("Request body does not contain all mandatory information or some fields are invalid."));
            }

            BPrimitiveType AuthMethodKey = null;

            if (NewMethod.Method == AuthMethod.Methods.USER_EMAIL_PASSWORD_METHOD)
            {
                if (NewMethod.UserEmail == null || NewMethod.PasswordMD5 == null || NewMethod.UserEmail.Length == 0 || NewMethod.PasswordMD5.Length == 0)
                {
                    return(BWebResponse.BadRequest("Request body does not contain all fields."));
                }
                AuthMethodKey = new BPrimitiveType(NewMethod.UserEmail + NewMethod.PasswordMD5);
            }
            else if (NewMethod.Method == AuthMethod.Methods.USER_NAME_PASSWORD_METHOD)
            {
                if (NewMethod.UserName == null || NewMethod.PasswordMD5 == null || NewMethod.UserName.Length == 0 || NewMethod.PasswordMD5.Length == 0)
                {
                    return(BWebResponse.BadRequest("Request body does not contain all fields."));
                }
                AuthMethodKey = new BPrimitiveType(NewMethod.UserName + NewMethod.PasswordMD5);
            }
            else if (NewMethod.Method == AuthMethod.Methods.API_KEY_METHOD)
            {
                int ExistenceTrial = 0;
                while (ExistenceTrial < 3)
                {
                    if (!BUtility.CalculateStringMD5(BUtility.RandomString(32, false), out NewMethod.ApiKey, _ErrorMessageAction))
                    {
                        return(BWebResponse.InternalError("Hashing error."));
                    }
                    NewMethod.ApiKey = NewMethod.ApiKey.ToUpper();

                    if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY + ":" + NewMethod.ApiKey, _ErrorMessageAction))
                    {
                        return(BWebResponse.InternalError("Atomic operation control has failed."));
                    }

                    if (!DatabaseService.UpdateItem(
                            UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(),
                            UniqueUserFieldsDBEntry.KEY_NAME_API_KEY,
                            new BPrimitiveType(NewMethod.ApiKey),
                            new JObject()
                    {
                        [UserDBEntry.KEY_NAME_USER_ID] = RequestedUserID
                    },
                            out JObject _,
                            EBReturnItemBehaviour.DoNotReturn,
                            DatabaseService.BuildAttributeNotExistCondition(UniqueUserFieldsDBEntry.KEY_NAME_API_KEY),
                            _ErrorMessageAction))
                    {
                        Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY + ":" + NewMethod.ApiKey, _ErrorMessageAction);
                        ExistenceTrial++;
                    }
                    else
                    {
                        _bSetClearanceForApiKey = true;
                        _ApiKey = NewMethod.ApiKey;
                        break;
                    }
                }
Beispiel #3
0
 public static bool GenerateUserID(out string _NewUserID, Action <string> _ErrorMessageAction)
 {
     return(BUtility.CalculateStringMD5(BUtility.RandomString(32, true), out _NewUserID, _ErrorMessageAction));
 }
Beispiel #4
0
        public static bool GenerateNonExistentUniqueID(
            WebServiceBaseTimeoutable _Request,
            IBDatabaseServiceInterface _DatabaseService,
            string _TableName,
            string _TableKeyName,
            string[] _TableEntryMustHaveProperties,
            EGetClearance _GetClearance,
            out string _GeneratedUniqueID,
            out BWebServiceResponse _FailureResponse,
            Action <string> _ErrorMessageAction = null)
        {
            _GeneratedUniqueID = null;
            _FailureResponse   = BWebResponse.InternalError("");

            int ExistenceTrial = 0;

            while (_GeneratedUniqueID == null && ExistenceTrial < 3)
            {
                if (!BUtility.CalculateStringMD5(BUtility.RandomString(32, false), out _GeneratedUniqueID, _ErrorMessageAction))
                {
                    _FailureResponse = BWebResponse.InternalError("Hashing operation has failed.");
                    return(false);
                }

                if (_GetClearance == EGetClearance.Yes && !Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(_Request.InnerProcessor, _TableName, _GeneratedUniqueID, _ErrorMessageAction))
                {
                    _FailureResponse = BWebResponse.InternalError("Atomic operation control has failed.");
                    return(false);
                }

                if (!_DatabaseService.GetItem(
                        _TableName,
                        _TableKeyName,
                        new BPrimitiveType(_GeneratedUniqueID),
                        _TableEntryMustHaveProperties,
                        out JObject ExistenceCheck,
                        _ErrorMessageAction))
                {
                    _FailureResponse = BWebResponse.InternalError("Database existence check operation has failed.");
                    return(false);
                }
                if (ExistenceCheck != null)
                {
                    if (_GetClearance == EGetClearance.Yes)
                    {
                        Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(_Request.InnerProcessor, _TableName, _GeneratedUniqueID, _ErrorMessageAction);
                    }

                    _GeneratedUniqueID = null;
                    ExistenceTrial++;
                }
                else
                {
                    break;
                }
            }
            if (_GeneratedUniqueID == null)
            {
                _FailureResponse = BWebResponse.InternalError("Unique model ID generation operation has failed.");
                return(false);
            }
            return(true);
        }
Beispiel #5
0
        private BWebServiceResponse OnRequest_Internal(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null)
        {
            if (!UrlParameters.TryGetValue("redirect_url", out string RedirectUrlEncoded) || RedirectUrlEncoded.Length == 0)
            {
                RedirectUrlEncoded = DEFAULT_REDIRECT_URL_ENCODED;
            }

            if (_Context.Request.HttpMethod != "GET")
            {
                _ErrorMessageAction?.Invoke("SSOLoginRequest: GET method is accepted. But received request method:  " + _Context.Request.HttpMethod);

                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, BWebResponse.Error_BadRequest_Code, "GET method is accepted. But received request method:  " + _Context.Request.HttpMethod));
            }

            if (!UrlParameters.TryGetValue("tenant", out string TenantName) || TenantName.Length == 0)
            {
                TenantName = DEFAULT_TENANT_NAME;
            }
            else
            {
                TenantName = TenantName.ToLower();
            }

            //Existing token from header
            string ClientAuthorization = null;

            if (BWebUtilities.DoesContextContainHeader(out List <string> ClientAuthorizationHeaderValues, out string _, _Context, "client-authorization"))
            {
                BUtility.CheckAndGetFirstStringFromList(ClientAuthorizationHeaderValues, out ClientAuthorization);
                if (ClientAuthorization != null && ClientAuthorization.Length == 0)
                {
                    ClientAuthorization = null;
                }
            }

            //Existing token from url parameters
            //Note: Must be token type prepended. Example: ?existing_token=bearer%20abc123123
            if (!UrlParameters.TryGetValue("existing_token", out string ExistingToken) || ExistingToken.Length == 0)
            {
                ExistingToken = null;
            }
            else
            {
                ExistingToken = WebUtility.UrlDecode(ExistingToken);
            }

            //If both existing tokens are non-null; it is error
            if (ClientAuthorization != null && ExistingToken != null)
            {
                _ErrorMessageAction?.Invoke("Error: SSOLoginRequest: Both existing tokens from url parameters and headers are non-null.");

                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, BWebResponse.Error_BadRequest_Code, "Both existing tokens from url parameters and headers are non-null."));
            }

            //From now on, use ClientAuthorization; not ExistingToken
            if (ExistingToken != null)
            {
                ClientAuthorization = ExistingToken;
            }

            //Check and try refresh if expired
            if (ClientAuthorization != null &&
                new Controller_SSOAccessToken(ClientAuthorization, DatabaseService, MemoryService, AzureAD_AppID, AzureAD_ClientSecret, SSOSuperAdmins, _ErrorMessageAction)
                .PerformCheckAndRefresh(
                    out Controller_SSOAccessToken.EPerformCheckAndRefreshSuccessStatus _,
                    out ClientAuthorization,
                    out string UserID,
                    out string _))
            {
                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), false, 0, null, UserID, ClientAuthorization));
            }

            //Get api passthrough endpoint from internal set state
            var LocalErrorString = "";

            if (!InternalSetState.GetValueFromMemoryService(
                    out string ApiPassthroughEndpoint,
                    InternalSetState.API_PASSTHROUGH_PUBLIC_ENDPOINT_PROPERTY,
                    MemoryService,
                    (string _Message) =>
            {
                LocalErrorString = _Message;
                _ErrorMessageAction?.Invoke(_Message);
            }))
            {
                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, 500, LocalErrorString));
            }

            string ServersideRedirectUrl = WebUtility.UrlEncode(ApiPassthroughEndpoint + "/auth/login/azure/callback");

            string AzureAuthenticationEndpointBase =
                "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
                + "?client_id=" + AzureAD_AppID
                + "&response_type=id_token code"
                + "&redirect_uri=" + ServersideRedirectUrl;

            var    TrialCount = 0;
            string SSOStateUniqueID;
            BMemoryQueryParameters SSOStateUniqueID_QueryParameters;

            do
            {
                if (!BUtility.CalculateStringMD5(BUtility.RandomString(32, true), out SSOStateUniqueID, _ErrorMessageAction))
                {
                    return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, 500, "SSO State ID generation has failed."));
                }

                SSOStateUniqueID_QueryParameters = SSOStateMEntry.ID_SSO_STATE_MEMORY_SERVICE_KEY(SSOStateUniqueID);

                if (!MemoryService.SetKeyValueConditionally(
                        SSOStateUniqueID_QueryParameters,
                        new Tuple <string, BPrimitiveType>(
                            SSOStateMEntry.HASH_KEY,
                            new BPrimitiveType(JsonConvert.SerializeObject(
                                                   new SSOStateMEntry()
                {
                    ServersideRedirectUrl = ServersideRedirectUrl,
                    TenantName = TenantName,
                    Status = SSOStateMEntry.STATUS_AUTHENTICATING
                })
                                               )
                            ),
                        _ErrorMessageAction))
                {
                    SSOStateUniqueID = null;
                }
            } while (SSOStateUniqueID == null && ++TrialCount < 5);

            if (SSOStateUniqueID == null)
            {
                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, 500, "Unique SSO State ID generation has failed."));
            }
            MemoryService.SetKeyExpireTime(SSOStateUniqueID_QueryParameters, TimeSpan.FromSeconds(120), _ErrorMessageAction);

            var AzureAuthenticationEndpoint = AzureAuthenticationEndpointBase
                                              + "&scope=" + SSOCommon.SCOPE_URL_ENCODED
                                              + "&response_mode=form_post"
                                              + "&nonce=" + SSOStateUniqueID
                                              + "&state="
                                              + WebUtility.UrlEncode(
                "redirect_url=" + RedirectUrlEncoded +
                "&tenant=" + TenantName +
                "&state=" + SSOStateUniqueID);

            return(SSOCommon.MakeCallerRedirected(AzureAuthenticationEndpoint, false, 0, null));
        }
Beispiel #6
0
        public bool CreateInstance(
            string _UniqueInstanceName,
            string _Description,
            string _MachineType,
            long _DiskSizeGB,
            int _GpuCount,
            string _GpuName,
            string _OSSourceImageURL,
            EBVMDiskType _DiskType,
            EBVMOSType _OSType,
            IDictionary <string, string> _Labels,
            BVMNetworkFirewall _FirewallSettings,
            string _OptionalStartupScript,
            out int _ErrorCode,
            Action <string> _ErrorMessageAction = null)
        {
            _ErrorCode = 400;

            if (!BUtility.CalculateStringMD5(BUtility.RandomString(32, true), out string RandomFirewallTag, _ErrorMessageAction))
            {
                _ErrorMessageAction?.Invoke("BVMServiceGC->CreateInstance: Firewall tag MD5 generation has failed.");
                return(false);
            }

            RandomFirewallTag = "a-" /*Has to start with a letter*/ + RandomFirewallTag;

            try
            {
                using (var Service = GetService())
                {
                    var NewInstance = new Instance()
                    {
                        Name               = _UniqueInstanceName,
                        Description        = _Description,
                        DeletionProtection = false,
                        Zone               = "projects/" + ProjectID + "/zones/" + ZoneName,
                        Labels             = _Labels,
                        MachineType        = "projects/" + ProjectID + "/zones/" + ZoneName + "/machineTypes/" + _MachineType,
                        Disks              = new List <AttachedDisk>()
                        {
                            new AttachedDisk()
                            {
                                AutoDelete       = true,
                                Boot             = true,
                                Kind             = "compute#attachedDisk",
                                DeviceName       = _UniqueInstanceName,
                                Mode             = "READ_WRITE",
                                InitializeParams = new AttachedDiskInitializeParams()
                                {
                                    SourceImage = _OSSourceImageURL,
                                    DiskType    = "projects/" + ProjectID + "/zones/" + ZoneName + "/diskTypes/" + (_DiskType == EBVMDiskType.SSD ? "pd-ssd" : "pd-standard"),
                                    DiskSizeGb  = _DiskSizeGB
                                },
                                Type = "PERSISTENT"
                            }
                        },
                        NetworkInterfaces = new List <NetworkInterface>()
                        {
                            new NetworkInterface()
                            {
                                AccessConfigs = new List <AccessConfig>()
                                {
                                    new AccessConfig()
                                    {
                                        Kind        = "compute#accessConfig",
                                        Name        = "External NAT",
                                        NetworkTier = "PREMIUM",
                                        Type        = "ONE_TO_ONE_NAT"
                                    }
                                },
                                Kind       = "compute#networkInterface",
                                Name       = "nic0",
                                Network    = "projects/" + ProjectID + "/global/networks/default",
                                Subnetwork = "projects/" + ProjectID + "/regions/" + ZoneName.Substring(0, ZoneName.LastIndexOf('-')) + "/subnetworks/default"
                            }
                        },
                        Tags = new Tags()
                        {
                            Items = new List <string>()
                            {
                                RandomFirewallTag
                            }
                        },
                        Metadata = new Metadata()
                        {
                            Kind  = "compute#metadata",
                            Items = new List <Metadata.ItemsData>()
                        },
                        ShieldedInstanceConfig = new ShieldedInstanceConfig()
                        {
                            EnableVtpm                = true,
                            EnableSecureBoot          = false,
                            EnableIntegrityMonitoring = true
                        },
                        Scheduling = new Scheduling()
                        {
                            AutomaticRestart  = true,
                            Preemptible       = false,
                            OnHostMaintenance = "TERMINATE"
                        }
                    };

                    if (_OptionalStartupScript != null)
                    {
                        NewInstance.Metadata.Items.Add(new Metadata.ItemsData()
                        {
                            Key   = _OSType == EBVMOSType.Linux ? "startup-script" : "windows-startup-script-ps1",
                            Value = _OptionalStartupScript
                        });
                    }

                    if (_GpuCount > 0)
                    {
                        if (NewInstance.GuestAccelerators == null)
                        {
                            NewInstance.GuestAccelerators = new List <AcceleratorConfig>();
                        }
                        NewInstance.GuestAccelerators.Add(
                            new AcceleratorConfig()
                        {
                            AcceleratorCount = _GpuCount,
                            AcceleratorType  = "projects/" + ProjectID + "/zones/" + ZoneName + "/acceleratorTypes/" + _GpuName
                        });
                    }

                    if (_OSType == EBVMOSType.Windows)
                    {
                        if (NewInstance.Disks[0].GuestOsFeatures == null)
                        {
                            NewInstance.Disks[0].GuestOsFeatures = new List <GuestOsFeature>();
                        }

                        if (!NewInstance.Disks[0].GuestOsFeatures.Any(Item => Item.Type == "VIRTIO_SCSI_MULTIQUEUE"))
                        {
                            NewInstance.Disks[0].GuestOsFeatures.Add(new GuestOsFeature()
                            {
                                Type = "VIRTIO_SCSI_MULTIQUEUE"
                            });
                        }

                        if (!NewInstance.Disks[0].GuestOsFeatures.Any(Item => Item.Type == "WINDOWS"))
                        {
                            NewInstance.Disks[0].GuestOsFeatures.Add(new GuestOsFeature()
                            {
                                Type = "WINDOWS"
                            });
                        }

                        if (!NewInstance.Disks[0].GuestOsFeatures.Any(Item => Item.Type == "MULTI_IP_SUBNET"))
                        {
                            NewInstance.Disks[0].GuestOsFeatures.Add(new GuestOsFeature()
                            {
                                Type = "MULTI_IP_SUBNET"
                            });
                        }

                        if (!NewInstance.Disks[0].GuestOsFeatures.Any(Item => Item.Type == "UEFI_COMPATIBLE"))
                        {
                            NewInstance.Disks[0].GuestOsFeatures.Add(new GuestOsFeature()
                            {
                                Type = "UEFI_COMPATIBLE"
                            });
                        }
                    }

                    var NewFirewall = new Firewall()
                    {
                        Kind         = "compute#firewall",
                        Name         = RandomFirewallTag,
                        Priority     = 1000,
                        Direction    = "INGRESS",
                        SelfLink     = "projects/" + ProjectID + "/global/firewalls/" + RandomFirewallTag,
                        Network      = "projects/" + ProjectID + "/global/networks/default",
                        SourceRanges = new List <string>(),
                        TargetTags   = new List <string>()
                        {
                            RandomFirewallTag
                        },
                        Allowed = new List <Firewall.AllowedData>()
                    };
                    if (_FirewallSettings.bOpenAll)
                    {
                        NewFirewall.Allowed.Add(new Firewall.AllowedData()
                        {
                            IPProtocol = "tcp"
                        });
                        NewFirewall.Allowed.Add(new Firewall.AllowedData()
                        {
                            IPProtocol = "udp"
                        });
                    }
                    else
                    {
                        foreach (var Current in _FirewallSettings.OpenPorts)
                        {
                            string[] OpenFor;
                            if (Current.OpenFor == BVMNetworkFirewall.EVMNetworkFirewallPortProtocol.TCP)
                            {
                                OpenFor = new string[] { "tcp" }
                            }
                            ;
                            else if (Current.OpenFor == BVMNetworkFirewall.EVMNetworkFirewallPortProtocol.UDP)
                            {
                                OpenFor = new string[] { "udp" }
                            }
                            ;
                            else
                            {
                                OpenFor = new string[] { "tcp", "udp" }
                            };

                            var PortList = new List <string>()
                            {
                                Current.FromPortInclusive + "-" + Current.ToPortInclusive
                            };
                            foreach (var OFor in OpenFor)
                            {
                                NewFirewall.Allowed.Add(new Firewall.AllowedData()
                                {
                                    IPProtocol = OFor,
                                    Ports      = PortList
                                });
                            }
                        }
                    }

                    var FirewallCreationResult = Service.Firewalls.Insert(NewFirewall, ProjectID).Execute();
                    if (FirewallCreationResult == null || (FirewallCreationResult.HttpErrorStatusCode.HasValue && FirewallCreationResult.HttpErrorStatusCode.Value >= 400))
                    {
                        _ErrorMessageAction?.Invoke("BVMServiceGC->CreateInstance: Firewall creation has failed: " + (FirewallCreationResult == null ? "Result is null." : FirewallCreationResult.HttpErrorMessage));
                        _ErrorCode = FirewallCreationResult.HttpErrorStatusCode.Value;
                        return(false);
                    }

                    var VMCreationResult = Service.Instances.Insert(NewInstance, ProjectID, ZoneName).Execute();
                    if (VMCreationResult == null || (VMCreationResult.HttpErrorStatusCode.HasValue && VMCreationResult.HttpErrorStatusCode.Value >= 400))
                    {
                        _ErrorMessageAction?.Invoke("BVMServiceGC->CreateInstance: VM creation has failed: " + (VMCreationResult == null ? "Result is null." : VMCreationResult.HttpErrorMessage));
                        _ErrorCode = VMCreationResult.HttpErrorStatusCode.Value;
                        return(false);
                    }
                }
            }
            catch (Exception e)
            {
                _ErrorMessageAction?.Invoke("BVMServiceGC->CreateInstance: " + e.Message + ", Trace: " + e.StackTrace);
                return(false);
            }
            return(true);
        }
Beispiel #7
0
        private BWebServiceResponse OnRequest_Internal(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null)
        {
            if (_Context.Request.HttpMethod != "POST")
            {
                _ErrorMessageAction?.Invoke("LoginRequest: POST method is accepted. But received request method:  " + _Context.Request.HttpMethod);
                return(BWebResponse.MethodNotAllowed("POST method is accepted. But received request method: " + _Context.Request.HttpMethod));
            }

            JObject ParsedBody;

            using (var InputStream = _Context.Request.InputStream)
            {
                using (var ResponseReader = new StreamReader(InputStream))
                {
                    try
                    {
                        ParsedBody = JObject.Parse(ResponseReader.ReadToEnd());
                    }
                    catch (Exception e)
                    {
                        _ErrorMessageAction?.Invoke("LoginRequest-> Read request body stage has failed. Exception: " + e.Message + ", Trace: " + e.StackTrace);
                        return(BWebResponse.BadRequest("Malformed request body. Request must be a valid json form."));
                    }
                }
            }

            if (!ParsedBody.ContainsKey(AuthMethod.API_KEY_PROPERTY) &&
                ((!ParsedBody.ContainsKey(AuthMethod.USER_NAME_PROPERTY) && !ParsedBody.ContainsKey(AuthMethod.USER_EMAIL_PROPERTY)) || !ParsedBody.ContainsKey(AuthMethod.PASSWORD_MD5_PROPERTY)))
            {
                _ErrorMessageAction?.Invoke("LoginRequest-> Request does not have required fields.");
                return(BWebResponse.BadRequest("Request does not have required fields."));
            }

            string Method;

            if (ParsedBody.ContainsKey(AuthMethod.API_KEY_PROPERTY))
            {
                var ApiKey = (string)ParsedBody[AuthMethod.API_KEY_PROPERTY];
                Method = ApiKey;
            }
            else
            {
                var PasswordMD5 = ((string)ParsedBody[AuthMethod.PASSWORD_MD5_PROPERTY]).ToLower();

                if (ParsedBody.ContainsKey(UserDBEntry.USER_NAME_PROPERTY))
                {
                    Method = (string)ParsedBody[UserDBEntry.USER_NAME_PROPERTY] + PasswordMD5;
                }
                else
                {
                    Method = ((string)ParsedBody[UserDBEntry.USER_EMAIL_PROPERTY]).ToLower() + PasswordMD5;
                }
            }

            if (!AuthenticationCommon.FetchUserInfoFromMemoryService_ByMethod(MemoryService, Method, out string UserID, out string _, out string _, _ErrorMessageAction))
            {
                if (!AuthenticationCommon.FetchUserInfoFromDatabaseService_ByMethod(DatabaseService, MemoryService, Method, out UserID, out _, out _, out BWebServiceResponse FailureResponse, _ErrorMessageAction))
                {
                    return(FailureResponse);
                }
            }

            if (!BUtility.CalculateStringMD5(BUtility.RandomString(32, true), out string AccessTokenMD5, _ErrorMessageAction))
            {
                return(BWebResponse.InternalError("Hash operation failed."));
            }

            var AccessTokenMD5WithTokenType = "Basic " + AccessTokenMD5;

            var QueryParameters = new BMemoryQueryParameters()
            {
                Domain     = Resources_DeploymentManager.Get().GetDeploymentBranchNameEscapedLoweredWithDash().ToUpper(),
                SubDomain  = "SELF_SIGNED_ACCESS_TOKEN_VALIDATION",
                Identifier = AccessTokenMD5WithTokenType
            };

            MemoryService.SetKeyValue(QueryParameters, new Tuple <string, BPrimitiveType>[]
            {
                new Tuple <string, BPrimitiveType>("method", new BPrimitiveType(Method))
            },
                                      _ErrorMessageAction);

            MemoryService.SetKeyExpireTime(QueryParameters, TimeSpan.FromHours(1), _ErrorMessageAction);

            return(BWebResponse.StatusOK("Login successful.", new JObject()
            {
                ["userId"] = UserID,
                ["token"] = AccessTokenMD5WithTokenType
            }));
        }