cpaas-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +4 -0
- data/LICENSE.md +1 -0
- data/README.md +25 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cpaas-sdk.gemspec +32 -0
- data/docs/Cpaas.html +446 -0
- data/docs/Cpaas/Conversation.html +1742 -0
- data/docs/Cpaas/Notification.html +301 -0
- data/docs/Cpaas/TwoFactor.html +908 -0
- data/docs/_index.html +146 -0
- data/docs/_index.md +21 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +496 -0
- data/docs/file.README.html +102 -0
- data/docs/file._index.html +94 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +94 -0
- data/docs/js/app.js +303 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +251 -0
- data/docs/mv_index.html +102 -0
- data/docs/top-level-namespace.html +663 -0
- data/examples/2fa/.env.example +6 -0
- data/examples/2fa/.gitignore +159 -0
- data/examples/2fa/.ruby-gemset +1 -0
- data/examples/2fa/.ruby-version +1 -0
- data/examples/2fa/Gemfile +8 -0
- data/examples/2fa/README.md +34 -0
- data/examples/2fa/app.rb +134 -0
- data/examples/2fa/config.ru +10 -0
- data/examples/2fa/helper.rb +37 -0
- data/examples/2fa/public/stylesheets/forms.css +28 -0
- data/examples/2fa/public/stylesheets/global.css +7 -0
- data/examples/2fa/public/stylesheets/layout.css +45 -0
- data/examples/2fa/public/stylesheets/main.css +3 -0
- data/examples/2fa/views/alert.erb +5 -0
- data/examples/2fa/views/dashboard.erb +4 -0
- data/examples/2fa/views/index.erb +17 -0
- data/examples/2fa/views/login.erb +13 -0
- data/examples/2fa/views/verify.erb +8 -0
- data/examples/sms/.env.example +4 -0
- data/examples/sms/.gitignore +159 -0
- data/examples/sms/.ruby-gemset +1 -0
- data/examples/sms/.ruby-version +1 -0
- data/examples/sms/Gemfile +8 -0
- data/examples/sms/README.md +80 -0
- data/examples/sms/app.rb +87 -0
- data/examples/sms/config.ru +10 -0
- data/examples/sms/helper.rb +33 -0
- data/examples/sms/public/scripts/notification.js +46 -0
- data/examples/sms/public/stylesheets/forms.css +28 -0
- data/examples/sms/public/stylesheets/global.css +7 -0
- data/examples/sms/public/stylesheets/layout.css +74 -0
- data/examples/sms/public/stylesheets/main.css +3 -0
- data/examples/sms/views/alert.erb +5 -0
- data/examples/sms/views/index.erb +48 -0
- data/lib/cpaas-sdk.rb +30 -0
- data/lib/cpaas-sdk/api.rb +139 -0
- data/lib/cpaas-sdk/config.rb +9 -0
- data/lib/cpaas-sdk/resources.rb +4 -0
- data/lib/cpaas-sdk/resources/conversation.rb +268 -0
- data/lib/cpaas-sdk/resources/notification.rb +62 -0
- data/lib/cpaas-sdk/resources/notification_channel.rb +39 -0
- data/lib/cpaas-sdk/resources/twofactor.rb +136 -0
- data/lib/cpaas-sdk/util.rb +93 -0
- data/lib/cpaas-sdk/version.rb +3 -0
- data/tutorials/2FA.md +109 -0
- data/tutorials/2fa-flow.png +0 -0
- data/tutorials/GetStarted.md +86 -0
- data/tutorials/SMSMessaging.md +132 -0
- data/tutorials/index.html +86 -0
- data/tutorials/quickstarts.yml +15 -0
- metadata +238 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
# Ignore the default SQLite database.
|
2
|
+
/db/*.sqlite3
|
3
|
+
/db/*.sqlite3-journal
|
4
|
+
|
5
|
+
# Ignore all logfiles and tempfiles.
|
6
|
+
/log/*
|
7
|
+
/tmp/*
|
8
|
+
!/log/.keep
|
9
|
+
!/tmp/.keep
|
10
|
+
|
11
|
+
# Ignore uploaded files in development
|
12
|
+
/storage/*
|
13
|
+
!/storage/.keep
|
14
|
+
|
15
|
+
.byebug_history
|
16
|
+
|
17
|
+
# Ignore master key for decrypting credentials and more.
|
18
|
+
/config/master.key
|
19
|
+
|
20
|
+
## App-Specific
|
21
|
+
|
22
|
+
# Ignore the generated sample apps folder.
|
23
|
+
/public/sample_apps
|
24
|
+
|
25
|
+
*.pdf
|
26
|
+
|
27
|
+
# Ignore the generated csv folder
|
28
|
+
/public/csv
|
29
|
+
|
30
|
+
## Capistrano
|
31
|
+
|
32
|
+
.env.staging
|
33
|
+
.env.production
|
34
|
+
.env.china
|
35
|
+
.env.developer
|
36
|
+
|
37
|
+
## Rails
|
38
|
+
|
39
|
+
*.rbc
|
40
|
+
*.sassc
|
41
|
+
.sass-cache
|
42
|
+
capybara-*.html
|
43
|
+
.rspec
|
44
|
+
/log
|
45
|
+
/tmp
|
46
|
+
/db/*.sqlite3
|
47
|
+
/db/*.sqlite3-journal
|
48
|
+
/public/system
|
49
|
+
/public/assets
|
50
|
+
/public/uploads
|
51
|
+
/public/docs
|
52
|
+
/coverage/
|
53
|
+
/spec/tmp
|
54
|
+
rerun.txt
|
55
|
+
pickle-email-*.html
|
56
|
+
dump.rdb
|
57
|
+
|
58
|
+
## Environment normalisation:
|
59
|
+
/.bundle
|
60
|
+
/vendor/bundle
|
61
|
+
|
62
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
63
|
+
.rvmrc
|
64
|
+
|
65
|
+
# if using bower-rails ignore default bower_components path bower.json files
|
66
|
+
/vendor/assets/bower_components
|
67
|
+
*.bowerrc
|
68
|
+
bower.json
|
69
|
+
|
70
|
+
# Ignore pow environment settings
|
71
|
+
.powenv
|
72
|
+
|
73
|
+
## Documentation cache and generated files:
|
74
|
+
/.yardoc/
|
75
|
+
/_yardoc/
|
76
|
+
/doc/
|
77
|
+
/rdoc/
|
78
|
+
|
79
|
+
# Developer-specific files - These have a corresponding *.example file as a template to quickly copy over
|
80
|
+
config/database.yml
|
81
|
+
.env
|
82
|
+
|
83
|
+
## General
|
84
|
+
|
85
|
+
# Git
|
86
|
+
**.orig
|
87
|
+
|
88
|
+
# OS X
|
89
|
+
.DS_Store
|
90
|
+
.DS_Store?
|
91
|
+
.AppleDouble
|
92
|
+
.LSOverride
|
93
|
+
|
94
|
+
# Icon must end with two \r
|
95
|
+
Icon
|
96
|
+
|
97
|
+
|
98
|
+
# Thumbnails
|
99
|
+
._*
|
100
|
+
|
101
|
+
# Files that might appear on external disk
|
102
|
+
.Spotlight-V100
|
103
|
+
.Trashes
|
104
|
+
|
105
|
+
# Directories potentially created on remote AFP share
|
106
|
+
.AppleDB
|
107
|
+
.AppleDesktop
|
108
|
+
Network Trash Folder
|
109
|
+
Temporary Items
|
110
|
+
.apdisk
|
111
|
+
|
112
|
+
# Windows image file caches
|
113
|
+
Thumbs.db
|
114
|
+
ehthumbs.db
|
115
|
+
|
116
|
+
# Folder config file
|
117
|
+
Desktop.ini
|
118
|
+
|
119
|
+
# Recycle Bin used on file shares
|
120
|
+
$RECYCLE.BIN/
|
121
|
+
|
122
|
+
# Windows Installer files
|
123
|
+
*.cab
|
124
|
+
*.msi
|
125
|
+
*.msm
|
126
|
+
*.msp
|
127
|
+
|
128
|
+
# Windows shortcuts
|
129
|
+
*.lnk
|
130
|
+
|
131
|
+
# Compiled source
|
132
|
+
*.com
|
133
|
+
*.class
|
134
|
+
*.dll
|
135
|
+
*.exe
|
136
|
+
*.o
|
137
|
+
*.so
|
138
|
+
|
139
|
+
# Packages
|
140
|
+
# it's better to unpack these files and commit the raw source
|
141
|
+
# git has its own built in compression methods
|
142
|
+
*.7z
|
143
|
+
*.dmg
|
144
|
+
*.gz
|
145
|
+
*.iso
|
146
|
+
*.jar
|
147
|
+
*.rar
|
148
|
+
*.tar
|
149
|
+
*.zip
|
150
|
+
|
151
|
+
# Logs and databases
|
152
|
+
*.log
|
153
|
+
*.sql
|
154
|
+
*.sql-e
|
155
|
+
*.sqlite
|
156
|
+
|
157
|
+
# Files generated by atom
|
158
|
+
*.tags
|
159
|
+
*.tags_swap
|
@@ -0,0 +1 @@
|
|
1
|
+
kandy-sdk-example-2fa
|
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.5.0
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Two Factor Authentication Starter App
|
2
|
+
|
3
|
+
This is an elementary login authentication use case of two-factor authentication via SMS. The main focus of this application is to understand and implement the 2FA flow, so least amount of stress is given to the authentication/login mechanism.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
1. Copy `.env.example` and rename to `.env` and add the appropriate values. Check `Configuration` section for more details.
|
7
|
+
2. To install dependencies, run:
|
8
|
+
```bash
|
9
|
+
bundle install
|
10
|
+
```
|
11
|
+
3. To start the server, run:
|
12
|
+
```bash
|
13
|
+
bundle exec rackup -p 6000
|
14
|
+
```
|
15
|
+
|
16
|
+
## Configuration
|
17
|
+
There are a few environment variables (check `.env` file) to make the application simpler and help us focus on the key aspects a two-factor authentication system via SMS. Some of the variables are pre-filled and some are left blank which are left on the user to place appropriate values. All the variables are mandatory.
|
18
|
+
|
19
|
+
ENV KEY | Description
|
20
|
+
------------- | -------------
|
21
|
+
CLIENT_ID | Private project key
|
22
|
+
CLIENT_SECRET | Private project secret
|
23
|
+
BASE_URL | URL of the CPaaS server to use
|
24
|
+
PHONE_NUMBER | Phone number that would receive the verification code
|
25
|
+
EMAIL | Email used in the login screen of the application
|
26
|
+
PASSWORD | Password to be entered against the EMAIL provided
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
The application comprises of three simple pages, login, code verification, dashboard/portal
|
30
|
+
> + On opening the application in the browser, the login screen is presented. The user needs to enter the `Email` / `Password` that are specified in the `.env` file and click on the `Login` button.
|
31
|
+
> + Once the credentials are verified, a verification code is sent out to the phone number and redirected to the code verification page. This phone number corresponds to the one entered in the `.env` file as `PHONE_NUMBER`.
|
32
|
+
> + The user now needs to enter the verification code received in the mentioned phone number and click `Verify` button.
|
33
|
+
> + The application verifies the entered code. If the code validates, the user is redirected to the dashboard section; else the user will be promoted with an error alert `Code invalid or expired` and is required to re-enter the verification code.
|
34
|
+
> + As the user is authenticated, the dashboard opens up. The user can logout from the dashboard and login screen would be presented.
|
data/examples/2fa/app.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'json'
|
3
|
+
require 'pry'
|
4
|
+
require 'cpaas-sdk'
|
5
|
+
|
6
|
+
require './helper'
|
7
|
+
|
8
|
+
|
9
|
+
class App < Sinatra::Application
|
10
|
+
enable :sessions
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super
|
14
|
+
|
15
|
+
# Initialize
|
16
|
+
Cpaas.configure do |config|
|
17
|
+
config.client_id = ENV['CLIENT_ID']
|
18
|
+
config.client_secret = ENV['CLIENT_SECRET']
|
19
|
+
config.base_url = ENV['BASE_URL']
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
get '/' do
|
24
|
+
redirect '/login'
|
25
|
+
end
|
26
|
+
|
27
|
+
get '/login' do
|
28
|
+
# If user is logged in and trying to access login page, redirect to dashboard.
|
29
|
+
return redirect '/dashboard' if is_logged_in? session
|
30
|
+
|
31
|
+
set_default_state(session)
|
32
|
+
|
33
|
+
erb :login, layout: :index
|
34
|
+
end
|
35
|
+
|
36
|
+
post '/login' do
|
37
|
+
if valid_credentials? params
|
38
|
+
# If login credentials are valid, send_code method is used to request 2FA code
|
39
|
+
# to the phone number as destination_address.
|
40
|
+
#
|
41
|
+
# If a valid response is received, the code_id present in the response is set in the session.
|
42
|
+
# This code_id is eventually used when the 2FA code (received in the phone number) needs to be verified.
|
43
|
+
# Once the code_id is set, the user is redirected to the code verification page
|
44
|
+
# where the user is prompted to enter the code received in the phone number.
|
45
|
+
#
|
46
|
+
# If an error is raised by send_code, it is caught in the catch block and the user is
|
47
|
+
# redirected to the login page with the received error message as an alert.
|
48
|
+
|
49
|
+
response = Cpaas::Twofactor.send_code({
|
50
|
+
destination_address: ENV['PHONE_NUMBER'],
|
51
|
+
message: 'Your verification code: {code}'
|
52
|
+
})
|
53
|
+
|
54
|
+
if response[:exception_id]
|
55
|
+
# Here something went wrong either with the server or proper parameters were not passed.
|
56
|
+
# Received error message is echoed back to the UI as error alert.
|
57
|
+
return erb :login, layout: :index, locals: { alert: { message: error_message(response), type: 'error' } }
|
58
|
+
end
|
59
|
+
|
60
|
+
session[:code_id] = response[:code_id]
|
61
|
+
set_credentials_verified(session)
|
62
|
+
|
63
|
+
redirect '/verify'
|
64
|
+
else
|
65
|
+
# If login credentials do not match with credentials present in .env, login page is re-rendered with error alert
|
66
|
+
erb :login, layout: :index, locals: { alert: { message: 'Invalid username or password', type: 'error' } }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
get '/verify' do
|
71
|
+
# If logged in and trying to access login page, redirect to dashboard.
|
72
|
+
return redirect '/dashboard' if is_logged_in? session
|
73
|
+
# If login credentials are not verified but tries to access the code verification page, user is redirected.
|
74
|
+
return redirect '/logout' if !is_credentials_verified? session
|
75
|
+
|
76
|
+
# If the login credentials are verified, user is shown code verification page.
|
77
|
+
erb :verify, layout: :index, locals: { alert: { message: "Verification code has been sent to #{ENV['PHONE_NUMBER']}", type: 'success' } }
|
78
|
+
end
|
79
|
+
|
80
|
+
post '/verify' do
|
81
|
+
# The 2FA code entered in the UI is passed to the verify_code along with codeId,
|
82
|
+
# which was saved from the response of send_code method.
|
83
|
+
#
|
84
|
+
# There are two valid response for verify_code method.
|
85
|
+
#
|
86
|
+
# Type 1 - The 2FA code is successfully verified.
|
87
|
+
# {
|
88
|
+
# verified: true,
|
89
|
+
# message: 'Verified'
|
90
|
+
# }
|
91
|
+
#
|
92
|
+
# Type 2 - The 2FA code pass is either incorrect or the code has expired
|
93
|
+
# (The expiry of the code can be changed by passing expiry param in the send_code. Ref - Documentation)
|
94
|
+
# {
|
95
|
+
# verified: false,
|
96
|
+
# message: 'Code expired or invalid'
|
97
|
+
# }
|
98
|
+
|
99
|
+
response = Cpaas::Twofactor.verify_code({
|
100
|
+
code_id: session[:code_id],
|
101
|
+
verification_code: params['code']
|
102
|
+
})
|
103
|
+
|
104
|
+
if response[:exception_id]
|
105
|
+
# Here something went wrong either with the server or proper parameters were not passed.
|
106
|
+
# Received error message is echoed back to the UI as error alert.
|
107
|
+
return erb :verify, layout: :index, locals: { alert: { message: error_message(response), type: 'error' } }
|
108
|
+
end
|
109
|
+
|
110
|
+
if response[:verified]
|
111
|
+
login session
|
112
|
+
# The code is verified and redirected to dashboard/portal/protected area of app.
|
113
|
+
return redirect '/dashboard'
|
114
|
+
else
|
115
|
+
# The code is invalid and error message received from server is shown as error alert.
|
116
|
+
return erb :verify, layout: :index, locals: { alert: { message: response[:message], type: 'error' } }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
get '/dashboard' do
|
121
|
+
# If not logged in, redirected to logout.
|
122
|
+
return redirect '/logout' if !is_logged_in? session
|
123
|
+
|
124
|
+
# Login criteria is fulfilled, renders dashboard/portal/protected area of app
|
125
|
+
erb :dashboard, layout: :index
|
126
|
+
end
|
127
|
+
|
128
|
+
get '/logout' do
|
129
|
+
# Logged in session is cleared
|
130
|
+
logout session
|
131
|
+
|
132
|
+
redirect '/login'
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
def valid_credentials?(params)
|
2
|
+
ENV['EMAIL'] == params['email'] && ENV['PASSWORD'] == params['password']
|
3
|
+
end
|
4
|
+
|
5
|
+
def error_message(error)
|
6
|
+
"#{error[:name]}: #{error[:message]} (#{error[:exception_id]})"
|
7
|
+
end
|
8
|
+
|
9
|
+
def set_credentials_verified(session)
|
10
|
+
session[:credentials_verified] = true
|
11
|
+
session[:code_verified] = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def is_credentials_verified?(session)
|
15
|
+
session[:credentials_verified] && !session[:code_verified]
|
16
|
+
end
|
17
|
+
|
18
|
+
def is_logged_in?(session)
|
19
|
+
session[:credentials_verified] && session[:code_verified]
|
20
|
+
end
|
21
|
+
|
22
|
+
def logout(session)
|
23
|
+
session[:credentials_verified] = true
|
24
|
+
session[:code_verified] = false
|
25
|
+
session[:code_id] = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_default_state(session)
|
29
|
+
session[:credentials_verified] = false
|
30
|
+
session[:code_verified] = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def login(session)
|
35
|
+
session[:credentials_verified] = true
|
36
|
+
session[:code_verified] = true
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
.input-group {
|
2
|
+
display: flex;
|
3
|
+
flex-direction: column;
|
4
|
+
}
|
5
|
+
|
6
|
+
input[type=text],
|
7
|
+
input[type=password] {
|
8
|
+
border-radius: 4px;
|
9
|
+
border: 1px solid #ccc;
|
10
|
+
box-sizing: border-box;
|
11
|
+
display: inline-block;
|
12
|
+
font-size: 14px;
|
13
|
+
margin: 8px 0;
|
14
|
+
padding: 12px 20px;
|
15
|
+
width: 100%;
|
16
|
+
}
|
17
|
+
|
18
|
+
button {
|
19
|
+
background-color: #4CAF50;
|
20
|
+
border-radius: 5px;
|
21
|
+
border: none;
|
22
|
+
color: white;
|
23
|
+
cursor: pointer;
|
24
|
+
font-size: 14px;
|
25
|
+
margin: 8px 0;
|
26
|
+
padding: 14px 20px;
|
27
|
+
width: 100%;
|
28
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
.box {
|
2
|
+
background-color: #f2f2f2;
|
3
|
+
border-radius: 5px;
|
4
|
+
border: 1px black solid;
|
5
|
+
height: 400px;
|
6
|
+
padding: 20px;
|
7
|
+
width: 300px;
|
8
|
+
display: flex;
|
9
|
+
flex-direction: column;
|
10
|
+
justify-content: center;
|
11
|
+
}
|
12
|
+
|
13
|
+
.centered-box {
|
14
|
+
margin: calc((50vh - 200px) / 2) auto;
|
15
|
+
}
|
16
|
+
|
17
|
+
.text-center {
|
18
|
+
text-align: center;
|
19
|
+
}
|
20
|
+
|
21
|
+
.alert {
|
22
|
+
align-items: center;
|
23
|
+
border-radius: 5px;
|
24
|
+
border: 1px solid transparent;
|
25
|
+
display: flex;
|
26
|
+
height: 30px;
|
27
|
+
justify-content: center;
|
28
|
+
left: 10%;
|
29
|
+
padding: 10px 20px;
|
30
|
+
position: absolute;
|
31
|
+
top: 10px;
|
32
|
+
width: 80%;
|
33
|
+
}
|
34
|
+
|
35
|
+
.alert-error {
|
36
|
+
color: #721c24;
|
37
|
+
background-color: #f8d7da;
|
38
|
+
border-color: #f5c6cb;
|
39
|
+
}
|
40
|
+
|
41
|
+
.alert-success {
|
42
|
+
color: #155724;
|
43
|
+
background-color: #d4edda;
|
44
|
+
border-color: #c3e6cb;
|
45
|
+
}
|