From 0bb2305103757a981389280e1d62de7f108d1b48 Mon Sep 17 00:00:00 2001 From: Steven Fisher Date: Thu, 31 Dec 2015 00:19:44 -0500 Subject: [PATCH] Added support for twilio video --- src/classes/TwilioAuthAccessToken.cls | 129 ++++++++++++++++++ .../TwilioAuthAccessToken.cls-meta.xml | 5 + src/classes/TwilioAuthConversationsGrant.cls | 56 ++++++++ .../TwilioAuthConversationsGrant.cls-meta.xml | 5 + src/classes/TwilioAuthGrant.cls | 26 ++++ src/classes/TwilioAuthGrant.cls-meta.xml | 5 + src/classes/Twilio_TestAuthAccessToken.cls | 61 +++++++++ .../Twilio_TestAuthAccessToken.cls-meta.xml | 5 + .../Twilio_TestAuthConversationsGrant.cls | 60 ++++++++ ...io_TestAuthConversationsGrant.cls-meta.xml | 5 + 10 files changed, 357 insertions(+) create mode 100644 src/classes/TwilioAuthAccessToken.cls create mode 100644 src/classes/TwilioAuthAccessToken.cls-meta.xml create mode 100644 src/classes/TwilioAuthConversationsGrant.cls create mode 100644 src/classes/TwilioAuthConversationsGrant.cls-meta.xml create mode 100644 src/classes/TwilioAuthGrant.cls create mode 100644 src/classes/TwilioAuthGrant.cls-meta.xml create mode 100644 src/classes/Twilio_TestAuthAccessToken.cls create mode 100644 src/classes/Twilio_TestAuthAccessToken.cls-meta.xml create mode 100644 src/classes/Twilio_TestAuthConversationsGrant.cls create mode 100644 src/classes/Twilio_TestAuthConversationsGrant.cls-meta.xml diff --git a/src/classes/TwilioAuthAccessToken.cls b/src/classes/TwilioAuthAccessToken.cls new file mode 100644 index 0000000..2724519 --- /dev/null +++ b/src/classes/TwilioAuthAccessToken.cls @@ -0,0 +1,129 @@ +/* +Copyright (c) 2012 Twilio, Inc. +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ +public class TwilioAuthAccessToken +{ + private final String accountSid; + private final String keySid; + private final String secret; + private final Integer ttl; + + private final Integer nbf; + private final String identity; + private final Set grants; + + public TwilioAuthAccessToken(String accountSid, String keySid, String secret, + Integer ttl, String identity, String configSid) + { + this.accountSid = accountSid; + this.keySid = keySid; + this.secret = secret; + this.ttl = ttl; + this.identity = identity; + + TwilioAuthConversationsGrant configGrant = new TwilioAuthConversationsGrant(); + configGrant.configurationProfileSid = configSid; + + grants = new Set(); + grants.add(configGrant); + } + + public String getIdentity() + { + return this.identity; + } + + public String toJWT() + { + Map headers = new Map(); + headers.put('cty', 'twilio-fpa;v=1'); + headers.put('alg', 'HS256'); + headers.put('typ', 'JWT'); + + Integer timestamp = (Integer)(System.currentTimeMillis() / 1000); + Map grantPayload = new Map(); + + if (this.identity != null) + { + grantPayload.put('identity', this.identity); + } + + for (TwilioAuthGrant grant : this.grants) + { + grantPayload.put(grant.getGrantKey(), grant.getPayload()); + } + + Map payload = new Map(); + payload.put('grants', grantPayload); + payload.put('exp', timestamp + this.ttl); + payload.put('sub', this.accountSid); + payload.put('iss', this.keySid); + payload.put('jti', this.keySid + '-' + String.valueOf(timestamp)); + + List segments = new List(); + segments.add(urlSafeEncodeBase64(JSON.serialize(headers))); + segments.add(urlSafeEncodeBase64(JSON.serialize(payload))); + + String signature = sign(join(segments, '.'), this.secret); + segments.add(signature); + + return join(segments, '.'); + } + + @TestVisible + private static String urlSafeEncodeBase64(String data) + { + return urlSafeEncodeBase64(Blob.valueOf(data)); + } + + @TestVisible + private static String urlSafeEncodeBase64(Blob data) + { + String encodedString = EncodingUtil.base64Encode(data); + return encodedString.replace('+', '-').replace('/', '_').replace('=', ''); + } + + @TestVisible + public static String join(List vals, String sep) + { + String sb = ''; + for (Iterator it = vals.iterator(); it.hasNext();) + { + String value = it.next(); + if (sb.length() != 0) + { + sb += sep; + } + + sb += value; + } + + return sb; + } + + private static String sign(String data, String key) + { + Blob mac = Crypto.generateMac('hmacSHA256', Blob.valueOf(data), Blob.valueOf(key)); + String result = urlSafeEncodeBase64(mac); + + return result; + } +} diff --git a/src/classes/TwilioAuthAccessToken.cls-meta.xml b/src/classes/TwilioAuthAccessToken.cls-meta.xml new file mode 100644 index 0000000..d219ea1 --- /dev/null +++ b/src/classes/TwilioAuthAccessToken.cls-meta.xml @@ -0,0 +1,5 @@ + + + 35.0 + Active + diff --git a/src/classes/TwilioAuthConversationsGrant.cls b/src/classes/TwilioAuthConversationsGrant.cls new file mode 100644 index 0000000..8a4d7b6 --- /dev/null +++ b/src/classes/TwilioAuthConversationsGrant.cls @@ -0,0 +1,56 @@ +/* +Copyright (c) 2012 Twilio, Inc. +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ +public class TwilioAuthConversationsGrant implements TwilioAuthGrant +{ + public String configurationProfileSid; + + public String getConfigurationProfileSid() + { + return configurationProfileSid; + } + + public TwilioAuthConversationsGrant setConfigurationProfileSid(String configurationProfileSid) + { + this.configurationProfileSid = configurationProfileSid; + return this; + } + + public String getGrantKey() + { + return 'rtc'; + } + + public Object getPayload() + { + return new Payload(this); + } + + public class Payload + { + public final String configuration_profile_sid; + + public Payload(TwilioAuthConversationsGrant grant) + { + this.configuration_profile_sid = grant.configurationProfileSid; + } + } +} diff --git a/src/classes/TwilioAuthConversationsGrant.cls-meta.xml b/src/classes/TwilioAuthConversationsGrant.cls-meta.xml new file mode 100644 index 0000000..d219ea1 --- /dev/null +++ b/src/classes/TwilioAuthConversationsGrant.cls-meta.xml @@ -0,0 +1,5 @@ + + + 35.0 + Active + diff --git a/src/classes/TwilioAuthGrant.cls b/src/classes/TwilioAuthGrant.cls new file mode 100644 index 0000000..5a5483b --- /dev/null +++ b/src/classes/TwilioAuthGrant.cls @@ -0,0 +1,26 @@ +/* +Copyright (c) 2012 Twilio, Inc. +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ +public interface TwilioAuthGrant +{ + String getGrantKey(); + Object getPayload(); +} diff --git a/src/classes/TwilioAuthGrant.cls-meta.xml b/src/classes/TwilioAuthGrant.cls-meta.xml new file mode 100644 index 0000000..d219ea1 --- /dev/null +++ b/src/classes/TwilioAuthGrant.cls-meta.xml @@ -0,0 +1,5 @@ + + + 35.0 + Active + diff --git a/src/classes/Twilio_TestAuthAccessToken.cls b/src/classes/Twilio_TestAuthAccessToken.cls new file mode 100644 index 0000000..8361bf4 --- /dev/null +++ b/src/classes/Twilio_TestAuthAccessToken.cls @@ -0,0 +1,61 @@ +/* +Copyright (c) 2012 Twilio, Inc. +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ +@isTest +private class Twilio_TestAuthAccessToken +{ + final static String accountSid = 'skOPGTJWyBM7Wyrz5tRCbm8zqGGUAvfhePVU'; + final static String apiKeySid = 'VOM7EV29bq8kEfG2jyPA0b0ywD894lxlxZqn'; + final static String apiKeySecret = 'uGhUTeKS3xjkDQJlCq2gH1r9BBEPX5SVQyhf'; + final static String configurationProfileSid = 'DNTBElGC532wArnIBYE2unCDI6yWbstanNzC'; + + static testMethod void testGetIdentity() + { + TwilioAuthAccessToken accessToken = new TwilioAuthAccessToken(accountSid, apikeySid, apiKeySecret, + 3600, 'Testing', configurationProfileSid); + + System.assertEquals('Testing', accessToken.getIdentity()); + } + + static testMethod void testEncodeBase64() + { + System.assertEquals('', TwilioAuthAccessToken.urlSafeEncodeBase64('')); + System.assertEquals('QQ', TwilioAuthAccessToken.urlSafeEncodeBase64('A')); + System.assertEquals('QUI', TwilioAuthAccessToken.urlSafeEncodeBase64('AB')); + System.assertEquals('QUJDRA', TwilioAuthAccessToken.urlSafeEncodeBase64('ABCD')); + } + + static testMethod void testJoin() + { + System.assertEquals('', TwilioAuthAccessToken.join(new List{''}, '-')); + System.assertEquals('a-b-c', TwilioAuthAccessToken.join(new List{'a','b','c'}, '-')); + System.assertEquals('a', TwilioAuthAccessToken.join(new List{'a'}, '-')); + System.assertEquals('abc', TwilioAuthAccessToken.join(new List{'a','b','c'}, '')); + } + + static testMethod void testToJWT() + { + TwilioAuthAccessToken accessToken = new TwilioAuthAccessToken(accountSid, apiKeySid, apiKeySecret, + 3600, 'Testing', configurationProfileSid); + + System.assert(accessToken.toJWT() != null); + } +} diff --git a/src/classes/Twilio_TestAuthAccessToken.cls-meta.xml b/src/classes/Twilio_TestAuthAccessToken.cls-meta.xml new file mode 100644 index 0000000..d219ea1 --- /dev/null +++ b/src/classes/Twilio_TestAuthAccessToken.cls-meta.xml @@ -0,0 +1,5 @@ + + + 35.0 + Active + diff --git a/src/classes/Twilio_TestAuthConversationsGrant.cls b/src/classes/Twilio_TestAuthConversationsGrant.cls new file mode 100644 index 0000000..b789b2a --- /dev/null +++ b/src/classes/Twilio_TestAuthConversationsGrant.cls @@ -0,0 +1,60 @@ +/* +Copyright (c) 2012 Twilio, Inc. +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ +@isTest +private class Twilio_TestAuthConversationsGrant +{ + final static String configurationProfileSid = 'DNTBElGC532wArnIBYE2unCDI6yWbstanNzC'; + + static testmethod void testSetConfigurationProfileSid() + { + TwilioAuthConversationsGrant grant = new TwilioAuthConversationsGrant(); + grant.setConfigurationProfileSid(configurationProfileSid); + + System.assertEquals(configurationProfileSid, grant.configurationProfileSid); + } + + static testMethod void testGetGrantKey() + { + TwilioAuthConversationsGrant grant = new TwilioAuthConversationsGrant(); + + System.assertEquals('rtc', grant.getGrantKey()); + } + + static testMethod void testGetConfigurationProfileSid() + { + TwilioAuthConversationsGrant grant = new TwilioAuthConversationsGrant(); + grant.setConfigurationProfileSid(configurationProfileSid); + + System.assertEquals(configurationProfileSid, grant.getConfigurationProfileSid()); + } + + static testMethod void testGetPayload() + { + TwilioAuthConversationsGrant grant = new TwilioAuthConversationsGrant(); + grant.setConfigurationProfileSid(configurationProfileSid); + + TwilioAuthConversationsGrant.Payload payload = (TwilioAuthConversationsGrant.Payload)grant.getPayload(); + + System.assert(payload != null); + System.assertEquals(configurationProfileSid, payload.configuration_profile_sid); + } +} diff --git a/src/classes/Twilio_TestAuthConversationsGrant.cls-meta.xml b/src/classes/Twilio_TestAuthConversationsGrant.cls-meta.xml new file mode 100644 index 0000000..d219ea1 --- /dev/null +++ b/src/classes/Twilio_TestAuthConversationsGrant.cls-meta.xml @@ -0,0 +1,5 @@ + + + 35.0 + Active +