REM Connectivity to Asterisk server. ; REM Assumes that &user has been granted access to Asterisk Manager API; Local string &host = "192.168.1.200"; Local string &user = "asterisk_user_id"; Local string &pswd = "asterisk_password"; REM Asterisk information for how we will be originating phone calls; Local String &voip_provider_acct = "123456789</code><code>"; Local string &channel = "IAX2/" | </code><code>&voip_provider_acct</code><code>; Local string &context = "challenge-psft-user"; Local string &exten = "7189"; REM The phone number that we will be calling; REM This would normally come out of the user's profile; Local string &phone = "15105551212"; REM The PeopleSoft userID of the person to call; Local string &userID = "PTDMO"; REM This PIN could be autogenerated or stored in the DB; Local string &pinCode = "4554"; REM ******** No more user variables below here *********** ; Local string &base = "org.asteriskjava.manager."; Local JavaObject &connectFactory = CreateJavaObject(&base | "ManagerConnectionFactory", &host, &user, &pswd); Local JavaObject &connection = &connectFactory.createManagerConnection(); &connection.login(); Local JavaObject &originateAction = CreateJavaObject(&base | "action.OriginateAction"); Local JavaObject &vars = CreateJavaObject("java.util.HashMap"); &vars.put("PIN", &pinCode); &vars.put("PSFTUSERID", &userID); &originateAction.setChannel(&channel | "/" | &phone); &originateAction.setContext(&context); &originateAction.setVariables(&vars); &originateAction.setExten(&exten); &originateAction.setPriority(CreateJavaObject("java.lang.Integer", 1)); Local JavaObject &originateResponse = &connection.sendAction(&originateAction, 30000); Warning (&originateResponse.getResponse());
== Parsing '/etc/asterisk/manager.conf': Found == Manager 'asterisk_user_id' logged on from 192.168.1.11 -- Call accepted by 64.85.163.184 (format ulaw) -- Format for call is ulawAs soon as I answered the phone, then the Asterisk console shows
> Channel IAX2/123456789-2 was answered.If you’ll remember our original requirements, we needed some programmatic validation of a PIN code through the phone. The cool thing about Asterisk is that there are tons of built-in options for how you handle a call coming in. Here’s a snippet from the Asterisk configuration. This defines what Asterisk calls a “context” and what to do with a call into that context for extension 7189. The name of the context and the extension don’t really matter; we just need for our PeopleCode to match up with Asterisk has.
[challenge-psft-user] exten => 7189,1,Answer() exten =>One thing that may be a little confusing here is that we’re using Asterisk from two sides. One is our code that is calling the Asterisk Manager API that is initiating the call between my mobile phone and this context/extension definition within Asterisk. However, the Manager API is just initiating the call and then it’s done. The context/extension definition within Asterisk then says what to do with the call to this context/extension. Line 1 of the context/extension definition says to Answer the call. Line 2 plays a message that explains what is happening. On my mobile phone, I hear “This is the Grey Sparling demo login. “. Line 3 just logs what is happening on the Asterisk console. We use one of the variables that was set in the PeopleCode side so that we can match up calls with the PeopleSoft user accounts. Line 4 is a builtin Asterisk command to challenge the user to type in a PIN code. Here we’re using the PIN code that was set from the PeopleCode side. There are a series of voice prompts already delivered in Asterisk that get played as part of this as well as Asterisk “listening” for the DTMF tones from the buttons on the phone being pushed. You can roll your own handling of this within Asterisk (speech recognition anyone?), but the Authenticate command has a lot of built-in functionality for free so we make use of that. One strange thing worth mentioning here is the “j” parameter after the PIN code. That tells Asterisk to jump “+101” if the command fails (it continues on the next line if successful). It’s a bizarre form of GOTO (note that there are other ways of adding logic to Asterisk though). Then we log what happened on the console (depending on whether we get the right PIN code or not) and then hangup the phone. Here’s what the Asterisk console looks like with an invalid login.7189
,2,Playback(gs-demo-login) exten =>
7189
,3,NoOp(Authenticating user ${PSFTUSERID}) exten =>
7189
,4,Authenticate(${PIN},j) exten =>
7189
,5,NoOp(Successful login ${PSFTUSERID}) exten =>
7189
,6,Hangup() exten =>
7189
,105,NoOp(Unsuccessful login ${PSFTUSERID}) exten =>
7189
,106,Hangup()
-- Executing [7189@challenge-psft-user:1] Answer("IAX2/123456789-2", "") in new stack -- Executing [7189@challenge-psft-user:2] Playback("IAX2/123456789-2", "gs-demo-login") in new stack -- Playing 'gs-demo-login' (language 'en') == Manager 'asterisk_user_id' logged off from 192.168.1.11 -- Executing [7189@challenge-psft-user:3] NoOp("IAX2/123456789-2", "Authenticating user PTDMO") in new stack -- Executing [7189@challenge-psft-user:4] Authenticate("IAX2/123456789-2", "4554|j") in new stack -- Playing 'agent-pass' (language 'en') -- Playing 'auth-incorrect' (language 'en') -- Playing 'auth-incorrect' (language 'en') -- Executing [7189@challenge-psft-user:105] NoOp("IAX2/123456789-2", "Unsuccessful login PTDMO") in new stack -- Executing [7189@challenge-psft-user:106] Hangup("IAX2/123456789-2", "") in new stack == Spawn extension (challenge-psft-user, 7189, 106) exited non-zero on 'IAX2/123456789-2' -- Hungup 'IAX2/123456789-2'We can see that in this instance I didn’t type in the PIN code correctly, so I wouldn’t have been granted access. Here’s the relevant bits from the Asterisk console of a successful login.
-- Playing 'agent-pass' (language 'en') -- Playing 'auth-thankyou' (language 'en') -- Executing [7189@challenge-psft-user:5] NoOp("IAX2/123456789-3", "Successful login PTDMO") in new stack -- Executing [7189@challenge-psft-user:6] Hangup("IAX2/123456789-3", "") in new stackBut how do we find that out within the PeopleCode side so that we can actually take action? That will have to wait until part 2 One final note here. I mentioned that CallWithUs is pay by the drip. One reason that is important is because the pay by the drip VoIP providers are typically more open to initiating multiple calls at once (since you’re not paying a flat fee), which is something that you’d need for doing this for authenticating users. Once you’re comfortable with doing this sort of thing, then you might want to get your own internal phone folks involved, but since this sort of thing is fairly uncommon at this point, you’ll probably be on your own for your initial experiments in this. The nice thing is that it’s fairly cheap though. For each call to my mobile phone that was initiated while testing this I paid US$0.0125. So you get 80 login attempts for a buck 🙂
"Learn how you can reduce risk with rapid threat protection, audit response and access control. All from a single, comprehensive platform"
Trusted by hundreds of leading brands