From 01fc038e5b76fa8f2737883e346df5ffb29f21e0 Mon Sep 17 00:00:00 2001 From: Anthony Lee Date: Tue, 7 Jul 2020 11:10:39 -0400 Subject: [PATCH 1/6] Fix Attachments and Get Subcribers --- apiClientDotNet/Clients/Constants/AgentConstants.cs | 6 ++---- apiClientDotNet/Clients/DatafeedClient.cs | 2 +- apiClientDotNet/Clients/MessageClient.cs | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/apiClientDotNet/Clients/Constants/AgentConstants.cs b/apiClientDotNet/Clients/Constants/AgentConstants.cs index c1d60e4..b90136b 100644 --- a/apiClientDotNet/Clients/Constants/AgentConstants.cs +++ b/apiClientDotNet/Clients/Constants/AgentConstants.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace apiClientDotNet.Clients.Constants { @@ -10,7 +8,7 @@ public class AgentConstants public static String READDATAFEED = "/agent/v4/datafeed/{id}/read"; public static String CREATEMESSAGE = "/agent/v4/stream/{sid}/message/create"; public static String GETMESSAGES = "/agent/v4/stream/{sid}/message"; - public static String GETATTACHMENT = "/v1/stream/{sid}/attachment"; + public static String GETATTACHMENT = "/agent/v1/stream/{sid}/attachment"; public static String SEARCHMESSAGES = "/agent/v1/message/search"; public static String MESSAGEIMPORT = "/agent/v4/message/import" ; @@ -22,7 +20,7 @@ public class AgentConstants public static String DELETESIGNAL = "/agent/v1/signals/{id}/delete"; public static String SUBSCRIBESIGNAL = "/agent/v1/signals/{id}/subscribe"; public static String UNSUBSCRIBESIGNAL = "/agent/v1/signals/{id}/unsubscribe"; - public static String GETSUBSCRIBERS = "/v1/signals/{id}/subscribers"; + public static String GETSUBSCRIBERS = "/agent/v1/signals/{id}/subscribers"; } } diff --git a/apiClientDotNet/Clients/DatafeedClient.cs b/apiClientDotNet/Clients/DatafeedClient.cs index cd25ee5..b41c20e 100644 --- a/apiClientDotNet/Clients/DatafeedClient.cs +++ b/apiClientDotNet/Clients/DatafeedClient.cs @@ -16,7 +16,7 @@ namespace apiClientDotNet { public class DatafeedClient { - List listeners = new List(); + List listeners = new List(); static HttpClient client = new HttpClient(); public Datafeed createDatafeed(SymConfig symConfig) diff --git a/apiClientDotNet/Clients/MessageClient.cs b/apiClientDotNet/Clients/MessageClient.cs index 0a3a9a9..b61ae57 100644 --- a/apiClientDotNet/Clients/MessageClient.cs +++ b/apiClientDotNet/Clients/MessageClient.cs @@ -82,7 +82,7 @@ public byte[] getAttachment(String streamId, String attachmentId, String message SymConfig symConfig = botClient.getConfig(); RestRequestHandler restRequestHandler = new RestRequestHandler(); - string url = CommonConstants.HTTPSPREFIX + symConfig.agentHost + ":" + symConfig.agentPort + AgentConstants.GETATTACHMENT.Replace("{sid}", streamId) + "?filedId=" + attachmentId + "&messageId=" + messageId; + string url = CommonConstants.HTTPSPREFIX + symConfig.agentHost + ":" + symConfig.agentPort + AgentConstants.GETATTACHMENT.Replace("{sid}", streamId) + "?fileId=" + attachmentId + "&messageId=" + messageId; HttpWebResponse resp = restRequestHandler.executeRequest(null, url, false, WebRequestMethods.Http.Get, symConfig, true); string body = restRequestHandler.ReadResponse(resp); From 3b3fdb264ec10dab270a35f883885db5d4ec5ba0 Mon Sep 17 00:00:00 2001 From: Anthony Lee Date: Wed, 26 Jan 2022 16:52:12 -0500 Subject: [PATCH 2/6] Add Firehose --- apiClientDotNet/Clients/SymBotClient.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apiClientDotNet/Clients/SymBotClient.cs b/apiClientDotNet/Clients/SymBotClient.cs index 5b65740..b85926f 100644 --- a/apiClientDotNet/Clients/SymBotClient.cs +++ b/apiClientDotNet/Clients/SymBotClient.cs @@ -15,6 +15,7 @@ public class SymBotClient : ISymClient private SymConfig config; private ISymAuth symBotAuth; private DatafeedEventsService datafeedEventsService; + private FirehoseEventsService firehostEventsService; private MessageClient messagesClient; private StreamClient streamClient; private PresenceClient presenceClient; @@ -57,6 +58,15 @@ public DatafeedEventsService getDatafeedEventsService() return datafeedEventsService; } + public FirehoseEventsService getFirehoseEventsService() + { + if (firehostEventsService == null) + { + firehostEventsService = new FirehoseEventsService(this); + } + return firehostEventsService; + } + public SymConfig getConfig() { return config; From 04d3d64af9829ac0bb6057eb1fe6df362ce898e8 Mon Sep 17 00:00:00 2001 From: Anthony Lee Date: Wed, 26 Jan 2022 16:52:29 -0500 Subject: [PATCH 3/6] Added Firehose --- apiClientDotNet/Clients/FirehoseClient.cs | 47 +++ apiClientDotNet/Models/Firehose.cs | 11 + .../Services/FirehoseEventsService.cs | 294 ++++++++++++++++++ 3 files changed, 352 insertions(+) create mode 100644 apiClientDotNet/Clients/FirehoseClient.cs create mode 100644 apiClientDotNet/Models/Firehose.cs create mode 100644 apiClientDotNet/Services/FirehoseEventsService.cs diff --git a/apiClientDotNet/Clients/FirehoseClient.cs b/apiClientDotNet/Clients/FirehoseClient.cs new file mode 100644 index 0000000..33ae85b --- /dev/null +++ b/apiClientDotNet/Clients/FirehoseClient.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text; +using apiClientDotNet.Models; +using apiClientDotNet.Models.Events; +using apiClientDotNet.Utils; +using apiClientDotNet.Listeners; +using System.Net; +using Newtonsoft.Json.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace apiClientDotNet +{ + public class FirehoseClient + { + List listeners = new List(); + static HttpClient client = new HttpClient(); + + public Firehose createFirehose(SymConfig symConfig) + { + Firehose firehose = new Firehose(); + RestRequestHandler restRequestHandler = new RestRequestHandler(); + string url = "https://" + symConfig.agentHost + ":" + symConfig.agentPort + "/agent/v4/firehose/create"; + HttpWebResponse resp = restRequestHandler.executeRequest(null, url, false, WebRequestMethods.Http.Post, symConfig, true); + string body = restRequestHandler.ReadResponse(resp); + resp.Close(); + JObject o = JObject.Parse(body); + firehose.firehoseId = (string)o["id"]; + return firehose; + } + + + public HttpWebResponse getEventsFromFirehose(SymConfig symConfig, Firehose firehose) + { + RestRequestHandler restRequestHandler = new RestRequestHandler(); + DatafeedEvent eventv4 = new DatafeedEvent(); + string url = "https://" + symConfig.agentHost + ":" + symConfig.agentPort + "/agent/v4/firehose/" + firehose.firehoseId + "/read"; + HttpWebResponse response = restRequestHandler.executeRequest(null, url, false, WebRequestMethods.Http.Get, symConfig, true); + return response; + } + + } + +} diff --git a/apiClientDotNet/Models/Firehose.cs b/apiClientDotNet/Models/Firehose.cs new file mode 100644 index 0000000..c2f4f15 --- /dev/null +++ b/apiClientDotNet/Models/Firehose.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace apiClientDotNet.Models +{ + public class Firehose + { + public string firehoseId { get; set; } + } +} diff --git a/apiClientDotNet/Services/FirehoseEventsService.cs b/apiClientDotNet/Services/FirehoseEventsService.cs new file mode 100644 index 0000000..fd71391 --- /dev/null +++ b/apiClientDotNet/Services/FirehoseEventsService.cs @@ -0,0 +1,294 @@ +using System; +using System.Collections.Generic; +using apiClientDotNet.Models; +using apiClientDotNet.Models.Events; +using apiClientDotNet.Listeners; +using apiClientDotNet.Utils; +using System.Net; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace apiClientDotNet.Services +{ + public class FirehoseEventsService + { + + static bool stopLoop = false; + private List roomListeners; + private List IMListeners; + private List connectionListeners; + private List elementsActionListeners; + private FirehoseClient firehoseClient; + private SymBotClient botClient; + public String firehoseId; + public Firehose firehose; + + public FirehoseEventsService(SymBotClient client) + { + this.botClient = client; + roomListeners = new List(); + IMListeners = new List(); + connectionListeners = new List(); + elementsActionListeners = new List(); + firehoseClient = new FirehoseClient(); + firehose = firehoseClient.createFirehose(client.getConfig()); + firehoseId = firehose.firehoseId; + + } + + public FirehoseClient init(SymConfig symConfig) + { + roomListeners = new List(); + IMListeners = new List(); + connectionListeners = new List(); + elementsActionListeners = new List(); + firehoseClient = new FirehoseClient(); + + return firehoseClient; + } + + public Firehose createFirehose(SymConfig symConfig, FirehoseClient firehoseClient) + { + Firehose firehose = firehoseClient.createFirehose(symConfig); + return firehose; + } + + public void stopGettingEventsFromFirehose() + { + stopLoop = true; + } + + public void getEventsFromFirehose() + { + List events = new List(); + while (!stopLoop) + { + events = RunAsync(botClient.getConfig(), firehose, firehoseClient).GetAwaiter().GetResult(); + if (events != null) + { + handleEvents(events); + } + } + } + + static async Task> RunAsync(SymConfig symConfig, Firehose firehose, FirehoseClient firehoseClient) + { + + List events = new List(); + try + { + events = await GetEventAsync(symConfig, firehose, firehoseClient); + return events; + } + catch (Exception e) + { + Console.WriteLine(e.Message); + return events; + } + + } + + static async Task> GetEventAsync(SymConfig symConfig, Firehose firehose, FirehoseClient firehoseClient) + { + RestRequestHandler restRequestHandler = new RestRequestHandler(); + HttpWebResponse response = firehoseClient.getEventsFromFirehose(symConfig, firehose); + List events = null; + if (response.StatusCode.Equals(HttpStatusCode.OK) || response.StatusCode.Equals(HttpStatusCode.Accepted)) + { + try + { + string body = restRequestHandler.ReadResponse(response); + events = JsonConvert.DeserializeObject>(body); + } + catch (JsonSerializationException e) + { + Console.WriteLine("The file could not be read:"); + Console.WriteLine(e.Message); + } + } + else if (response.StatusCode.Equals(HttpStatusCode.Forbidden) || response.StatusCode.Equals(HttpStatusCode.Unauthorized)) + { + //Add reauth + stopLoop = true; + } + else if (response.StatusCode.Equals(HttpStatusCode.BadRequest)) + { + stopLoop = true; + } + response.Close(); + return events; + } + + + + private void handleEvents(List firehoseEvents) + { + foreach (DatafeedEvent eventv4 in firehoseEvents) + { + if(eventv4.initiator.user.userId != botClient.getBotUserInfo().id) + { + switch (eventv4.type) + { + case "MESSAGESENT": + + MessageSent messageSent = eventv4.payload.messageSent; + if (messageSent.message.stream.streamType.Equals("ROOM")) + { + foreach (IRoomListener listener in roomListeners) + { + listener.onRoomMessage(messageSent.message); + } + } + else + { + foreach (IIMListener listener in IMListeners) + { + listener.onIMMessage(messageSent.message); + } + } + break; + case "INSTANTMESSAGECREATED": + + foreach (IIMListener listeners in IMListeners) + { + listeners.onIMCreated(eventv4.payload.instantMessageCreated.stream); + } + break; + + case "ROOMCREATED": + + foreach (IRoomListener listener in roomListeners) + { + listener.onRoomCreated(eventv4.payload.roomCreated); + } + break; + + case "ROOMUPDATED": + + foreach (IRoomListener listener in roomListeners) + { + listener.onRoomUpdated(eventv4.payload.roomUpdated); + } + break; + + case "ROOMDEACTIVATED": + + foreach (IRoomListener listener in roomListeners) + { + listener.onRoomDeactivated(eventv4.payload.roomDeactivated); + } + break; + + case "ROOMREACTIVATED": + + foreach (IRoomListener listener in roomListeners) + { + listener.onRoomReactivated(eventv4.payload.roomReactivated.stream); + } + break; + + case "USERJOINEDROOM": + + foreach (IRoomListener listener in roomListeners) + { + listener.onUserJoinedRoom(eventv4.payload.userJoinedRoom); + } + break; + + case "USERLEFTROOM": + + foreach (IRoomListener listener in roomListeners) + { + listener.onUserLeftRoom(eventv4.payload.userLeftRoom); + } + break; + + case "ROOMMEMBERPROMOTEDTOOWNER": + + foreach (IRoomListener listener in roomListeners) + { + listener.onRoomMemberPromotedToOwner(eventv4.payload.roomMemberPromotedToOwner); + } + break; + + case "ROOMMEMBERDEMOTEDFROMOWNER": + + foreach (IRoomListener listener in roomListeners) + { + listener.onRoomMemberDemotedFromOwner(eventv4.payload.roomMemberDemotedFromOwner); + } + break; + + case "CONNECTIONACCEPTED": + + foreach (IConnectionListener listener in connectionListeners) + { + listener.onConnectionAccepted(eventv4.payload.connectionAccepted.fromUser); + } + break; + + case "CONNECTIONREQUESTED": + + foreach (IConnectionListener listener in connectionListeners) + { + listener.onConnectionRequested(eventv4.payload.connectionRequested.toUser); + } + break; + + case "SYMPHONYELEMENTSACTION": + string streamId = eventv4.payload.symphonyElementsAction.stream.streamId.ToString(); + SymphonyElementsAction symphonyElementsAction = eventv4.payload.symphonyElementsAction; + User user = eventv4.initiator.user; + foreach (IElementsActionListener listener in elementsActionListeners) + { + listener.onFormMessage(user, streamId, symphonyElementsAction); + } + break; + default: + break; + } + } + } + } + + public void addRoomListener(IRoomListener listener) + { + roomListeners.Add(listener); + } + + public void removeRoomListener(IRoomListener listener) + { + roomListeners.Remove(listener); + } + + public void addIMListener(IIMListener listener) + { + IMListeners.Add(listener); + } + + public void removeIMListener(IIMListener listener) + { + IMListeners.Remove(listener); + } + + public void addConnectionsListener(IConnectionListener listener) + { + connectionListeners.Add(listener); + } + + public void removeConnectionsListener(IConnectionListener listener) + { + connectionListeners.Remove(listener); + } + + public void addElementsActionListener(IElementsActionListener listener) + { + elementsActionListeners.Add(listener); + } + + public void removeElementsActionListener(IElementsActionListener listener) + { + elementsActionListeners.Remove(listener); + } + } +} From b52661094a99f5183ca27832d440cc65d8b3cf51 Mon Sep 17 00:00:00 2001 From: Anthony Lee Date: Wed, 26 Jan 2022 16:57:18 -0500 Subject: [PATCH 4/6] Fixed Typo --- apiClientDotNet/Clients/SymBotClient.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apiClientDotNet/Clients/SymBotClient.cs b/apiClientDotNet/Clients/SymBotClient.cs index b85926f..ac78f9c 100644 --- a/apiClientDotNet/Clients/SymBotClient.cs +++ b/apiClientDotNet/Clients/SymBotClient.cs @@ -15,7 +15,7 @@ public class SymBotClient : ISymClient private SymConfig config; private ISymAuth symBotAuth; private DatafeedEventsService datafeedEventsService; - private FirehoseEventsService firehostEventsService; + private FirehoseEventsService firehoseEventsService; private MessageClient messagesClient; private StreamClient streamClient; private PresenceClient presenceClient; @@ -60,11 +60,11 @@ public DatafeedEventsService getDatafeedEventsService() public FirehoseEventsService getFirehoseEventsService() { - if (firehostEventsService == null) + if (firehoseEventsService == null) { - firehostEventsService = new FirehoseEventsService(this); + firehoseEventsService = new FirehoseEventsService(this); } - return firehostEventsService; + return firehoseEventsService; } public SymConfig getConfig() From be467579af2ac299c5214c33e19c629f9f479c64 Mon Sep 17 00:00:00 2001 From: Anthony Lee Date: Fri, 4 Mar 2022 09:09:46 -0500 Subject: [PATCH 5/6] Fixed OBO --- .../Authentication/AuthEndpointConstants.cs | 9 + apiClientDotNet/Authentication/SymAuthBase.cs | 160 ++++++++++++++++++ apiClientDotNet/Authentication/SymOBOAuth.cs | 86 ++++++---- .../Authentication/SymOBOUserAuth.cs | 127 ++++++-------- apiClientDotNet/Clients/SymOBOClient.cs | 15 +- apiClientDotNet/Utils/RequestProxyBuilder.cs | 24 +++ 6 files changed, 298 insertions(+), 123 deletions(-) create mode 100644 apiClientDotNet/Authentication/SymAuthBase.cs create mode 100644 apiClientDotNet/Utils/RequestProxyBuilder.cs diff --git a/apiClientDotNet/Authentication/AuthEndpointConstants.cs b/apiClientDotNet/Authentication/AuthEndpointConstants.cs index 3f18588..cf5ac72 100644 --- a/apiClientDotNet/Authentication/AuthEndpointConstants.cs +++ b/apiClientDotNet/Authentication/AuthEndpointConstants.cs @@ -15,5 +15,14 @@ public class AuthEndpointConstants public static String SESSIONAPPAUTH = "/sessionauth/v1/app/authenticate"; public static String OBOUSERAUTH = "/sessionauth/v1/app/user/{uid}/authenticate"; public static String OBOUSERAUTHUSERNAME = "/sessionauth/v1/app/username/{username}/authenticate"; + public const string HttpsPrefix = "https://"; + public const string SessionAuthPath = "/sessionauth/v1/authenticate"; + public const string KeyAuthPath = "/keyauth/v1/authenticate"; + public const string LogoutPath = "/sessionauth/v1/logout"; + public const string RsaSessionAuthPath = "/login/pubkey/authenticate"; + public const string RsaKeyManagerAuthPath = "/relay/pubkey/authenticate"; + public const string AppSessionAuthPath = "/sessionauth/v1/app/authenticate"; + public const string OboUserAuthByIdPath = "/login/pubkey/app/user/{uid}/authenticate"; + public const string OboUserAuthByUsernamePath = "/login/pubkey/app/username/{username}/authenticate"; } } diff --git a/apiClientDotNet/Authentication/SymAuthBase.cs b/apiClientDotNet/Authentication/SymAuthBase.cs new file mode 100644 index 0000000..ce59219 --- /dev/null +++ b/apiClientDotNet/Authentication/SymAuthBase.cs @@ -0,0 +1,160 @@ +using System; +using System.IO; +using System.Net.Http; +using System.Security.Cryptography.X509Certificates; +using apiClientDotNet.Models; +using apiClientDotNet.Utils; + +namespace apiClientDotNet.Authentication +{ + public abstract class SymAuthBase : ISymAuth + { + protected string SessionToken; + protected string KeyManagerToken; + protected SymConfig SymConfig; + private HttpClient SessionAuthClient; + private HttpClient KeyAuthClient; + private HttpClient CertificateSessionAuthClient; + private HttpClient CertificateKeyAuthClient; + private HttpClient CertificateOBOSessionAuthClient; + + protected HttpClient GetCertificateSessionAuthClient() { + if (CertificateSessionAuthClient == null) { + if (SymConfig.botCertPath != "" && SymConfig.botCertName != "") { + string botCertificatePath = SymConfig.botCertPath + SymConfig.botCertName; + if (!File.Exists(botCertificatePath) && File.Exists(botCertificatePath + ".p12")) { + botCertificatePath = botCertificatePath + ".p12"; + } + else { + throw new FileNotFoundException("File not found: " + botCertificatePath); + } + CertificateSessionAuthClient = CreateHttpClient(SymConfig.sessionAuthHost, SymConfig.sessionAuthPort, SymConfig.sessionProxyURL, SymConfig.sessionProxyUsername, SymConfig.sessionProxyPassword, botCertificatePath, SymConfig.botCertPassword); + } + else { + throw new MissingFieldException("botCertPath and botCertName not specified"); + } + } + return CertificateSessionAuthClient; + } + + protected HttpClient GetSessionAuthClient() { + if (SessionAuthClient == null) { + SessionAuthClient = CreateHttpClient(SymConfig.podHost, SymConfig.podPort, SymConfig.podProxyURL, SymConfig.podProxyUsername, SymConfig.podProxyPassword, null, null); + } + return SessionAuthClient; + } + + protected HttpClient GetCertificateKeyAuthClient(){ + if (CertificateKeyAuthClient == null) { + if (SymConfig.botCertPath != "" && SymConfig.botCertName != "") { + string botCertificatePath = SymConfig.botCertPath + SymConfig.botCertName; + if (!File.Exists(botCertificatePath) && File.Exists(botCertificatePath + ".p12")) { + botCertificatePath = botCertificatePath + ".p12"; + } + else { + throw new FileNotFoundException("File not found: " + botCertificatePath); + } + CertificateKeyAuthClient = CreateHttpClient(SymConfig.keyAuthHost, SymConfig.keyAuthPort, SymConfig.keyManagerProxyURL, SymConfig.keyManagerProxyUsername, SymConfig.keyManagerProxyPassword, botCertificatePath, SymConfig.botCertPassword); + } + else { + throw new MissingFieldException("botCertPath and botCertName not specified"); + } + } + return CertificateKeyAuthClient; + } + + protected HttpClient GetKeyAuthClient() { + if (KeyAuthClient == null) { + KeyAuthClient = CreateHttpClient(SymConfig.keyAuthHost, SymConfig.keyAuthPort, SymConfig.keyManagerProxyURL, SymConfig.keyManagerProxyUsername, SymConfig.keyManagerProxyPassword, null, null); + } + return KeyAuthClient; + } + + protected HttpClient GetCertificateOBOSessionAuthClient(){ + if (CertificateOBOSessionAuthClient == null) { + if (SymConfig.appCertPath != "" && SymConfig.appCertName != "") { + string appCertificatePath = SymConfig.appCertPath + SymConfig.appCertName; + if (!File.Exists(appCertificatePath) && File.Exists(appCertificatePath + ".p12")) { + appCertificatePath = SymConfig.appCertPath + SymConfig.appCertName + ".p12"; + } + else { + throw new FileNotFoundException("File not found: " + appCertificatePath); + } + CertificateOBOSessionAuthClient = CreateHttpClient(SymConfig.sessionAuthHost, SymConfig.sessionAuthPort, SymConfig.sessionProxyURL, SymConfig.sessionProxyUsername, SymConfig.sessionProxyPassword, appCertificatePath, SymConfig.appCertPassword); + } + else { + throw new MissingFieldException("appCertPath and appCertName not specified"); + } + } + return CertificateOBOSessionAuthClient; + } + + protected HttpClient GetOBOSessionAuthClient() { + return GetSessionAuthClient(); + } + + private HttpClient CreateHttpClient(string authUrl, int authPort, string proxyUrl, string proxyUsername, string proxyPassword, string certificatePath, string certificatePassword) { + var requestHandler = new HttpClientHandler(); + if (!string.IsNullOrEmpty(proxyUrl)) { + requestHandler.Proxy = RequestProxyBuilder.CreateWebProxy(proxyUrl, proxyUsername, proxyPassword); + } + else if (!string.IsNullOrEmpty(SymConfig.proxyURL)) { + requestHandler.Proxy = RequestProxyBuilder.CreateWebProxy(SymConfig.proxyURL, SymConfig.proxyUsername, SymConfig.proxyPassword); + } + if (certificatePath != null) { + var certificate = File.ReadAllBytes(certificatePath); + requestHandler.ClientCertificates.Add(new X509Certificate2(certificate, certificatePassword)); + } + var httpClient = new HttpClient(requestHandler); + httpClient.BaseAddress = new UriBuilder("https", authUrl, authPort).Uri; + return httpClient; + } + + public virtual string GetSessionToken() + { + return SessionToken; + } + + public string getSessionToken(){ + return GetSessionToken(); + } + + public virtual void SetSessionToken(string sessionToken) + { + SessionToken = sessionToken; + } + + public void setSessionToken(string sessionToken){ + SetSessionToken(sessionToken); + } + + public abstract void Authenticate(); + public void authenticate(){ + Authenticate(); + } + public abstract void SessionAuthenticate(); + public void sessionAuthenticate(){ + SessionAuthenticate(); + } + public abstract void KeyManagerAuthenticate(); + public void kmAuthenticate(){ + KeyManagerAuthenticate(); + } + public abstract string GetKeyManagerToken(); + public string getKmToken(){ + return GetKeyManagerToken(); + } + public abstract void SetKeyManagerToken(string kmToken); + public void setKmToken(string kmToken){ + SetKeyManagerToken (kmToken); + } + public abstract void Logout(); + public void logout(){ + Logout(); + } + + public SymConfig GetSymConfig() { + return SymConfig; + } + } +} \ No newline at end of file diff --git a/apiClientDotNet/Authentication/SymOBOAuth.cs b/apiClientDotNet/Authentication/SymOBOAuth.cs index bc6e163..a2338cf 100644 --- a/apiClientDotNet/Authentication/SymOBOAuth.cs +++ b/apiClientDotNet/Authentication/SymOBOAuth.cs @@ -1,57 +1,73 @@ using System; -using System.Collections.Generic; -using System.Text; using apiClientDotNet.Models; -using Newtonsoft.Json.Linq; -using apiClientDotNet.Utils; -using System.Net; +using System.Net.Http; +using Newtonsoft.Json; -namespace apiClientDotNet.Authentication + +namespace apiClientDotNet.Authentication { - public class SymOBOAuth + public class SymOBOAuth : SymAuthBase { - AuthTokens authTokens; - private String sessionToken; - private String kmToken; - private SymConfig symConfig; - - public SymOBOAuth(SymConfig config) + public string AppSessionToken + { + get { return SessionToken; } + set { SessionToken = value; } + } + + public SymOBOAuth(SymConfig config) { - symConfig = config; - authTokens = new AuthTokens(); + SymConfig = config; } - - public SymOBOUserAuth getUserAuth(String username) + public SymOBOUserAuth GetUserAuth(string username) { - SymOBOUserAuth userAuth = new SymOBOUserAuth(symConfig, username, this); - userAuth.authenticate(); - authTokens.sessionToken = userAuth.getSessionToken(); - sessionToken = userAuth.getSessionToken(); + SymOBOUserAuth userAuth = new SymOBOUserAuth(username, this); + userAuth.Authenticate(); return userAuth; } - public SymOBOUserAuth getUserAuth(long uid) + public SymOBOUserAuth GetUserAuth(long uid) { - SymOBOUserAuth userAuth = new SymOBOUserAuth(symConfig, - uid, this); - userAuth.authenticate(); + SymOBOUserAuth userAuth = new SymOBOUserAuth(uid, this); + userAuth.Authenticate(); return userAuth; } - public void sessionAppAuthenticate() + public override void SessionAuthenticate() + { + var response = GetCertificateOBOSessionAuthClient().PostAsync(AuthEndpointConstants.AppSessionAuthPath, null).Result; + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + SessionToken = JsonConvert.DeserializeObject(result).token; + } + else + { + SessionToken = null; + } + } + + public HttpClient GetAppAuthClient() { - RestRequestHandler restRequestHandler = new RestRequestHandler(); - string url = "https://" + symConfig.sessionAuthHost + ":" + symConfig.sessionAuthPort + AuthEndpointConstants.SESSIONAPPAUTH; - HttpWebResponse resp = restRequestHandler.executeRequest(null, url, true, WebRequestMethods.Http.Post, symConfig, false); - string body = restRequestHandler.ReadResponse(resp); - resp.Close(); - JObject o = JObject.Parse(body); - authTokens.sessionToken = (string)o["token"]; - sessionToken = authTokens.sessionToken; - symConfig.authTokens = authTokens; + return GetOBOSessionAuthClient(); } + public override void Authenticate() + { + SessionAuthenticate(); + } + public override void KeyManagerAuthenticate() {} + public override string GetKeyManagerToken() + { + return null; + } + + public override void SetKeyManagerToken(string kmToken) {} + + public override void Logout() + { + throw new NotImplementedException(); + } } } diff --git a/apiClientDotNet/Authentication/SymOBOUserAuth.cs b/apiClientDotNet/Authentication/SymOBOUserAuth.cs index 4d7dc94..d69a757 100644 --- a/apiClientDotNet/Authentication/SymOBOUserAuth.cs +++ b/apiClientDotNet/Authentication/SymOBOUserAuth.cs @@ -1,106 +1,79 @@ using System; -using System.Collections.Generic; -using System.Text; using apiClientDotNet.Models; -using Newtonsoft.Json.Linq; -using apiClientDotNet.Utils; -using System.Net; +using Newtonsoft.Json; +using System.Net.Http; namespace apiClientDotNet.Authentication { - public class SymOBOUserAuth : ISymAuth + public class SymOBOUserAuth : SymAuthBase { - AuthTokens authTokens; - private String sessionToken; - private SymConfig config; - private long uid; - private String username; - private SymOBOAuth appAuth; + public long UserId {get; private set;} + public String UserName {get; private set;} + private SymOBOAuth AppAuth; - public SymOBOUserAuth( SymConfig config, long uid, SymOBOAuth appAuth) + public SymOBOUserAuth(long uid, SymOBOAuth appAuth) { - this.config = config; - this.uid = uid; - this.appAuth = appAuth; - authTokens = config.authTokens; + UserId = uid; + AppAuth = appAuth; + SymConfig = appAuth.GetSymConfig(); + SymConfig.authTokens = new AuthTokens(); } - public SymOBOUserAuth( SymConfig config, String username, SymOBOAuth appAuth) + public SymOBOUserAuth(string username, SymOBOAuth appAuth) { - this.config = config; - this.username = username; - this.appAuth = appAuth; - authTokens = config.authTokens; + UserId = 0; + UserName = username; + AppAuth = appAuth; + SymConfig = appAuth.GetSymConfig(); + SymConfig.authTokens = new AuthTokens(); } - public void authenticate() - { - sessionAuthenticate(); - } - - public string getKmToken() - { - throw new NotImplementedException(); - } - - public string getSessionToken() - { - return sessionToken; - } - - public void kmAuthenticate() - { - throw new NotImplementedException(); + public override void Authenticate(){ + SessionAuthenticate(); } - public void sessionAuthenticate() + public override void SessionAuthenticate() { - if (uid != 0) + AppAuth.authenticate(); + string requestPath; + if (UserId != 0) { - RestRequestHandler restRequestHandler = new RestRequestHandler(); - string url = "https://" + config.sessionAuthHost + ":" + config.sessionAuthPort + AuthEndpointConstants.OBOUSERAUTH.Replace("{uid}", uid.ToString()); - HttpWebResponse resp = restRequestHandler.executeRequest(null, url, true, WebRequestMethods.Http.Post, config, false); - string body = restRequestHandler.ReadResponse(resp); - resp.Close(); - JObject o = JObject.Parse(body); - authTokens.sessionToken = (string)o["sessionToken"]; - sessionToken = authTokens.sessionToken; + requestPath = AuthEndpointConstants.OboUserAuthByIdPath.Replace("{uid}", UserId.ToString()); } - else + else { - RestRequestHandler restRequestHandler = new RestRequestHandler(); - string url = "https://" + config.sessionAuthHost + ":" + config.sessionAuthPort + AuthEndpointConstants.OBOUSERAUTHUSERNAME.Replace("{username}", username); - HttpWebResponse resp = restRequestHandler.executeRequest(null, url, true, WebRequestMethods.Http.Post, config, false); - string body = restRequestHandler.ReadResponse(resp); - resp.Close(); - JObject o = JObject.Parse(body); - authTokens.sessionToken = (string)o["sessionToken"]; - sessionToken = authTokens.sessionToken; - + requestPath = AuthEndpointConstants.OboUserAuthByUsernamePath.Replace("{username}", UserName); + } + var request = new HttpRequestMessage() { + RequestUri = new Uri( GetSessionAuthClient().BaseAddress + requestPath), + Method = HttpMethod.Post + }; + request.Headers.Add("sessionToken", AppAuth.GetSessionToken()); + var response = GetSessionAuthClient().SendAsync(request).Result; + if (response.IsSuccessStatusCode) + { + SessionToken = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result).token; + SymConfig.authTokens.sessionToken = SessionToken; + } + else + { + if (response.StatusCode == System.Net.HttpStatusCode.NotFound) { + throw new Exception("User Not Found."); + } + else throw new Exception("Unable to Authenticate"); } } - public void setKmToken(string kmToken) + public override void Logout() { - throw new NotImplementedException(); + var response = AppAuth.GetAppAuthClient().PostAsync(AuthEndpointConstants.LogoutPath, null).Result; } - public void setSessionToken(string sessionToken) - { - - this.sessionToken = sessionToken; - this.authTokens.sessionToken = sessionToken; + public override string GetKeyManagerToken(){ + return ""; } - public void logout() - { - RestRequestHandler restRequestHandler = new RestRequestHandler(); - string url = "https://" + config.sessionAuthHost + ":" + config.sessionAuthPort + AuthEndpointConstants.LOGOUTPATH; - HttpWebResponse resp = restRequestHandler.executeRequest(null, url, true, WebRequestMethods.Http.Post, config, false); - string body = restRequestHandler.ReadResponse(resp); - resp.Close(); - JObject o = JObject.Parse(body); - string message = (string)o["message"]; - } + public override void SetKeyManagerToken(string kmToken) {} + public override void KeyManagerAuthenticate() {} } } diff --git a/apiClientDotNet/Clients/SymOBOClient.cs b/apiClientDotNet/Clients/SymOBOClient.cs index 2016d21..9a6777b 100644 --- a/apiClientDotNet/Clients/SymOBOClient.cs +++ b/apiClientDotNet/Clients/SymOBOClient.cs @@ -11,8 +11,7 @@ public class SymOBOClient : ISymClient { private static SymOBOClient botClient; private SymConfig config; - private ISymAuth symBotAuth; - private DatafeedEventsService datafeedEventsService; + private ISymAuth symOBOAuth; private MessageClient messagesClient; private StreamClient streamClient; private PresenceClient presenceClient; @@ -20,15 +19,9 @@ public class SymOBOClient : ISymClient private ConnectionsClient connectionsClient; private SignalsClient signalsClient; - public static SymOBOClient initOBOClient(SymConfig config, ISymAuth symBotAuth) + public SymOBOClient(SymConfig config, ISymAuth symOBOAuth) { - botClient = new SymOBOClient(config, symBotAuth); - return botClient; - } - - private SymOBOClient(SymConfig config, ISymAuth symBotAuth) - { - this.symBotAuth = symBotAuth; + this.symOBOAuth = symOBOAuth; this.config = config; } @@ -39,7 +32,7 @@ public SymConfig getConfig() public ISymAuth getSymAuth() { - return symBotAuth; + return symOBOAuth; } public MessageClient getMessagesClient() diff --git a/apiClientDotNet/Utils/RequestProxyBuilder.cs b/apiClientDotNet/Utils/RequestProxyBuilder.cs new file mode 100644 index 0000000..c157a98 --- /dev/null +++ b/apiClientDotNet/Utils/RequestProxyBuilder.cs @@ -0,0 +1,24 @@ +using System; +using System.Net; + +namespace apiClientDotNet.Utils +{ + public static class RequestProxyBuilder + { + public static WebProxy CreateWebProxy(string proxyUrl, string proxyUsername, string proxyPassword) + { + var webProxy = new WebProxy(); + var webProxyUri = new Uri(proxyUrl); + webProxy.Address = webProxyUri; + if (!string.IsNullOrEmpty(proxyUsername) && !string.IsNullOrEmpty(proxyPassword)) + { + webProxy.Credentials = new NetworkCredential(proxyUsername, proxyPassword); + } + else + { + webProxy.Credentials = CredentialCache.DefaultNetworkCredentials; // Credential from current account + } + return webProxy; + } + } + } \ No newline at end of file From 0e54804c04e7be5f0a382f6d83c182d2b4a0a1bb Mon Sep 17 00:00:00 2001 From: Anthony Lee Date: Fri, 4 Mar 2022 10:42:25 -0500 Subject: [PATCH 6/6] Added App OBO RSA Auth --- .../Authentication/AuthEndpointConstants.cs | 3 +- apiClientDotNet/Authentication/SymOBOAuth.cs | 45 +---------------- .../Authentication/SymOBOAuthBase.cs | 50 +++++++++++++++++++ .../Authentication/SymOBORSAAuth.cs | 36 +++++++++++++ .../Authentication/SymOBOUserAuth.cs | 8 +-- apiClientDotNet/Models/SymConfig.cs | 9 ++++ apiClientDotNet/Utils/JWTHandler.cs | 17 ++++--- 7 files changed, 113 insertions(+), 55 deletions(-) create mode 100644 apiClientDotNet/Authentication/SymOBOAuthBase.cs create mode 100644 apiClientDotNet/Authentication/SymOBORSAAuth.cs diff --git a/apiClientDotNet/Authentication/AuthEndpointConstants.cs b/apiClientDotNet/Authentication/AuthEndpointConstants.cs index cf5ac72..6d428c4 100644 --- a/apiClientDotNet/Authentication/AuthEndpointConstants.cs +++ b/apiClientDotNet/Authentication/AuthEndpointConstants.cs @@ -21,7 +21,8 @@ public class AuthEndpointConstants public const string LogoutPath = "/sessionauth/v1/logout"; public const string RsaSessionAuthPath = "/login/pubkey/authenticate"; public const string RsaKeyManagerAuthPath = "/relay/pubkey/authenticate"; - public const string AppSessionAuthPath = "/sessionauth/v1/app/authenticate"; + public const string OBOAppSessionAuthPath = "/sessionauth/v1/app/authenticate"; + public const string OBOAppSessionRSAAuthPath = "/login/pubkey/app/authenticate"; public const string OboUserAuthByIdPath = "/login/pubkey/app/user/{uid}/authenticate"; public const string OboUserAuthByUsernamePath = "/login/pubkey/app/username/{username}/authenticate"; } diff --git a/apiClientDotNet/Authentication/SymOBOAuth.cs b/apiClientDotNet/Authentication/SymOBOAuth.cs index a2338cf..d5b136f 100644 --- a/apiClientDotNet/Authentication/SymOBOAuth.cs +++ b/apiClientDotNet/Authentication/SymOBOAuth.cs @@ -7,35 +7,17 @@ namespace apiClientDotNet.Authentication { - public class SymOBOAuth : SymAuthBase + public class SymOBOAuth : SymOBOAuthBase { - public string AppSessionToken - { - get { return SessionToken; } - set { SessionToken = value; } - } public SymOBOAuth(SymConfig config) { SymConfig = config; } - public SymOBOUserAuth GetUserAuth(string username) - { - SymOBOUserAuth userAuth = new SymOBOUserAuth(username, this); - userAuth.Authenticate(); - return userAuth; - } - - public SymOBOUserAuth GetUserAuth(long uid) - { - SymOBOUserAuth userAuth = new SymOBOUserAuth(uid, this); - userAuth.Authenticate(); - return userAuth; - } public override void SessionAuthenticate() { - var response = GetCertificateOBOSessionAuthClient().PostAsync(AuthEndpointConstants.AppSessionAuthPath, null).Result; + var response = GetCertificateOBOSessionAuthClient().PostAsync(AuthEndpointConstants.OBOAppSessionAuthPath, null).Result; if (response.IsSuccessStatusCode) { var result = response.Content.ReadAsStringAsync().Result; @@ -46,28 +28,5 @@ public override void SessionAuthenticate() SessionToken = null; } } - - public HttpClient GetAppAuthClient() - { - return GetOBOSessionAuthClient(); - } - - public override void Authenticate() - { - SessionAuthenticate(); - } - - public override void KeyManagerAuthenticate() {} - public override string GetKeyManagerToken() - { - return null; - } - - public override void SetKeyManagerToken(string kmToken) {} - - public override void Logout() - { - throw new NotImplementedException(); - } } } diff --git a/apiClientDotNet/Authentication/SymOBOAuthBase.cs b/apiClientDotNet/Authentication/SymOBOAuthBase.cs new file mode 100644 index 0000000..cf8d19c --- /dev/null +++ b/apiClientDotNet/Authentication/SymOBOAuthBase.cs @@ -0,0 +1,50 @@ +using System; +using apiClientDotNet.Models; +using System.Net.Http; +using Newtonsoft.Json; + + +namespace apiClientDotNet.Authentication +{ + + public abstract class SymOBOAuthBase : SymAuthBase + { + public string AppSessionToken + { + get { return SessionToken; } + set { SessionToken = value; } + } + + public SymOBOUserAuth GetUserAuth(string username) + { + SymOBOUserAuth userAuth = new SymOBOUserAuth(username, this); + userAuth.Authenticate(); + return userAuth; + } + + public SymOBOUserAuth GetUserAuth(long uid) + { + SymOBOUserAuth userAuth = new SymOBOUserAuth(uid, this); + userAuth.Authenticate(); + return userAuth; + } + + public override void Authenticate() + { + SessionAuthenticate(); + } + + public override void KeyManagerAuthenticate() {} + public override string GetKeyManagerToken() + { + return null; + } + + public override void SetKeyManagerToken(string kmToken) {} + + public override void Logout() + { + throw new NotImplementedException(); + } + } +} diff --git a/apiClientDotNet/Authentication/SymOBORSAAuth.cs b/apiClientDotNet/Authentication/SymOBORSAAuth.cs new file mode 100644 index 0000000..afaf045 --- /dev/null +++ b/apiClientDotNet/Authentication/SymOBORSAAuth.cs @@ -0,0 +1,36 @@ +using System.Net.Http; +using Newtonsoft.Json; +using apiClientDotNet.Utils; +using apiClientDotNet.Models; + +namespace apiClientDotNet.Authentication +{ + + public class SymOBORSAAuth : SymOBOAuthBase + { + + public SymOBORSAAuth(SymConfig config) + { + SymConfig = config; + } + + public override void SessionAuthenticate() + { + JWTHandler jwtHandler = new JWTHandler(); + var token = new + { + token = jwtHandler.generateJWT(SymConfig.appId, SymConfig.appPrivateKeyPath + SymConfig.appPrivateKeyName) + }; + var response = GetSessionAuthClient().PostAsync(AuthEndpointConstants.OBOAppSessionRSAAuthPath, new StringContent(JsonConvert.SerializeObject(token))).Result; + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + SessionToken = JsonConvert.DeserializeObject(result).token; + } + else + { + SessionToken = null; + } + } + } +} diff --git a/apiClientDotNet/Authentication/SymOBOUserAuth.cs b/apiClientDotNet/Authentication/SymOBOUserAuth.cs index d69a757..509bb25 100644 --- a/apiClientDotNet/Authentication/SymOBOUserAuth.cs +++ b/apiClientDotNet/Authentication/SymOBOUserAuth.cs @@ -9,9 +9,9 @@ public class SymOBOUserAuth : SymAuthBase { public long UserId {get; private set;} public String UserName {get; private set;} - private SymOBOAuth AppAuth; + private SymOBOAuthBase AppAuth; - public SymOBOUserAuth(long uid, SymOBOAuth appAuth) + public SymOBOUserAuth(long uid, SymOBOAuthBase appAuth) { UserId = uid; AppAuth = appAuth; @@ -19,7 +19,7 @@ public SymOBOUserAuth(long uid, SymOBOAuth appAuth) SymConfig.authTokens = new AuthTokens(); } - public SymOBOUserAuth(string username, SymOBOAuth appAuth) + public SymOBOUserAuth(string username, SymOBOAuthBase appAuth) { UserId = 0; UserName = username; @@ -66,7 +66,7 @@ public override void SessionAuthenticate() public override void Logout() { - var response = AppAuth.GetAppAuthClient().PostAsync(AuthEndpointConstants.LogoutPath, null).Result; + throw new NotImplementedException(); } public override string GetKeyManagerToken(){ diff --git a/apiClientDotNet/Models/SymConfig.cs b/apiClientDotNet/Models/SymConfig.cs index e4647fe..89f22cc 100644 --- a/apiClientDotNet/Models/SymConfig.cs +++ b/apiClientDotNet/Models/SymConfig.cs @@ -49,6 +49,15 @@ public class SymConfig [JsonProperty("appCertPassword")] public string appCertPassword { get; set; } + [JsonProperty("appPrivateKeyPath")] + public string appPrivateKeyPath { get; set; } + + [JsonProperty("appPrivateKeyName")] + public string appPrivateKeyName { get; set; } + + [JsonProperty("appId")] + public string appId { get; set; } + [JsonProperty("authTokenRefreshPeriod")] public string authTokenRefreshPeriod { get; set; } diff --git a/apiClientDotNet/Utils/JWTHandler.cs b/apiClientDotNet/Utils/JWTHandler.cs index b741aae..7ef82c7 100644 --- a/apiClientDotNet/Utils/JWTHandler.cs +++ b/apiClientDotNet/Utils/JWTHandler.cs @@ -50,15 +50,19 @@ public string generateJWT(SymConfig config) public string generateJWT(SymConfig config) { + return generateJWT(config.botUsername, config.botPrivateKeyPath + config.botPrivateKeyName); + } + + public string generateJWT(string subject, string privateKey) { string jwt = ""; - AsymmetricKeyParameter secret = parseSecret(config); + AsymmetricKeyParameter secret = parseSecret(privateKey); DateTime otherTime = DateTime.Now.AddMinutes(4); var payload = new JwtPayload { - { "sub", config.botUsername }, + { "sub", subject }, { "exp", ToUtcSeconds(otherTime) } }; @@ -73,19 +77,18 @@ public string generateJWT(SymConfig config) } return jwt; - } - private AsymmetricKeyParameter parseSecret(SymConfig config) + private AsymmetricKeyParameter parseSecret(string privateKey) { AsymmetricCipherKeyPair keyPair; - using (var reader = File.OpenText(config.botPrivateKeyPath + config.botPrivateKeyName)) // file containing RSA PKCS1 private key + using (var reader = File.OpenText(privateKey)) // file containing RSA PKCS1 private key keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject(); - AsymmetricKeyParameter privateKey = keyPair.Private; + AsymmetricKeyParameter secret = keyPair.Private; - return privateKey; + return secret; }