Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (ql:quickload :cl-base32)
- (ql:quickload :hunchentoot)
- (ql:quickload :cl-one-time-passwords)
- (ql:quickload :cl-qrencode)
- (ql:quickload :cl-pass)
- (ql:quickload :babel)
- (ql:quickload :flexi-streams)
- (ql:quickload :cl-who)
- (ql:quickload :ironclad)
- (defpackage otp-test
- (:use :cl))
- (in-package :otp-test)
- (setf *random-state* (make-random-state t))
- (setf crypto:*prng* (crypto:make-prng :fortuna))
- (setf totp:*time-step-in-seconds* 30)
- (defun make-otp-secret ()
- (ironclad:byte-array-to-hex-string (crypto:random-data 20)))
- (defclass user ()
- ((username :initarg :username
- :accessor username
- :initform nil)
- (password :initarg :password
- :accessor password
- :initform nil)
- (otp-secret :initarg :otp-secret
- :accessor otp-secret
- :initform nil)))
- (defmethod totp-uri ((user user))
- (format nil "otpauth://totp/2FATest:~A?secret=~A&issuer=2FATest"
- (username user)
- (cl-base32:bytes-to-base32
- (ironclad:hex-string-to-byte-array
- (otp-secret user)))))
- (defparameter *user* (make-instance 'user
- :username "testuser"
- :password (cl-pass:hash "testuser")
- :otp-secret (make-otp-secret)))
- (hunchentoot:define-easy-handler (qrcode :uri "/qrcode") ()
- (setf (hunchentoot:content-type*) "image/png")
- (flex:with-output-to-sequence (stream)
- (cl-qrencode:encode-png-stream (totp-uri *user*) stream
- :level :level-m
- :mode :byte)))
- (defun call-with-test-page (function)
- (who:with-html-output-to-string (html)
- (:html
- (:header
- (:title "2FA FreeOTP test"))
- (:body
- (:h1 (who:str "2FA FreeOTP test"))
- (:p (who:str "This is a FreeOTP test for Two Factor Authentication"))
- (:h3 (who:str "Instructions"))
- (:ol
- (:li (who:str "Install FreeOTP"))
- (:li (who:str "Scan the QR code"))
- (:li (who:str "Generate tokens in your phone and input here"))
- (:li (who:str "Click on \"Test\" button and verify it succeeds")))
- (:p (:b (who:str "IMPORTANT NOTE:")) "FreeOTP is very sensible regarding clock times, and tokens are valid for only 30 seconds, so it is very easy to get out of sync with the server. So you should make sure your phone's clock is uptodate")
- (:img :src "/qrcode" :width 200 :height 200)
- (:form :action "/login" :method :post
- (:input :type "text" :name "token")
- (:input :type "submit" :value "Test"))
- (funcall function html)))))
- (hunchentoot:define-easy-handler (test :uri "/") ()
- (call-with-test-page (lambda (html))))
- (hunchentoot:define-easy-handler (login :uri "/login") ()
- (call-with-test-page (lambda (html)
- (who:with-html-output (html html)
- (if (= (totp:totp (otp-secret *user*))
- (parse-integer (hunchentoot:parameter "token")))
- (who:htm (:h1 :style "color:green;"
- "Success!!"))
- (who:htm (:h1 :style "color:red;"
- "Failed")))))))
- (hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port 9095))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement