public void TestParseDirectory() { var eid = EntityIdentifier.FromString($"dir:{_testGuidString}"); Assert.AreEqual(eid.Id, _testGuid); Assert.AreEqual(eid.Type, EntityType.Directory); }
public void TestParseService() { var eid = EntityIdentifier.FromString($"svc:{_testGuidString}"); Assert.AreEqual(eid.Id, _testGuid); Assert.AreEqual(eid.Type, EntityType.Service); }
public void TestParseOrg() { var eid = EntityIdentifier.FromString($"org:{_testGuidString}"); Assert.AreEqual(eid.Id, _testGuid); Assert.AreEqual(eid.Type, EntityType.Organization); }
public void TestEncodeAndDecode() { var eid1 = new EntityIdentifier(EntityType.Organization, _testGuid); var eid1Str = eid1.ToString(); var eid2 = EntityIdentifier.FromString(eid1Str); Assert.AreEqual(eid1, eid2); }
public IServerSentEvent HandleServerSentEvent(Dictionary <string, List <string> > headers, string body, string method = null, string path = null) { var iovHeader = GetFirstHeader(headers, IOV_JWT_HEADER); var contentHeader = GetFirstHeader(headers, "Content-Type"); try { // pull out the key id var jwtData = _jwtService.GetJWTData(iovHeader); // get public key associated with the id. may have to fetch it! var publicKey = FetchPublicKeyWithId(jwtData.KeyId); // decode and verify the JWT. // note we do not store the result -- its not needed. Just want the decoder to throw an exception // if there is a validation issue // we also dont verify our private claims here, as they are not present or relevant var jwtObject = _jwtService.Decode(publicKey.KeyData, _issuer.ToString(), null, GetCurrentTime(), iovHeader); ValidatePrivateClaimsForServerSentRequest(method, path, body, jwtObject.Request); // if this is not application/jose, it is a service session end response if (contentHeader == "application/jose") { var requestingEntity = EntityIdentifier.FromString(jwtData.Audience); var decryptedBody = _jweService.Decrypt(body); if (decryptedBody.Contains("DEVICE_LINK_COMPLETION") == true) { DeviceLinkCompletion deviceLinkCompletion = DecodeResponse <DeviceLinkCompletion>(decryptedBody); return(new ServerSentEventDeviceLinked(deviceLinkCompletion)); } else { Guid authorizationRequestId; var core = DecodeResponse <ServiceV3AuthsGetResponseCore>(decryptedBody); bool response; string deviceId; string[] servicePins; string type; string reason; string denialreason; AuthPolicy.JWEAuthPolicy authPolicy; AuthPolicy.AuthMethod[] authMethods; if (core.JweEncryptedDeviceResponse != null) { var decryptedDeviceData = _jweService.Decrypt(core.JweEncryptedDeviceResponse); var deviceResponse = DecodeResponse <ServiceV3AuthsGetResponseDeviceJWE>(decryptedDeviceData); authorizationRequestId = deviceResponse.AuthorizationRequestId; response = deviceResponse.Type == "AUTHORIZED"; deviceId = deviceResponse.DeviceId; servicePins = deviceResponse.ServicePins; type = deviceResponse.Type; reason = deviceResponse.Reason; denialreason = deviceResponse.DenialReason; authPolicy = deviceResponse.AuthPolicy; authMethods = deviceResponse.AuthMethods; } else { var bodyJweHeaders = _jweService.GetHeaders(body); if (!bodyJweHeaders.ContainsKey("kid")) { throw new InvalidRequestException("JWE headers does not include a key id"); } var privateKey = _keyMap.GetKey(requestingEntity, bodyJweHeaders["kid"]); var encryptedDeviceData = Convert.FromBase64String(core.EncryptedDeviceResponse); var decryptedDeviceData = _crypto.DecryptRSA(encryptedDeviceData, privateKey); var decryptedDeviceDataString = Encoding.UTF8.GetString(decryptedDeviceData); var deviceResponse = DecodeResponse <ServiceV3AuthsGetResponseDevice>(decryptedDeviceDataString); authorizationRequestId = deviceResponse.AuthorizationRequestId; response = deviceResponse.Response; deviceId = deviceResponse.DeviceId; servicePins = deviceResponse.ServicePins; type = null; reason = null; denialreason = null; authPolicy = null; authMethods = null; } return(new ServerSentEventAuthorizationResponse( requestingEntity, EntityIdentifier.FromString(jwtData.Subject).Id, core.ServiceUserHash, core.OrgUserHash, core.UserPushId, authorizationRequestId, response, deviceId, servicePins, type, reason, denialreason, authPolicy, authMethods )); } } else { return(_jsonDecoder.DecodeObject <ServerSentEventUserServiceSessionEnd>(body)); } } catch (JwtError ex) { throw new InvalidRequestException("JWT error while processing event", ex); } catch (JweException ex) { throw new InvalidRequestException("Unable to decrypt body", ex); } }
public ServiceV3AuthsGetResponse ServiceV3AuthsGet(Guid authRequestId, EntityIdentifier subject) { var response = ExecuteRequest(HttpMethod.GET, $"/service/v3/auths/{authRequestId}", subject, null, new List <int> { 408 }); if ((int)response.StatusCode == 204) { // user has not responded yet return(null); } if ((int)response.StatusCode == 408) { throw new AuthorizationRequestTimedOutError(); } try { var coreResponse = DecryptResponse <ServiceV3AuthsGetResponseCore>(response); var jwtHeader = response.Headers[IOV_JWT_HEADER]; var jwtData = _jwtService.GetJWTData(jwtHeader); var audience = EntityIdentifier.FromString(jwtData.Audience); var key = _keyMap.GetKey(audience, coreResponse.PublicKeyId); bool authResponse = false; string deviceId = null; string[] servicePins = null; string type; string reason; string denialReason; AuthPolicy.JWEAuthPolicy authPolicy; AuthPolicy.AuthMethod[] authMethods; try { if (coreResponse.JweEncryptedDeviceResponse != null) { var decryptedResponse = DecryptJweData(coreResponse.JweEncryptedDeviceResponse); var deviceResponse = DecodeResponse <ServiceV3AuthsGetResponseDeviceJWE>(decryptedResponse); authResponse = deviceResponse.Type == "AUTHORIZED"; deviceId = deviceResponse.DeviceId; servicePins = deviceResponse.ServicePins; type = deviceResponse.Type; reason = deviceResponse.Reason; denialReason = deviceResponse.DenialReason; authPolicy = deviceResponse.AuthPolicy; authMethods = deviceResponse.AuthMethods; } else { var encryptedDeviceResponse = Convert.FromBase64String(coreResponse.EncryptedDeviceResponse); var decryptedResponse = _crypto.DecryptRSA(encryptedDeviceResponse, key); var decryptedResponseString = Encoding.UTF8.GetString(decryptedResponse); var deviceResponse = _jsonDecoder.DecodeObject <ServiceV3AuthsGetResponseDevice>(decryptedResponseString); authResponse = deviceResponse.Response; deviceId = deviceResponse.DeviceId; servicePins = deviceResponse.ServicePins; type = null; reason = null; denialReason = null; authPolicy = null; authMethods = null; } return(new ServiceV3AuthsGetResponse( audience, subject.Id, coreResponse.ServiceUserHash, coreResponse.OrgUserHash, coreResponse.UserPushId, authRequestId, authResponse, deviceId, servicePins, type, reason, denialReason, authPolicy, authMethods )); } catch (Exception ex) { throw new CryptographyError("Error decrypting device response", ex); } } catch (JwtError ex) { throw new CryptographyError("Unable to parse JWT to get key info", ex); } }
public void Initialize() { HttpResponse = new Mock <HttpResponse>(); HttpResponse.Object.StatusCode = HttpStatusCode.NoContent; HttpResponse.Object.Headers = new WebHeaderCollection { { "X-IOV-KEY-ID", "d2:8e:16:91:39:5b:9d:24:73:0e:36:0a:9a:ef:7e:de" }, { "X-IOV-JWT", "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImQyOjhlOjE2OjkxOjM5OjViOjlkOjI0OjczOjBlOjM2OjBhOjlhOmVmOjdlOmRlIn0.eyJhdWQiOiJzdmM6ZjgzMjllMGUtZGQ3YS0xMWU3LTk4YjQtNDY5MTU4NDY3YjFhIiwiaXNzIjoibGthIiwiY3R5IjoiYXBwbGljYXRpb24vanNvbiIsIm5iZiI6MTUxNTA1MTcwMSwianRpIjoiMjJkYWU0MjUzMTY1NDk1YThlZDU2YzM0YzRkMDUwY2UiLCJleHAiOjE1MTUwNTE3MDYsImlhdCI6MTUxNTA1MTcwMSwicmVzcG9uc2UiOnsic3RhdHVzIjoyMDAsImhhc2giOiI0YzViODBlZDhlNTRhZWIwNDkwODFiYTBjMWE0ZDViMjkwNzhkMjIzM2NhZTkxZDg5ODUyMjUwYTFkMWQ1OWEyIiwiZnVuYyI6IlMyNTYifSwic3ViIjoic3ZjOmY4MzI5ZTBlLWRkN2EtMTFlNy05OGI0LTQ2OTE1ODQ2N2IxYSJ9.NFhztQSep7f0QT8j7KIfK4yFwdHvL24r8qdYKZz3M3Y2kyQYT0ECBPXnXgr2KbU5gntWdjVUOySUQbDnF2aL8QDyWPQHGy6jX7n4rO2VdeYuROz-3dbx7taSJEUUlDSvoDAerL26P02xU6LbZno1TCl4pYMQn4k41xwBvYdf8vvN1ixLhCJE_S2V18bT4YKTqwxE-XnbubdAdvhkPdl-7Khja4r1MpktRTZAMWJECLXI3JJILm-3HudO9KS5uAAHkxGbW1ovZfxOcKv9fcwoZ4mSn1pXA7k1aAt7DJdk4EuOtLmxb5rIKTDvQcBZIPyO_N3repWeD8ghCIFgWOSHqUE7cM1koUvUZzDiTvPA9o2C46zD26QaljSWfsxYPKtyzZsyglPYc1bcmzJZWzfHFCOoKA8uxe7HLiqNyzry3Cyg0_kPiwwtJ_FBRAnN3MVhAczaXbEPHtrm3vLafw14_M2svtL6f6RsObFroBJE_VDmgdiKtiJiYQ1UEpx_LcwK_OB-BagOnXUFGtveKQIJvABZoRwrxS6TebhVMAU1cGurF2sJmlSO3oi1CC-GSgtVDMmh_a2oA9E5UrG3W5nmB-ThCGBpKfTIYB19rwsOd6RYNUaOEj65_KN_EFHH_7dLAeDDlPWqFCUfML9pjeRUK289c_ByDDOX3N3iTrnCt1o" } }; HttpClient = new Mock <IHttpClient>(); HttpClient.Setup(client => client.ExecuteRequest(It.IsAny <HttpMethod>(), It.IsAny <String>(), It.IsAny <String>(), It.IsAny <Dictionary <string, String> >())) .Returns(HttpResponse.Object); Crypto = new Mock <ICrypto>(); Crypto.Setup(c => c.DecryptRSA(It.IsAny <byte[]>(), It.IsAny <RSA>())).Returns(System.Text.Encoding.ASCII.GetBytes("Decrypted")); Crypto.Setup(c => c.Sha256(It.IsAny <byte[]>())).Returns(new byte[] { 255 }); PublicKeyCache = new Mock <ICache>(); PublicKeyCache.Setup(c => c.Get(It.IsAny <String>())).Returns("Public Key"); Issuer = new EntityIdentifier(EntityType.Directory, default(Guid)); JwtService = new Mock <IJwtService>(); JwtService.Setup(s => s.Encode(It.IsAny <String>(), It.IsAny <String>(), It.IsAny <String>(), It.IsAny <DateTime>(), It.IsAny <String>(), It.IsAny <String>(), It.IsAny <String>(), It.IsAny <String>())) .Returns("JWT Encoded"); JwtClaims = new Mock <JwtClaims>(); JwtClaimsResponse = new Mock <JwtClaimsResponse>(); JwtClaimsResponse.Object.StatusCode = 204; JwtClaimsResponse.Object.LocationHeader = null; JwtClaimsResponse.Object.CacheControlHeader = null; JwtClaimsResponse.Object.ContentHash = "ff"; JwtClaimsResponse.Object.ContentHashAlgorithm = "S256"; JwtClaims.Object.Response = JwtClaimsResponse.Object; JwtService.Setup(s => s.Decode(It.IsAny <RSA>(), It.IsAny <string>(), It.IsAny <String>(), It.IsAny <DateTime>(), It.IsAny <String>())) .Returns(JwtClaims.Object); JwtService.Setup(s => s.GetJWTData(It.IsAny <String>())) .Returns(new JwtData("lka", "svc:8c3c0268-f692-11e7-bd2e-7692096aba47", "svc:8c3c0268-f692-11e7-bd2e-7692096aba47", "Key ID")); JweService = new Mock <IJweService>(); JweService.Setup(s => s.Decrypt(It.IsAny <String>())).Returns("Decrypted JWE"); JweService.Setup(s => s.Encrypt(It.IsAny <String>(), It.IsAny <RSA>(), It.IsAny <String>(), It.IsAny <String>())) .Returns("Encrypted JWE"); JsonEncoder = new Mock <IJsonEncoder>(); JsonEncoder.Setup(e => e.EncodeObject(It.IsAny <Object>())).Returns("JSON Encoded"); JsonEncoder.Setup(e => e.DecodeObject <PublicV3PingGetResponse>(It.IsAny <String>())).Returns(new Mock <PublicV3PingGetResponse>().Object); AuthsGetResponseCore = new Mock <ServiceV3AuthsGetResponseCore>(); AuthsGetResponseCore.Object.EncryptedDeviceResponse = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes("Encrypted Device Response")); AuthsGetResponseCore.Object.JweEncryptedDeviceResponse = null; AuthsGetResponseCore.Object.ServiceUserHash = "Service User Hash"; AuthsGetResponseCore.Object.OrgUserHash = "Org User Hash"; AuthsGetResponseCore.Object.UserPushId = "User Push ID"; AuthsGetResponseCore.Object.PublicKeyId = "Response Public Key"; JsonEncoder.Setup(e => e.DecodeObject <ServiceV3AuthsGetResponseCore>(It.IsAny <String>())).Returns(AuthsGetResponseCore.Object); DeviceResponse = new Mock <ServiceV3AuthsGetResponseDevice>(); JsonEncoder.Setup(e => e.DecodeObject <ServiceV3AuthsGetResponseDevice>(It.IsAny <String>())).Returns(DeviceResponse.Object); KeyMap = new Mock <EntityKeyMap>(); KeyMap.Object.AddKey(EntityIdentifier.FromString("svc:8c3c0268-f692-11e7-bd2e-7692096aba47"), "Response Public Key", new Mock <RSA>().Object); Transport = new WebClientTransport( HttpClient.Object, Crypto.Object, PublicKeyCache.Object, BaseUrl, Issuer, JwtService.Object, JweService.Object, 0, 0, KeyMap.Object, JsonEncoder.Object); }
public void Initialize() { HttpResponse = new Mock <HttpResponse>(); HttpResponse.Object.StatusCode = HttpStatusCode.OK; HttpResponse.Object.Headers = new WebHeaderCollection { ["X-IOV-JWT"] = "IOV JWT" }; HttpClient = new Mock <IHttpClient>(); HttpClient.Setup(client => client.ExecuteRequest(It.IsAny <HttpMethod>(), It.IsAny <String>(), It.IsAny <String>(), It.IsAny <Dictionary <string, String> >())) .Returns(HttpResponse.Object); Crypto = new Mock <ICrypto>(); Crypto.Setup(c => c.DecryptRSA(It.IsAny <byte[]>(), It.IsAny <RSA>())).Returns(System.Text.Encoding.ASCII.GetBytes("Decrypted")); Crypto.Setup(c => c.Sha256(It.IsAny <byte[]>())).Returns(new byte[] { 255 }); PublicKeyCache = new Mock <ICache>(); PublicKeyCache.Setup(c => c.Get(It.IsAny <String>())).Returns("Public Key"); Issuer = new EntityIdentifier(EntityType.Directory, default(Guid)); JwtService = new Mock <IJwtService>(); JwtService.Setup(s => s.Encode(It.IsAny <String>(), It.IsAny <String>(), It.IsAny <String>(), It.IsAny <DateTime>(), It.IsAny <String>(), It.IsAny <String>(), It.IsAny <String>(), It.IsAny <String>())) .Returns("JWT Encoded"); JwtClaims = new Mock <JwtClaims>(); JwtClaimsResponse = new Mock <JwtClaimsResponse>(); JwtClaimsResponse.Object.StatusCode = 200; JwtClaimsResponse.Object.LocationHeader = null; JwtClaimsResponse.Object.CacheControlHeader = null; JwtClaimsResponse.Object.ContentHash = "ff"; JwtClaimsResponse.Object.ContentHashAlgorithm = "S256"; JwtClaimsRequest = new Mock <JwtClaimsRequest>(); JwtClaimsRequest.Object.ContentHash = "ff"; JwtClaimsRequest.Object.ContentHashAlgorithm = "S256"; JwtClaimsRequest.Object.Method = "POST"; JwtClaimsRequest.Object.Path = "/webhook"; JwtClaims.Object.Response = JwtClaimsResponse.Object; JwtClaims.Object.Request = JwtClaimsRequest.Object; JwtService.Setup(s => s.Decode(It.IsAny <RSA>(), It.IsAny <string>(), It.IsAny <String>(), It.IsAny <DateTime>(), It.IsAny <String>())) .Returns(JwtClaims.Object); JwtService.Setup(s => s.GetJWTData(It.IsAny <String>())) .Returns(new JwtData("lka", "svc:8c3c0268-f692-11e7-bd2e-7692096aba47", "svc:8c3c0268-f692-11e7-bd2e-7692096aba47", "Key ID")); JweService = new Mock <IJweService>(); JweService.Setup(s => s.Decrypt(It.IsAny <String>())).Returns("Decrypted JWE"); JweService.Setup(s => s.Encrypt(It.IsAny <String>(), It.IsAny <RSA>(), It.IsAny <String>(), It.IsAny <String>())) .Returns("Encrypted JWE"); JweHeaders = new Dictionary <string, string> { ["kid"] = "Public Key ID" }; JweService.Setup(s => s.GetHeaders(It.IsAny <String>())).Returns(JweHeaders); JsonEncoder = new Mock <IJsonEncoder>(); JsonEncoder.Setup(e => e.EncodeObject(It.IsAny <Object>())).Returns("JSON Encoded"); JsonEncoder.Setup(e => e.DecodeObject <PublicV3PingGetResponse>(It.IsAny <String>())).Returns(new Mock <PublicV3PingGetResponse>().Object); AuthsGetResponseCore = new Mock <ServiceV3AuthsGetResponseCore>(); AuthsGetResponseCore.Object.EncryptedDeviceResponse = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes("Encrypted Device Response")); AuthsGetResponseCore.Object.JweEncryptedDeviceResponse = null; AuthsGetResponseCore.Object.ServiceUserHash = "Service User Hash"; AuthsGetResponseCore.Object.OrgUserHash = "Org User Hash"; AuthsGetResponseCore.Object.UserPushId = "User Push ID"; AuthsGetResponseCore.Object.PublicKeyId = "Public Key ID"; JsonEncoder.Setup(e => e.DecodeObject <ServiceV3AuthsGetResponseCore>(It.IsAny <String>())).Returns(AuthsGetResponseCore.Object); DeviceResponse = new Mock <ServiceV3AuthsGetResponseDevice>(); JsonEncoder.Setup(e => e.DecodeObject <ServiceV3AuthsGetResponseDevice>(It.IsAny <String>())).Returns(DeviceResponse.Object); ServiceSessionEnd = new Mock <ServerSentEventUserServiceSessionEnd>(); JsonEncoder.Setup(e => e.DecodeObject <ServerSentEventUserServiceSessionEnd>(It.IsAny <String>())).Returns(ServiceSessionEnd.Object); KeyMap = new Mock <EntityKeyMap>(); KeyMap.Object.AddKey(EntityIdentifier.FromString("svc:8c3c0268-f692-11e7-bd2e-7692096aba47"), "Public Key ID", new Mock <RSA>().Object); Transport = new WebClientTransport( HttpClient.Object, Crypto.Object, PublicKeyCache.Object, BaseUrl, Issuer, JwtService.Object, JweService.Object, 0, 0, KeyMap.Object, JsonEncoder.Object); }