Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0b5e710
commit 7239400
Showing
42 changed files
with
3,230 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# Implementation of OTPManager - One time password library | ||
|
||
### Project Integration | ||
|
||
Add below dependency to your build environment | ||
|
||
<!-- Slf4J logger --> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
<version>1.7.7</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-simple</artifactId> | ||
<version>1.7.7</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>commons-codec</groupId> | ||
<artifactId>commons-codec</artifactId> | ||
<version>1.9</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.jasypt</groupId> | ||
<artifactId>jasypt</artifactId> | ||
<version>1.9.0</version> | ||
</dependency> | ||
Or copy all the libraries from OTPManager-1.0.0-archive\lib into your application classpath. | ||
|
||
* Add OTPManager-1.0.0-archive/OTPManager-1.0.0.jar' into your pom.xml file or copy it into your application classpath. | ||
* Copy OTPManager-1.0.0-archive/config/otp.properties' file into your configuration directory and change 'ISSUER.NAME' value. | ||
|
||
### Implementation | ||
* UserInfo: Need to be created in third-party application and make it persistent either in database file or flat file. | ||
It stores OTP related details details of User. Check UserInfo in OTPManager Javadoc or [example] (https://github.com/GSLabDev/OTPManager/tree/master/example) project. | ||
|
||
* IUSerInfoDAO: Must implement and initialize in OTPManager, It required to read/write userInfo object from/to the database. Check example\src\com\gslab\otp\example\UserInfoDAOImpl class for details. | ||
|
||
* IEncryptor: OTPManager comes with default AESEncryptor which do encrypt/decrypt the shared secret but for security purpose | ||
it must be implemented by third party Web Application. Check example\src\com\gslab\otp\example\AESEncryptor class for details. | ||
|
||
* OtpHandler: OTPManager has init(...) which is designed to be called only once. To handle OTPManager in multi threading environment, | ||
Caller should has to create one handler class which must be double checked singleton and it internally call all OTPManager API’s. Check example\src\com\gslab\otp\example\OtpHandler class for more details. | ||
|
||
### Usage | ||
|
||
The following code is designed to be called only once in the application lifetime. | ||
|
||
OTPManager otpManager = new OTPManager(); | ||
otpManager.init(otpFilePath, UserInfoDAOImpl, EncryptorImpl) | ||
|
||
Where optFilePath -> Path of otp.properties file | ||
UserInfoDAOImpl -> Implementation of IuserInfoDAO to perform read/write userInfo into the database. | ||
EncryptorImpl -> Implementation of IEncryptor which encrypt/decrypt the shared Secret. | ||
|
||
The above code must be called inside the getInstance() of a Singleton class e.g. OtpHandler class as explained above. | ||
|
||
private static volatile OtpHandler instance = null; | ||
public static OtpHandler getInstance() throws OTPManagerException { | ||
if (instance == null) { // single checked | ||
synchronized (OtpHandler.class) { | ||
if (instance == null) { // double checked | ||
instance = new OtpHandler(); | ||
otpManager = new OTPManager(); | ||
// specify the filepath of otp.properties file | ||
otpFile = new File("config", OTP_FILE); | ||
// For storing userInfo detail,Temporary we are using flat file | ||
// rather than database. We HAVE TO implement IUserInfoDAO | ||
// for reading/writing userInfo Entity from database | ||
userInfoDAO = new UserInfoDAOImpl(); | ||
// using bydefault Encryptor for encrypting/decryping shared | ||
// secret,Ideally we should implement our Encryptor by | ||
// implementing IEncryptor interface for Encryption | ||
encryptor = new AESEncryptor(); | ||
|
||
// Should be initialize while starting the application and should | ||
// not be called more than once in whole Application | ||
otpManager.init(otpFile, userInfoDAO, encryptor); | ||
} | ||
} | ||
} | ||
return instance; | ||
} | ||
To enable OTP for a user,It has to register to OTPManager to get the qrCodeURL. | ||
|
||
UserInfo userInfo = new UserInfo(); | ||
userInfo.setAccountName(“ACCOUNTNAME”);//accountName of user | ||
userInfo.setType(Type.TOTP);// OTP Type | ||
String qrCodeURL = otpHandler.getInstance().register(userInfo); | ||
It returns qrcodeUrl using which caller can generate QRCODE image or you can use OTPManager Utility class to get QRCodeBaseURL which will display Image qrcode directly at runtime. | ||
|
||
String qrcodeBaseURL = Utils.getQRCodeAsURL(qrcode, 200, 200); | ||
|
||
The following code verifies the OTP code against the QRCode Image. | ||
|
||
String boolean = otpHandler.getInstance()..verifyOTP(otpCode, userId) | ||
Please refer to the [examples](https://github.com/GSLabDev/OTPManager/tree/master/example) sub-directory for more details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
OTPManager - One time password library | ||
|
||
Copyright (c) 2016, Great Software Laboratory Private Limited. | ||
All rights reserved. | ||
|
||
Contributor: Abdul Waheed [abdul.waheed@gslab.com] | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
* Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
* Neither the name of the "Great Software Laboratory Private Limited" nor the | ||
names of its contributors may be used to endorse or promote products | ||
derived from this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY | ||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,59 @@ | ||
# OTPManager | ||
OTPManager - One time password library | ||
============================================== | ||
|
||
Copyright (c) 2016, [Great Software Laboratory Private Limited](http://gslab.com/). | ||
|
||
Contributor: Abdul Waheed [abdul.waheed@gslab.com] | ||
|
||
[https://github.com/GSLabDev/OTPManager](https://github.com/GSLabDev/OTPManager) | ||
|
||
**OTPManager** is a pluggable component that implements Time-based One-time Password [TOTP] (https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm) algorithm specified in RFC 6238 and HMAC based One-time Password [HOTP] (https://en.wikipedia.org/wiki/HMAC-based_One-time_Password_Algorithm) algorithm specified in RFC 4226. Using this component, a web application can support OTP Authentication without worrying much about the OTP implementation. It easily provide additional layer of security i.e. two factor authentication in any web application. | ||
|
||
**OTPManager** is licensed under the Open Source License. | ||
|
||
**Client Application** | ||
|
||
**OTPManager** will act as Authenticator server whereas Google Authenticator application (available for [iOS] (https://itunes.apple.com/in/app/google-authenticator/id388497605), [Android] (https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2), [BlackBerry] (https://appworld.blackberry.com/webstore/content/29401059) and [Windows] (https://www.microsoft.com/en-us/store/p/authenticatorg/9nblggh082hc) ) as a client to generates OTP code. | ||
|
||
**Library Documentation** | ||
|
||
This library includes full JavaDoc documentation and an example code to understand implementation of **OTPManager** library in a better way. | ||
|
||
# Usage | ||
|
||
## Requirements ( build dependencies ) | ||
* Java Version 6 or above | ||
* Apache Maven 3 or higher | ||
|
||
## Instructions | ||
|
||
### Build | ||
|
||
mvn clean install | ||
|
||
It will create the 'OTPManager-1.0.0-archive.zip' file under OTPManager/target directory which will be having 'OTPManager-1.0.0.jar' | ||
as well as all others dependencies required for this project. It also contains one properties file named otp.properties. | ||
|
||
### Usage in code | ||
|
||
See [examples](https://github.com/GSLabDev/OTPManager/tree/master/example) for working example. | ||
|
||
## Documentation | ||
|
||
The API documentation will get generated after mvn install under OTPManager/target/apidocs directory. | ||
|
||
For OTPManager library implementation details, see | ||
[IMPLEMENTATION.md](https://github.com/GSLabDev/libasynckafkaclient/blob/master/IMPLEMENTATION.md) | ||
|
||
|
||
## Examples | ||
|
||
See the [examples](https://github.com/GSLabDev/OTPManager/tree/master/example) sub-directory. | ||
|
||
|
||
## Support | ||
|
||
File bug reports, feature requests and questions using | ||
[GitHub Issues](https://github.com/GSLabDev/OTPManager/issues) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# The initial windowSize used when validating the codes. We are using Google's default behaviour of using a window size equal to 3. The range should be between 1 to 10 | ||
TOTP.WINDOWSIZE=3 | ||
|
||
# look-ahead parameters on the server to make it in sync. The range should be between 1 to 10. | ||
HOTP.WINDOWSIZE = 5 | ||
|
||
#REQUIRED if TYPE is HOTP, The counter parameter is required when provisioning a key for use with HOTP. It will set the initial counter value. | ||
HOTP.COUNTER=1 | ||
|
||
#throttling parameter which defines the maximum number of possible attempts for One-Time Password validation. | ||
MAX.OTP.FAILURE =5 | ||
|
||
#The issuer parameter is a string value indicating the provider or service this account is associated with. | ||
# Valid values corresponding to the label prefix examples above would be: ISSUER.NAME=Example, ISSUER.NAME=Provider1, and ISSUER.NAME=Big%20Corporation. | ||
ISSUER.NAME=OTP_EXAMPLE |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/** | ||
* Copyright 2014 GSLAB. All Rights Reserved. | ||
*/ | ||
package com.gslab.otp.example; | ||
|
||
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.gslab.otp.IEncryptor; | ||
import com.gslab.otp.OTPManagerException; | ||
|
||
/** | ||
* The AESEncryptor class implements {@link IEncryptor} interface. This class | ||
* provides the mechanism of Encrypting/Decrypting the Base32 encoded shared | ||
* Secret. {@link OTPManager} uses this class as default for encryption which | ||
* can be override during initialization. | ||
* | ||
* @author abdul.waheed@gslab.com (Abdul Waheed) | ||
* @version 1.0 | ||
* | ||
*/ | ||
public class AESEncryptor implements IEncryptor { | ||
|
||
private StandardPBEStringEncryptor encrytor; | ||
|
||
/** | ||
* The logger for this class | ||
*/ | ||
private static final Logger LOG = LoggerFactory | ||
.getLogger(AESEncryptor.class); | ||
|
||
public AESEncryptor() { | ||
encrytor = new StandardPBEStringEncryptor(); | ||
encrytor.setAlgorithm("PBEWithMD5AndDES"); | ||
|
||
// Ideally the password should not be maintained directly in the | ||
// source code, but rather kept someplace secure | ||
encrytor.setPassword("ZgPiPSCdq88K8Mfay7T7IA"); | ||
} | ||
|
||
/* | ||
* (non-Javadoc) | ||
* | ||
* @see com.gslab.otp.IEncryptor#encrypt(java.lang.String) | ||
*/ | ||
public String encrypt(String sharedSecret) throws OTPManagerException { | ||
LOG.info("Encrypting shared Secret..."); | ||
if (sharedSecret == null || sharedSecret.isEmpty()) { | ||
LOG.error("SharedSecret cannot be null or empty"); | ||
throw new OTPManagerException( | ||
"SharedSecret cannot be null or empty"); | ||
} | ||
String encryptedKey = null; | ||
try { | ||
encryptedKey = encrytor.encrypt(sharedSecret); | ||
} catch (Exception e) { | ||
LOG.error("Error while encrypting sharedSecret {}", e.getMessage(), | ||
e); | ||
throw new OTPManagerException( | ||
"Error while encrypting sharedSecret " + e.getMessage(), e); | ||
} | ||
LOG.debug("Encrypted Shared Secret successfully"); | ||
return encryptedKey; | ||
} | ||
|
||
/* | ||
* (non-Javadoc) | ||
* | ||
* @see com.gslab.otp.IEncryptor#decrypt(java.lang.String) | ||
*/ | ||
public String decrypt(String sharedSecret) throws OTPManagerException { | ||
LOG.info("Decrypting shared Secret..."); | ||
String decryptedKey = null; | ||
if (sharedSecret == null || sharedSecret.isEmpty()) { | ||
LOG.error("SharedSecret cannot be null or empty"); | ||
throw new OTPManagerException( | ||
"SharedSecret cannot be null or empty"); | ||
} | ||
try { | ||
decryptedKey = encrytor.decrypt(sharedSecret); | ||
} catch (Exception e) { | ||
// for Invalid sharedSecret, e.getMessage will be null | ||
LOG.error("Error while decrypting sharedSecret {}", e.getMessage(), | ||
e); | ||
throw new OTPManagerException( | ||
"Error while decrypting sharedSecret " + e.getMessage(), e); | ||
} | ||
LOG.debug("Decrypted Shared Secret successfully"); | ||
return decryptedKey; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/** | ||
* Copyright 2014 GSLAB. All Rights Reserved. | ||
*/ | ||
package com.gslab.otp.example; | ||
|
||
import javax.xml.bind.JAXBContext; | ||
import javax.xml.bind.JAXBException; | ||
import javax.xml.bind.Marshaller; | ||
import javax.xml.bind.Unmarshaller; | ||
|
||
/** | ||
* This is utility class used to do all JAXB serialization to/from disk. Please | ||
* use this whenever you need to read/write all configuration classes from/to | ||
* disk. It also requires that all JAXB serializeable classes are included into | ||
* jaxb.index. | ||
* | ||
* @author abdul.waheed@gslab.com (Abdul Waheed) | ||
* | ||
*/ | ||
public class JAXBUtil { | ||
|
||
private static JAXBContext context; | ||
|
||
private static Marshaller marshaller; | ||
private static Unmarshaller unmarshaller; | ||
|
||
private static JAXBContext getContext() throws JAXBException { | ||
if (context == null) { | ||
context = JAXBContext.newInstance(JAXBUtil.class.getPackage() | ||
.getName()); | ||
} | ||
return context; | ||
|
||
} | ||
|
||
public static Marshaller getMarshaller() throws JAXBException { | ||
if (marshaller == null) { | ||
marshaller = getContext().createMarshaller(); | ||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); | ||
} | ||
return marshaller; | ||
} | ||
|
||
public static Unmarshaller getUnmarshaller() throws JAXBException { | ||
if (unmarshaller == null) { | ||
unmarshaller = getContext().createUnmarshaller(); | ||
} | ||
return unmarshaller; | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.