README.md in rotp-3.3.1 vs README.md in rotp-4.0.0
- old
+ new
@@ -2,21 +2,29 @@
[![Build Status](https://travis-ci.org/mdp/rotp.svg?branch=master)](https://travis-ci.org/mdp/rotp)
[![Gem Version](https://badge.fury.io/rb/rotp.svg)](https://rubygems.org/gems/rotp)
[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/mdp/rotp/blob/master/LICENSE)
-A ruby library for generating one time passwords (HOTP & TOTP) according to [RFC 4226](http://tools.ietf.org/html/rfc4226) and [RFC 6238](http://tools.ietf.org/html/rfc6238).
+A ruby library for generating and validating one time passwords (HOTP & TOTP) according to [RFC 4226](http://tools.ietf.org/html/rfc4226) and [RFC 6238](http://tools.ietf.org/html/rfc6238).
-ROTP is compatible with the [Google Authenticator](https://github.com/google/google-authenticator) available for [Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2) and [iPhone](https://itunes.apple.com/en/app/google-authenticator/id388497605).
+ROTP is compatible with [Google Authenticator](https://github.com/google/google-authenticator) available for [Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2) and [iPhone](https://itunes.apple.com/en/app/google-authenticator/id388497605) and any other TOTP based implementations.
-Many websites use this for [multi-factor authentication](https://www.youtube.com/watch?v=17rykTIX_HY), such as GMail, Facebook, Amazon EC2, WordPress, and Salesforce. You can find the whole [list here](https://en.wikipedia.org/wiki/Google_Authenticator#Usage).
+Many websites use this for [multi-factor authentication](https://www.youtube.com/watch?v=17rykTIX_HY), such as GMail, Facebook, Amazon EC2, WordPress, and Salesforce. You can find a more complete [list here](https://en.wikipedia.org/wiki/Google_Authenticator#Usage).
## Dependencies
* OpenSSL
-* Ruby 1.9.3 or higher
+* Ruby 2.0 or higher
+## Breaking changes in >= 4.0
+
+- Simplified API
+ - `verify` now takes options for `drift` and `after`
+ - `verify` returns a timestamp if true, nil if false
+- Dropping support for Ruby < 2.0
+- Docs for 3.x can be found [here](https://github.com/mdp/rotp/tree/v3.3.0)
+
## Installation
```bash
gem install rotp
```
@@ -24,24 +32,21 @@
## Library Usage
### Time based OTP's
```ruby
-totp = ROTP::TOTP.new("base32secret3232")
+totp = ROTP::TOTP.new("base32secret3232", issuer: "My Service")
totp.now # => "492039"
-# OTP verified for current time
-totp.verify("492039") # => true
+# OTP verified for current time - returns timestamp of the current interval
+# period.
+totp.verify("492039") # => 1474590700
+
sleep 30
-totp.verify("492039") # => false
-```
-Optionally, you can provide an issuer which will be used as a title in Google Authenticator.
-
-```ruby
-totp = ROTP::TOTP.new("base32secret3232", issuer: "My Service")
-totp.provisioning_uri("alice@google.com")
+# OTP fails to verify - returns nil
+totp.verify("492039") # => nil
```
### Counter based OTP's
```ruby
@@ -49,73 +54,80 @@
hotp.at(0) # => "786922"
hotp.at(1) # => "595254"
hotp.at(1401) # => "259769"
# OTP verified with a counter
-hotp.verify("259769", 1401) # => true
-hotp.verify("259769", 1402) # => false
+hotp.verify("316439", 1401) # => 1401
+hotp.verify("316439", 1402) # => nil
```
-### Verifying a Time based OTP with drift
-
-Some users devices may be slightly behind or ahead of the actual time. ROTP allows users to verify
-an OTP code with an specific amount of 'drift'
-
-```ruby
-totp = ROTP::TOTP.new("base32secret3232")
-totp.now # => "492039"
-
-# OTP verified for current time with 120 seconds allowed drift
-totp.verify_with_drift("492039", 60, Time.now - 30) # => true
-totp.verify_with_drift("492039", 60, Time.now - 90) # => false
-```
-
### Preventing reuse of Time based OTP's
-In order to prevent reuse of time based tokens within the interval window (default 30 seconds)
-it is necessary to store the last time an OTP was used. The following is an example of this in action:
+By keeping track of the last time a user's OTP was verified, we can prevent token reuse during
+the interval window (default 30 seconds)
+The following is an example of this in action:
+
```ruby
User.find(someUserID)
totp = ROTP::TOTP.new(user.otp_secret)
totp.now # => "492039"
-user.last_otp_at # => 1472145530
+user.last_otp_at # => 1432703530
# Verify the OTP
-verified_at_timestamp = totp.verify_with_drift_and_prior("492039", 0, user.last_otp_at) #=> 1472145760
+last_otp_at = totp.verify("492039", after: user.last_otp_at) #=> 1472145760
+# ROTP returns the timestamp(int) of the current period
# Store this on the user's account
-user.update(last_otp_at: verified_at_timestamp)
-verified_at_timestamp = totp.verify_with_drift_and_prior("492039", 0, user.last_otp_at) #=> false
+user.update(last_otp_at: last_otp_at)
+# Someone attempts to reused the OTP inside the 30s window
+last_otp_at = totp.verify("492039", after: user.last_otp_at) #=> nil
+# It fails to verify because we are still in the same 30s interval window
```
+### Verifying a Time based OTP with drift
+
+Some users may enter a code just after it has expired. By adding 'drift' you can allow
+for a recently expired token to remain valid.
+
+```ruby
+totp = ROTP::TOTP.new("base32secret3232")
+now = Time.at(1474590600) #2016-09-23 00:30:00 UTC
+totp.at(now) # => "250939"
+
+# OTP verified for current time along with 15 seconds earlier
+# ie. User enters a code just after it expired
+totp.verify("250939", drift_behind: 15, at: now + 35) # => 1474590600
+# User waits too long. Fails to validate previous OTP
+totp.verify("250939", drift_behind: 15, at: now + 45) # => nil
+```
+
### Generating a Base32 Secret key
```ruby
-ROTP::Base32.random_base32 # returns a 16 character base32 secret. Compatible with Google Authenticator
+ROTP::Base32.random_base32 # returns a 32 character base32 secret. Compatible with Google Authenticator
```
Note: The Base32 format conforms to [RFC 4648 Base32](http://en.wikipedia.org/wiki/Base32#RFC_4648_Base32_alphabet)
-### Google Authenticator Compatible URI's
+### Generating QR Codes for provisioning mobile apps
-Provisioning URI's generated by ROTP are compatible with the Google Authenticator App
-to be scanned with the in-built QR Code scanner.
+Provisioning URI's generated by ROTP are compatible with most One Time Password applications, including
+Google Authenticator.
```ruby
totp.provisioning_uri("alice@google.com") # => 'otpauth://totp/issuer:alice@google.com?secret=JBSWY3DPEHPK3PXP'
hotp.provisioning_uri("alice@google.com", 0) # => 'otpauth://hotp/issuer:alice@google.com?secret=JBSWY3DPEHPK3PXP&counter=0'
```
-This can then be rendered as a QR Code which can then be scanned and added to the users
-list of OTP credentials.
+This can then be rendered as a QR Code which the user can scan using their mobile phone and the appropriate application.
#### Working example
Scan the following barcode with your phone, using Google Authenticator
-![QR Code for OTP](http://chart.apis.google.com/chart?cht=qr&chs=250x250&chl=otpauth%3A%2F%2Ftotp%2Falice%40google.com%3Fsecret%3DJBSWY3DPEHPK3PXP)
+![QR Code for OTP](https://cloud.githubusercontent.com/assets/2868/18771262/54f109dc-80f2-11e6-863f-d2be62ee587a.png)
Now run the following and compare the output
```ruby
require 'rubygems'
@@ -131,12 +143,11 @@
bundle exec rspec
```
## Executable Usage
-Once the rotp rubygem is installed on your system, you should be able to run the `rotp` executable
-(if not, you might find trouble-shooting help [at this stackoverflow question](http://stackoverflow.com/a/909980)).
+The rotp rubygem includes an executable for helping with testing and debugging
```bash
# Try this to get an overview of the commands
rotp --help
@@ -149,10 +160,10 @@
Have a look at the [contributors graph](https://github.com/mdp/rotp/graphs/contributors) on Github.
## License
-MIT Copyright (C) 2011 by Mark Percival, see [LICENSE](https://github.com/mdp/rotp/blob/master/LICENSE) for details.
+MIT Copyright (C) 2016 by Mark Percival, see [LICENSE](https://github.com/mdp/rotp/blob/master/LICENSE) for details.
## Other implementations
A list can be found at [Wikipedia](https://en.wikipedia.org/wiki/Google_Authenticator#Implementations).