The sip:phone Mobile App is a mobile client for iOS and Android and supports voice calls via SIP, as well as presence and instant messaging via XMPP. The following chapters describe the steps needed to integrate it into the sip:carrier.
Part of the mobile apps is a mechanism to sign up to the service via a 3rd party web site, which is initiated on the login screen and rendered within the app. During the sign-up process, the 3rd party service is supposed to create a new account and/or subscriber on the sip:carrier (e.g. automatically via the API) and provide the end user with the access credentials.
In order to minimize the end customer steps to log in using these credentials (especially ruling out the need to manually enter them), the mobile apps come with a zero config mechanism, which allows to deliver the access credentials via a side channel (e.g. Email, SMS) and packed into a URL, which the user just has to click, and which automatically launches the app with the correct credentials. The following picture shows the overall work flow.
There are two components provided by a 3rd party system, which are not part of the sip:carrier. One is the 3rd Party Sign-Up Form, and the other is the 3rd Party Launch Handler. The purpose of these components is to make the end customer to open a link with the access credentials via the sip:phone app.
The 3rd Party Sign-Up Form is a web site the app shows to the end user when he taps the sign-up link on the Login Screen of the app. There, the end customer usually provides his contact details like name, address, phone number and/or email address etc. After validation, this web site creates the account and/or subscriber on the sip:carrier via the API.
After successfully creating the account and/or subscriber, this site needs to construct a specially crafted URL, which is sent back to the end customer via a side channel. Ideally, this channel would be SMS if you want to verify the end user’s mobile number, or an email if you want to verify her email address.
The sip:phone app registers a URL schema handler for URLs starting with sipphone://
. If you start such a link, the app performs a Base64 decoding of the string right after the sipphone://
schema string, then decrypts the resulting binary string via AES using keys defined during the branding step. The resulting string is supposed to be
username=$user&server=$domain&password=$password.
Therefore, the 3rd Party Sign-Up Form needs to construct this string using the credentials defined while creating the subscriber via the sip:carrier API, then encrypt it via AES, and finally perform a Base64 encoding of the result.
Up until and including version mr4.1.1 of the sip:carrier, the SIP login credentials are used here. Future versions will connect to the REST interface of the sip:carrier using the web credentials first and fetch the SIP credentials along with other settings from there. |
An example code snipped in Perl to properly encode such a string is outlined here. The AES key and initialization vector ($key and $iv) are the standard values of the sip:phone app and should work, if you haven’t specified other values during the branding process.
#!/usr/bin/perl -w use strict; use Crypt::Rijndael; use MIME::Base64; use URI::Escape; my $key = 'iBmTdavJ8joPW3HO'; my $iv = 'tww21lQe6cmywrp3'; my $plain = do { local $/; <> }; # pkcs#5 padding to 16 bytes blocksize my $pad = 16 - (length $plain) % 16; $plain .= pack('C', $pad) x $pad; my $cipher = Crypt::Rijndael->new( $key, Crypt::Rijndael::MODE_CBC() ); $cipher->set_iv($iv); my $crypted = $cipher->encrypt($plain); # store b64-encoded string and print to STDOUT my $b64 = encode_base64($crypted, ''); print $b64, "\n"; # print to STDOUT using URL escaping also print uri_escape($b64), "\n";
This snippet takes a string from STDIN, encrypts it via AES, encodes it via Base64 and prints the result on STDOUT. It also prints a second line with the same string, but this time URL escaped. To test it, you would run it as follows on a shell, granted it’s stored at /path/to/encrypt.pl
.
echo -n 'username=testuser&server=example.org&password=testpass' \ | /path/to/encrypt.pl
This command would result in the output strings CI8VN8toaE40w8E4OH2rAuFj3Qev9QdLI/Wv/VaBCVK2yNkBZjxE9eafXkkrQfmYdeu01PquS5P40zhUq8Mfjg==
and CI8VN8toaE40w8E4OH2rAuFj3Qev9QdLI%2FWv%2FVaBCVK2yNkBZjxE9eafXkkrQfmYdeu01PquS5P40zhUq8Mfjg%3D%3D
. The sip:phone can use the former string to automatically fill in the login form of the Login Screen if started via a Link like sipphone://CI8VN8toaE40w8E4OH2rAuFj3Qev9QdLI/Wv/VaBCVK2yNkBZjxE9eafXkkrQfmYdeu01PquS5P40zhUq8Mfjg==
.
Here is the same code in PHP.
#!/usr/bin/php <?php $key = "iBmTdavJ8joPW3HO"; $iv = "tww21lQe6cmywrp3"; $clear = fgets(STDIN); $cipher = fnEncrypt($clear, $key, $iv); echo $cipher, "\n"; echo urlencode($cipher), "\n"; function fnEncrypt($clear, $key, $iv) { $pad = 16 - strlen($clear) % 16; $clear .= str_repeat(pack('C', $pad), $pad); return rtrim(base64_encode(mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $key, $clear, MCRYPT_MODE_CBC, $iv)), "\0"); } ?>
Similar to the perl version, you can call it like this:
echo -n 'username=testuser&server=example.org&password=testpass' \ | /path/to/encrypt.php
However, a URL with the sipphone://
schema is not displayed as a link in SMS or Email clients and thus can not be clicked by the end customer, so you need to make a detour via a normal http://
URL. To do so, you need a 3rd Party Launch Handler to trick the phone to open such a link.
This means that the 3rd Party Sign-Up Form needs to return a link with an URL pointing to the 3rd Party Launch Handler and pass the URL escaped string gathered above to the client via SMS or Email. Since it is a standard http://
link, it is click-able on the phone and can be launched from virtually any client (SMS, Email etc.) which properly renders an HTML link.
A possible SMS sent to the end customer (via the phone number entered in the sign-up from) could therefore look as follows (trying to stay below 140 chars).
http://example.org/p?c=CI8VN8toaE40w8E4OH2rAuFj3Qev9QdLI %2FWv%2FVaBCVK2yNkBZjxE9eafXkkrQfmYdeu01PquS5P40zhUq8Mfjg%3D%3D to launch sipphone
An HTML Email could look like this:
Welcome to Example.org, <a href="http://www.example.org/sipphone?c=CI8VN8toaE40w8E4OH2rAuFj3Qev9QdLI %2FWv%2FVaBCVK2yNkBZjxE9eafXkkrQfmYdeu01PquS5P40zhUq8Mfjg%3D%3D"> click here </a> to log in.
That way, you can on one hand verify the contact details of the user, and on the other hand send her the login credentials in a secure manner.
The URL http://www.example.org/sipphone
mentioned above can be any simple script, and its sole purpose is to send back a 301 Moved Permanently
or 302 Moved Temporarily
with a Location: sipphone://xxxxxxxxxxxx
header to tell the phone to open this link via the sip:phone app. The xxxxxxxxxxxx is actually the plain (non-URL-escaped) string generated by the script above.
An example CGI script performing this task follows.
#!/usr/bin/perl -w use strict; use CGI; my $q = CGI->new; my $c = $q->param('c'); print CGI::redirect("sipphone://$c");
The script simply takes the URL parameter c
from the URL http://www.example.org/sipphone?c=CI8VN8toaE40w8E4OH2rAuFj3Qev9QdLI%2FWv%2FVaBCVK2yNkBZjxE9eafXkkrQfmYdeu01PquS5P40zhUq8Mfjg%3D%3D
crafted above and puts its content into a Location
header using the sipphone://
schema, and finally sends a 301 Moved Permanently
back to the phone.
The phone follows the redirect by opening the URL using the sip:phone app, which in turn decrypts the content and fills in the login form.
Future versions of the sip:carrier will ship with this launch handler integrated in the system. Up until and including version mr4.1.1, this script needs to be installed on any webserver manually. |
The sip:phone provides mobile push functionality to remotely start the app via the Google GCM or Apple APNS notification systems on inbound calls, in case the app is not registered.
Although stopping the App on the phone and letting it wake up via the push notification system safes some battery power on the phone, the whole push notification concept is a best effort framework for both iOS and Android provided by Apple and Google, respectively, and is therefore not 100% reliable. |
If the mobile push functionality is enabled, the call-flow looks as follows if there are no devices registered for a subscriber.
In case of a timeout (no registration notification within a certain time) at the application server, the call is rejected with an error.
The push daemon needs your specific keys and/or certificates obtained from Apple and Google, respectively.
Please read the official GCM Getting Started Guide for Android on how to obtain a push notification key from Google for GCM.
For instructions how to generate Apple push notification certificates and keys, please read the official Provisioning Procedures from Apple.
The final configuration in your /etc/ngcp-config/config.yml should look as follows.
pushd: apns: certificate: '/etc/ssl/private/your.phone.push.dev.pem' enable: 'yes' endpoint: gateway.push.apple.com feedback_endpoint: feedback.push.apple.com feedback_interval: 3600 key: '' socket_timeout: 0 enable: 'yes' gcm: enable: 'yes' key: 'xxxxxxxxxxxxxxxxxxxxxxxx-yyyyyyyyyyyyyy' port: 45060 processes: 4 ssl: 'yes'
Once configured, execute ngcpcfg apply
to confirm your changes.