Skip to content

Commit

Permalink
Two-Factor Authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
alexivanov committed Aug 5, 2017
1 parent ee150b1 commit 359ff38
Show file tree
Hide file tree
Showing 47 changed files with 2,547 additions and 38 deletions.
212 changes: 212 additions & 0 deletions api-docs/apiLive.htm
Expand Up @@ -2629,6 +2629,22 @@ <h2 class="flybar-button">User</h2>
<td></td>
</tr>
<tr>
<td><a href="#twofactor">Two-Factor Authentication</a>a</td>
<td>twofactor</td>
<td><a href="#twofacor_request">Request OTP</a></td>
<td><a href="#twofactor_deliverymethods">List OTP delivery methods</a></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>twofactor/validate</td>
<td><a href="#twofacor_validate">Validate OTP</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="#users">User</a></td>
<td>users</td>
<td><a href="#users_create">Create a User</a></td>
Expand Down Expand Up @@ -2942,6 +2958,16 @@ <h2 class="flybar-button">System</h2>
external service Configuration</a></td>
<td></td>
</tr>
<tr>
<td><a href="#twofactor_config_get">Two-Factor Configuration</a></td>
<td>twofactor/configure</td>
<td></td>
<td><a href="#twofactor_config_get">Retrieve
Two-Factor Configuration</a></td>
<td><a href="#twofactor_config_update">Update
Two-Factor Configuration</a></td>
<td></td>
</tr>
</table>
</div>
</div>
Expand Down Expand Up @@ -3930,6 +3956,11 @@ <h3>Authentication Overview</h3>
Default authentication is using HTTP Basic Auth. Oauth2 can be enabled by using <i>-Psecurity=oauth</i> option on gradle build command , refer
the platform setup <a href="https://github.com/openMF/mifosx/wiki/Launching-platform-server-locally-from-the-command-line#choosing-authentication-mechanism"> wiki</a> for additional details.
</p>
<p>
Optionally, two-factor authentication can be enabled by using
<i>-Ptwofactor=enabled</i> on gradle build.
Details of the authentication workflow with two-factor authentication enabled can be found <a href="#twofactor">here</a>.
</p>
<p>
The platform has been configured to reject plain HTTP requests and
to expect all API requests to be made over <a
Expand Down Expand Up @@ -4057,6 +4088,120 @@ <h3>Authentication Oauth2</h3>
</code>
</div>
</div>
<a id="twofactor" name="twofactor" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h3>Two-Factor Authentication</h3>
<p>
Two-Factor authentication is supported by requesting & verifying
one-time passwords(OTP). OTPs are sent via SMS & email.
</p>
<p>
By default, two-factor authentication is disabled by default.
More information on how to enable TFA can be found <a href="#authentication_overview">here</a>.
</p>
<p>
Two-factor authentication workflow:
<ol class="normalli">
<li class="normalli">User authticates via BasicAuth / oAauth</li>
<li>Client requests a list of supported OTP delivery methods for the authenticated user(<a href="#twofactor_deliverymethods">Get Delivery Methods</a>)</li>
<li>User selects an OTP delivery method and client sends a request for OTP(<a href="#twofacor_request">Request OTP</a>)</li>
<li>User receives an OTP and the client sends it for verification(<a href="#twofactor_validate">Validate OTP</a>)</li>
<li>If the OTP is valid, an access token is returned</li>
<li>The access token is sent in following requestes to the server as a header <i>Fineract-Platform-TFA-Token</i></li>
</ol>
</p>
<p>
Two-Factor authentication and delivery methods can be configured via
the <a href="#twofactor_configure"<i>/twofactor/configure</i> endpoint.</a>
</p>
</div>
<div class="method-example">

</div>
</div>

<a id="twofactor_deliverymethods" name="twofactor_deliverymethods" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Get Delivery Methods</h4>
<p>Returns a list of possible OTP delivery methods for the current user</p>
<p>Requres first-factor authenticated user.</p>
</div>
<div class="method-example">
<code class="method-declaration">GET https://DomainName/api/v1/twofactor</code>
<code class="method-response">
[
{
"name": "sms",
"target": "08888888888"
},
{
"name": "email",
"target": "user@example.com"
}
]</code>
</div>
</div>

<a id="twofacor_request" name="twofactor_request" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Request OTP</h4>
<p>Requests an OTP.</p>
<p>Requres first-factor authenticated user.</p>
<h5>Arguments</h5>
<dl class="argument-list">
<dt>deliveryMethod</dt>
<dd>
String<span> mandatory, the delivery method name</span>
</dd>
<dt>extendedToken</dt>
<dd>
boolean<span> optional, whether to request an extended token, default false</span>
</dd>
</dl>
</div>
<div class="method-example">
<code class="method-declaration">POST https://DomainName/api/v1/twofactor?deliveryMethod=sms&extendedToken=false</code>
<code class="method-response">
{
"requestTime": 1500000000000,
"tokenLiveTimeInSec": 300,
"extendedAccessToken": false,
"deliveryMethod": {
"name": "sms",
"target": "08888888888"
}
}</code>
</div>
</div>

<a id="twofacor_validate" name="twofacor_validate" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Validate OTP</h4>
<p>Validates an OTP. If the OTP is valid, an access token is created.</p>
<p>The returned access token is later sent as a header <i>Fineract-Platform-TFA-Token</i>.</p>
<p>Requres first-factor authenticated user.</p>
<h5>Arguments</h5>
<dl class="argument-list">
<dt>token</dt>
<dd>
String<span> mandatory, the OTP to validate</span>
</dd>
</dl>
</div>
<div class="method-example">
<code class="method-declaration">POST https://DomainName/api/v1/twofactor?token=YYYYY</code>
<code class="method-response">
{
"token": "cb0bb6e33fc540709d50a16eb2e555f9",
"validFrom": 1501530702801,
"validTo": 1501617102801
}</code>
</div>
</div>

