private static void MakeQueryParameters(out BMemoryQueryParameters _QueryParameters, string _ItemKey) { _QueryParameters = new BMemoryQueryParameters(); _QueryParameters.Domain = "PODHEALTCHECK"; _QueryParameters.SubDomain = "LOCKER"; _QueryParameters.Identifier = _ItemKey; }
/// <summary> /// /// <para>Subscribe:</para> /// /// <para>Subscribes to given workspace [_QueryParameters.Domain]:[_QueryParameters.SubDomain]:[_QueryParameters.Identifier] topic</para> /// /// <para>Check <seealso cref="IBPubSubServiceInterface.Subscribe"/> for detailed documentation</para> /// /// </summary> public bool Subscribe(BMemoryQueryParameters _QueryParameters, Action <string, JObject> _OnMessage, Action <string> _ErrorMessageAction = null) { if (_OnMessage == null) { return(false); } string Topic = _QueryParameters.Domain + ":" + _QueryParameters.SubDomain + ":" + _QueryParameters.Identifier; return(CustomSubscribe(Topic, (string TopicParameter, string MessageParameter) => { JObject AsJson; try { AsJson = JObject.Parse(MessageParameter); } catch (Exception e) { AsJson = null; _ErrorMessageAction?.Invoke("BPubSubServiceAWS->Subscribe->Callback: " + e.Message + ", Trace: " + e.StackTrace); if (e.InnerException != null && e.InnerException != e) { _ErrorMessageAction?.Invoke("BPubSubServiceAWS->Subscribe->Callback->Inner: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace); } } if (AsJson != null) { _OnMessage?.Invoke(TopicParameter, AsJson); } }, _ErrorMessageAction)); }
/// <summary> /// /// <para>DeleteTopicGlobally:</para> /// /// <para>Deletes all messages and the topic of given workspace [_QueryParameters.Domain]:[_QueryParameters.SubDomain] topic</para> /// /// <para>Check <seealso cref="IBPubSubServiceInterface.DeleteTopicGlobally"/> for detailed documentation</para> /// /// </summary> public void DeleteTopicGlobally( BMemoryQueryParameters _QueryParameters, Action <string> _ErrorMessageAction = null) { string Topic = _QueryParameters.Domain + ":" + _QueryParameters.SubDomain + ":" + _QueryParameters.Identifier; DeleteCustomTopicGlobally(Topic, _ErrorMessageAction); }
private bool MakeQueryParameters(out BMemoryQueryParameters _QueryParameters, out string _PasswordMD5_FromAccessToken) { _QueryParameters = new BMemoryQueryParameters(); if (!BUtility.CalculateStringMD5(AccessToken_TokenTypeSpacePrepended, out _PasswordMD5_FromAccessToken, ErrorMessageAction)) { return(false); } _QueryParameters = MakeSSOQueryParameters(_PasswordMD5_FromAccessToken); return(true); }
/// <summary> /// /// <para>Publish:</para> /// /// <para>Publishes the given message to given workspace [_QueryParameters.Domain]:[_QueryParameters.SubDomain]:[_QueryParameters.Identifier] topic</para> /// /// <para>Check <seealso cref="IBPubSubServiceInterface.Publish"/> for detailed documentation</para> /// /// </summary> public bool Publish(BMemoryQueryParameters _QueryParameters, JObject _Message, Action <string> _ErrorMessageAction = null) { if (_Message == null) { return(false); } string Topic = _QueryParameters.Domain + ":" + _QueryParameters.SubDomain + ":" + _QueryParameters.Identifier; string Message = _Message.ToString(); return(CustomPublish(Topic, Message, _ErrorMessageAction)); }
private BWebServiceResponse OnRequest_Internal_Logic( JObject ParsedBody, Action <string> _ErrorMessageAction) { var ForUrlPath = (string)ParsedBody["forUrlPath"]; var RequestMethod = (string)ParsedBody["requestMethod"]; var SSOTokenRefreshStatus = Controller_SSOAccessToken.EPerformCheckAndRefreshSuccessStatus.None; var AccessTokenWithTokenType = (string)ParsedBody["authorization"]; string Method; if (AccessTokenWithTokenType.StartsWith("Basic")) { var QueryParameters = new BMemoryQueryParameters() { Domain = Resources_DeploymentManager.Get().GetDeploymentBranchNameEscapedLoweredWithDash().ToUpper(), SubDomain = "SELF_SIGNED_ACCESS_TOKEN_VALIDATION", Identifier = AccessTokenWithTokenType }; var MethodPrimitive = MemoryService.GetKeyValue(QueryParameters, "method", _ErrorMessageAction); if (MethodPrimitive == null) { return(BWebResponse.Unauthorized("Token is invalid. Please re-login.")); } Method = MethodPrimitive.AsString; } else { var AccessTokenManager = new Controller_SSOAccessToken(AccessTokenWithTokenType, DatabaseService, MemoryService, AzureAD_AppID, AzureAD_ClientSecret, SSOSuperAdmins, _ErrorMessageAction); if (AccessTokenManager.PerformCheckAndRefresh( out SSOTokenRefreshStatus, out AccessTokenWithTokenType, out _, out string _EmailAddressWithoutPostfix)) { ParsedBody["authorization"] = AccessTokenWithTokenType; }
private bool Perform_SecondLeg_Authorization( string _AuthorizationCode_From_FirstLeg, BMemoryQueryParameters _SSOStateUniqueID_QueryParameters, SSOStateMEntry _SSOState, out AuthorizationResult _SuccessResponse, out BWebServiceResponse _FailureResponse, Action <string> _ErrorMessageAction) { _SuccessResponse = null; _FailureResponse = BWebResponse.InternalError(""); _SSOState.Status = SSOStateMEntry.STATUS_AUTHORIZING; MemoryService.SetKeyValue(_SSOStateUniqueID_QueryParameters, new Tuple <string, BPrimitiveType>[] { new Tuple <string, BPrimitiveType>(SSOStateMEntry.HASH_KEY, new BPrimitiveType(JsonConvert.SerializeObject(_SSOState))) }, _ErrorMessageAction); MemoryService.SetKeyExpireTime(_SSOStateUniqueID_QueryParameters, TimeSpan.FromSeconds(120), _ErrorMessageAction); var FormUrlEncodedPairs = new List <KeyValuePair <string, string> >() { new KeyValuePair <string, string>("client_id", AzureAD_AppID), new KeyValuePair <string, string>("scope", SSOCommon.SCOPE), new KeyValuePair <string, string>("grant_type", "authorization_code"), new KeyValuePair <string, string>("code", _AuthorizationCode_From_FirstLeg), new KeyValuePair <string, string>("redirect_uri", WebUtility.UrlDecode(_SSOState.ServersideRedirectUrl)), new KeyValuePair <string, string>("client_secret", WebUtility.UrlDecode(AzureAD_ClientSecret)) }; using var Handler = new HttpClientHandler { SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, ServerCertificateCustomValidationCallback = (a, b, c, d) => true }; using var Client = new HttpClient(Handler); Client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); string ResponseString = null; try { using var RequestContent = new FormUrlEncodedContent(FormUrlEncodedPairs); using var RequestTask = Client.PostAsync("https://login.microsoftonline.com/common/oauth2/v2.0/token", RequestContent); RequestTask.Wait(); using var Response = RequestTask.Result; using var ResponseContent = Response.Content; using var ReadResponseTask = ResponseContent.ReadAsStringAsync(); ReadResponseTask.Wait(); ResponseString = ReadResponseTask.Result; if (!Response.IsSuccessStatusCode) { bool bJsonParseable = true; try { JObject.Parse(ResponseString); } catch (JsonReaderException) { bJsonParseable = false; } _FailureResponse = new BWebServiceResponse( (int)Response.StatusCode, new BStringOrStream(ResponseString), bJsonParseable ? "application/json" : "text/html"); return(false); } var Parsed = JObject.Parse(ResponseString); _SuccessResponse = new AuthorizationResult() { TokenType = (string)Parsed["token_type"], AccessToken = (string)Parsed["access_token"], ExpiresInSeconds = (int)Parsed["expires_in"], RefreshToken = (string)Parsed["refresh_token"] }; } catch (Exception e) { if (e.InnerException != null && e.InnerException != e) { _ErrorMessageAction?.Invoke("Error: SSOLoginCallback->Perform_SecondLeg_Authorization->Inner: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace); } if (e is AggregateException) { foreach (var Inner in (e as AggregateException).InnerExceptions) { _ErrorMessageAction?.Invoke("Error: SSOLoginCallback->Perform_SecondLeg_Authorization->Aggregate->Inner: " + Inner.Message + ", Trace: " + Inner.StackTrace); } } _ErrorMessageAction?.Invoke("Error: SSOLoginCallback->Perform_SecondLeg_Authorization: Authorization request failed. Response: " + ResponseString + ", message: " + e.Message + ", trace: " + e.StackTrace); _FailureResponse = BWebResponse.InternalError("Authorization request has failed."); return(false); } MemoryService.DeleteAllKeys(_SSOStateUniqueID_QueryParameters, true, _ErrorMessageAction); return(true); }
private bool Parse_FirstLeg_Authentication_Content( string _ResponseContent, out string _AuthorizationCode_From_FirstLeg, out BMemoryQueryParameters _SSOStateUniqueID_QueryParameters, out SSOStateMEntry _SSOState, out string _LocalRedirectUrl_From_FirstLeg, out string _EmailAddress_From_FirstLeg, out string _AzureADUniqueID_From_FirstLeg, out BWebServiceResponse _FailureResponse, Action <string> _ErrorMessageAction) { _AuthorizationCode_From_FirstLeg = null; _SSOStateUniqueID_QueryParameters = new BMemoryQueryParameters(); _SSOState = null; _LocalRedirectUrl_From_FirstLeg = null; _EmailAddress_From_FirstLeg = null; _AzureADUniqueID_From_FirstLeg = null; _FailureResponse = BWebResponse.InternalError(""); _ResponseContent = _ResponseContent.Trim(); //Handle error if (_ResponseContent.StartsWith("error=")) { var ErrorResponse = new JObject() { ["result"] = "failure" }; try { var ErrorFields = _ResponseContent.Split('&'); if (ErrorFields != null && ErrorFields.Length >= 2) { ErrorResponse["error"] = ErrorFields[0].Substring("error=".Length); ErrorResponse["message"] = ErrorFields[1].Substring("error_description=".Length); } } catch (Exception) { } _FailureResponse = BWebResponse.Unauthorized(ErrorResponse.ToString()); return(false); } //Normal flow var Splitted = _ResponseContent.Split('&'); if (Splitted == null || Splitted.Length < 3) { _FailureResponse = BWebResponse.BadRequest("Request body must contain all requested types. Split has failed."); return(false); } string IDToken = null; string StateField = null; for (var i = 0; i < Splitted.Length; i++) { if (Splitted[i].StartsWith("id_token=")) { IDToken = Splitted[i].Substring("id_token=".Length); } else if (Splitted[i].StartsWith("code=")) { _AuthorizationCode_From_FirstLeg = Splitted[i].Substring("code=".Length); } else if (Splitted[i].StartsWith("state=")) { StateField = WebUtility.UrlDecode(Splitted[i].Substring("state=".Length)); } } if (IDToken == null || _AuthorizationCode_From_FirstLeg == null || StateField == null) { _FailureResponse = BWebResponse.BadRequest("Request body must contain all requested types."); return(false); } Splitted = StateField.Split('&'); if (Splitted == null || Splitted.Length < 3) { _FailureResponse = BWebResponse.BadRequest("State field must contain all mandatory entries. Split has failed."); return(false); } bool bSSOStateUniqueID_QueryParameters_Set = false; string TenantName = null; for (var i = 0; i < Splitted.Length; i++) { if (Splitted[i].StartsWith("redirect_url=")) { _LocalRedirectUrl_From_FirstLeg = WebUtility.UrlDecode(Splitted[i].Substring("redirect_url=".Length)); } else if (Splitted[i].StartsWith("tenant=")) { TenantName = Splitted[i].Substring("tenant=".Length); } else if (Splitted[i].StartsWith("state=")) { _SSOStateUniqueID_QueryParameters = SSOStateMEntry.ID_SSO_STATE_MEMORY_SERVICE_KEY(Splitted[i].Substring("state=".Length)); bSSOStateUniqueID_QueryParameters_Set = true; } } if (_LocalRedirectUrl_From_FirstLeg == null || TenantName == null || !bSSOStateUniqueID_QueryParameters_Set) { _FailureResponse = BWebResponse.BadRequest("State field must contain all mandatory entries."); return(false); } var Serialized = MemoryService.GetKeyValue(_SSOStateUniqueID_QueryParameters, SSOStateMEntry.HASH_KEY, _ErrorMessageAction); if (Serialized == null) { _FailureResponse = BWebResponse.Unauthorized("Login prompt session has expired. Please try again."); return(false); } try { _SSOState = JsonConvert.DeserializeObject <SSOStateMEntry>(Serialized.AsString); if (_SSOState == null) { throw new NullReferenceException(); } } catch (Exception e) { _ErrorMessageAction?.Invoke("Error: SSOLoginCallback->Parse_FirstLeg_Authentication_Content: Invalid session state. Message: " + e.Message + ", trace: " + e.StackTrace); _FailureResponse = BWebResponse.InternalError("Invalid session state. Please try again."); return(false); } if (_SSOState.Status != SSOStateMEntry.STATUS_AUTHENTICATING) { _FailureResponse = BWebResponse.Unauthorized("Invalid SSO state. Please try again."); return(false); } if (TenantName != _SSOState.TenantName) { _FailureResponse = BWebResponse.Unauthorized("SSO state - request tenant mismatch. Please try again."); return(false); } var JWTHandler = new JwtSecurityTokenHandler(); JwtSecurityToken Token = null; try { Token = JWTHandler.ReadJwtToken(IDToken); } catch (Exception e) { _ErrorMessageAction?.Invoke("Error: SSOLoginCallback->Parse_FirstLeg_Authentication_Content: Invalid JWT token. Token: " + IDToken + ", message: " + e.Message + ", trace: " + e.StackTrace); _FailureResponse = BWebResponse.BadRequest("Invalid JWT token."); return(false); } if (!Token.Payload.TryGetValue("email", out object EmailObject)) { _FailureResponse = BWebResponse.BadRequest("JWT token does not contain email in the payload."); return(false); } _EmailAddress_From_FirstLeg = ((string)EmailObject).ToLower(); if (!Token.Payload.TryGetValue("sub", out object AzureADUserUniqueIDObject)) { _FailureResponse = BWebResponse.BadRequest("JWT token does not contain sub in the payload."); return(false); } _AzureADUniqueID_From_FirstLeg = ((string)AzureADUserUniqueIDObject).ToLower(); return(true); }
public void SetMemoryService(IBMemoryServiceInterface _MemoryService, BMemoryQueryParameters _QueryParameters) { MemoryService = _MemoryService; QueryParameters = _QueryParameters; }
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 })); }
public static bool IsTokenExpiredOrInvalid(out Dictionary <string, BPrimitiveType> _Result, IBMemoryServiceInterface _MemoryService, BMemoryQueryParameters _QueryParameters, Action <string> _ErrorMessageAction) { _Result = _MemoryService.GetKeysValues(_QueryParameters, new List <string>() { UserDBEntry.KEY_NAME_USER_ID, "refresh_token", "expires_at" }, _ErrorMessageAction); if (_Result == null) { return(true); } if (!_Result.ContainsKey(UserDBEntry.KEY_NAME_USER_ID) || !_Result.ContainsKey("refresh_token") || !_Result.ContainsKey("expires_at")) { var DebugString = ""; foreach (var Returned in _Result) { DebugString += Returned.Key + "->" + Returned.Value.ToString(); } _ErrorMessageAction?.Invoke("Error: Controller_SSOAccessToken->IsTokenExpiredOrInvalid: MemoryService.GetKeysValues did not return all mandatory fields. Deleting the entry. Returned: " + DebugString); _MemoryService.DeleteAllKeys(_QueryParameters, true, _ErrorMessageAction); _Result = null; return(true); } if (_Result["expires_at"].AsInteger <= new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds()) { return(true); } return(false); }