<a id="batch_api" name="batch_api" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
Expand Down Expand Up @@ -19391,6 +19536,73 @@ <h4>Update External Service</h4>
</div>
</div>

<a id="twofactor_config" name="twofactor_config"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h3>Two-Factor Configuration</h3>
<p>The following section describes the way to configure two-factor authentication</p>
<p>Two-Factor Authentication has to be enabled by either building with Gradle arguments
<i>-Ptwofactor=enabled</i> or enabling the <i>twofactor</i> profile via env. variable
</p>
<p>In order for SMS to be enabled an SMS bridge has to be setup with the message-gateway service.</p>
</div>
<div class="method-example">
</div>
</div>

<a id="twofactor_config_get" name="twofactor_config_get" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve Two-Factor Configuration</h4>
<p>Returns available two-factor configuration.</p>
</div>
<div class="method-example">
<code class="method-declaration"> GET https://DomainName/api/v1/twofactor/configure
</code>
<code class="method-response">
{
"otp-delivery-email-body": "Hello {{username}}.\n\nYour OTP login token is {{token}}.",
"otp-delivery-sms-enable": true,
"otp-delivery-sms-provider": 6,
"otp-delivery-email-subject": "Fineract Two-Factor Authentication Token",
"otp-token-length": 5,
"access-token-live-time-extended": 604800,
"otp-delivery-email-enable": true,
"otp-token-live-time": 300,
"otp-delivery-sms-text": "Your authentication token for Fineract is {{token}}.",
"access-token-live-time": 86400
}
</code>
</div>
</div>

<a id="twofactor_config_update" name="twofactor_config_update" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Update Two-Factor Configuration</h4>
<p>Update two-factor configuration.</p>
</div>
<div class="method-example">
<code class="method-declaration"> PUT https://DomainName/api/v1/twofactor/configure
</code>
<code class="method-request">
{
"otp-delivery-sms-provider": 7
"otp-delivery-sms-enable": false
}
</code>
<code class="method-response">
{
"changes": {
"otp-delivery-sms-enable": false,
"otp-delivery-sms-provider": 7
}
}
</code>
</div>
</div>

<!-- Fund starts here -->
<a id="funds" name="funds" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
Expand Down
4 changes: 4 additions & 0 deletions api-docs/apidocs.css
Expand Up @@ -745,4 +745,8 @@ ul.field li {

tt {
font-size: 9.5pt;
}

ol.normalli li {
list-style-type: decimal;
}
36 changes: 26 additions & 10 deletions fineract-provider/build.gradle
Expand Up @@ -193,17 +193,33 @@ if (project.hasProperty('env') && project.getProperty('env') == 'dev') {

/* Enable Oauth2 authentication based on environment, default to HTTP basic auth */
if (project.hasProperty('security') && project.getProperty('security') == 'oauth') {
copy {
from './properties/oauth/'
into 'src/main/resources/'
include '*.properties'
}
if(project.hasProperty('twofactor') && project.getProperty('twofactor') == 'enabled') {
copy {
from './properties/oauth/twofactor/'
into 'src/main/resources/'
include '*.properties'
}
} else {
copy {
from './properties/oauth/'
into 'src/main/resources/'
include '*.properties'
}
}
} else {
copy {
from './properties/basicauth/'
into 'src/main/resources/'
include '*.properties'
}
if(project.hasProperty('twofactor') && project.getProperty('twofactor') == 'enabled') {
copy {
from './properties/basicauth/twofactor/'
into 'src/main/resources/'
include '*.properties'
}
} else {
copy {
from './properties/basicauth/'
into 'src/main/resources/'
include '*.properties'
}
}
}

task dist(type:Zip){
Expand Down
@@ -0,0 +1,21 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

spring.profiles.default=basicauth
spring.profiles.active=basicauth,twofactor
@@ -0,0 +1,21 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

spring.profiles.default=basicauth
spring.profiles.active=oauth,twofactor
Expand Up @@ -2904,7 +2904,7 @@ public CommandWrapperBuilder deleteSmsCampaign(final Long resourceId) {
this.href = "/smscampaigns/"+resourceId;
return this;
}

public CommandWrapperBuilder holdAmount(final Long accountId) {
this.actionName = "HOLDAMOUNT";
this.entityName = "SAVINGSACCOUNT";
Expand Down Expand Up @@ -2977,4 +2977,11 @@ public CommandWrapperBuilder unblockSavingsAccount(final Long accountId) {
this.href = "/savingsaccounts/" + accountId + "?command=unblock";
return this;
}

public CommandWrapperBuilder updateTwoFactorConfiguration() {
this.actionName = "UPDATE";
this.entityName = "TWOFACTOR_CONFIGURATION";
this.href = "/twofactor/configure";
return this;
}
}
Expand Up @@ -85,5 +85,12 @@ public interface ConfigurationDomainService {
Long getDailyTPTLimit();

void removeGlobalConfigurationPropertyDataFromCache(String propertyName);


boolean isSMSOTPDeliveryEnabled();

boolean isEmailOTPDeliveryEnabled();

Integer retrieveOTPCharacterLength();

Integer retrieveOTPLiveTime();
}

0 comments on commit 359ff38

Please sign in to comment.