gosora/common/gauth/authenticator.go

66 lines
1.9 KiB
Go
Raw Normal View History

Added the Page Manager for faster and easier custom page creation. Added the PageStore. Renamed account_own_edit.html to account_own_edit_password.html Renamed custom-page.html to custom_page.html Renamed the pre_render_custom_page hook to pre_render_tmpl_page. Added a new pre_render_custom_page hook, not to be confused with the previous one. Renamed the pre_render_account_own_edit_critical hook to pre_render_account_own_edit_password. Moved the report forum ID into a constant. Renamed todaysReportCount to topicsTopicCountByForum and made it more generic. Renamed panel-menu.html to panel_menu.html Renamed panel-inner-menu.html to panel_inner_menu.html Removed an irrelevant editable_parent in a no results row. Fixed the profile page loading the wrong profile.css Fixed a bug where the last poster avatar would break on the forum page. Added the AddNotice method to *Header. Greatly simplified many of the page struct definitions. Added the ErrorPage page struct and refactored the error pages to use it. Added the BasePanelPage page struct and refactored the panel page structs to use it. Tweaked the DefaultHeader function to set the user on the spot rather than after the fact. Simplified AccountEditAvatarSubmit into a redirect. Add the addElement closure in the control panel dashboard to reduce the amount of complexity. Tweaked LogWarning to better handle nils. Added the account_username phrase. Added the account_avatar phrase. Added the account_email phrase. Added the panel_pages phrase. Added the panel_pages_edit phrase. Added the panel_page_created phrase. Added the panel_page_updated phrase. Added the panel_page_deleted phrase. Added the account_menu_security phrase. Added the panel_menu_pages phrase. Added the panel_pages_head phrase. Added the panel_pages_edit_button_aria phrase. Added the panel_pages_delete_button_aria phrase. Added the panel_pages_no_pages phrase. Added the panel_pages_create_head phrase. Added the panel_pages_create_name phrase. Added the panel_pages_create_name_placeholder phrase. Added the panel_pages_create_title phrase. Added the panel_pages_create_title_placeholder phrase. Added the panel_pages_create_body_placeholder phrase. Added the panel_pages_create_submit_button phrase. Added the panel_pages_edit_head phrase. Added the panel_pages_name phrase. Added the panel_pages_title phrase. Added the panel_pages_edit_update_button phrase. Began work on two-factor authentication. Made more progress with the Nox Theme.
2018-06-06 00:21:22 +00:00
// Google Authenticator 2FA
// Borrowed from https://github.com/tilaklodha/google-authenticator, as we can't import it as a library as it's in package main
package gauth
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/base32"
"encoding/binary"
"strconv"
"strings"
"time"
)
// Append extra 0s if the length of otp is less than 6
// If otp is "1234", it will return it as "001234"
func prefix0(otp string) string {
if len(otp) == 6 {
return otp
}
for i := (6 - len(otp)); i > 0; i-- {
otp = "0" + otp
}
return otp
}
func GetHOTPToken(secret string, interval int64) (string, error) {
// Converts secret to base32 Encoding. Base32 encoding desires a 32-character subset of the twenty-six letters AZ and ten digits 09
key, err := base32.StdEncoding.DecodeString(strings.ToUpper(secret))
if err != nil {
return "", err
}
bs := make([]byte, 8)
binary.BigEndian.PutUint64(bs, uint64(interval))
// Signing the value using HMAC-SHA1 Algorithm
hash := hmac.New(sha1.New, key)
hash.Write(bs)
h := hash.Sum(nil)
// We're going to use a subset of the generated hash.
// Using the last nibble (half-byte) to choose the index to start from.
// This number is always appropriate as it's maximum decimal 15, the hash will have the maximum index 19 (20 bytes of SHA1) and we need 4 bytes.
o := (h[19] & 15)
var header uint32
// Get 32 bit chunk from hash starting at the o
r := bytes.NewReader(h[o : o+4])
err = binary.Read(r, binary.BigEndian, &header)
if err != nil {
return "", err
}
// Ignore most significant bits as per RFC 4226.
// Takes division from one million to generate a remainder less than < 7 digits
h12 := (int(header) & 0x7fffffff) % 1000000
return prefix0(strconv.Itoa(int(h12))), nil
}
func GetTOTPToken(secret string) (string, error) {
// The TOTP token is just a HOTP token seeded with every 30 seconds.
interval := time.Now().Unix() / 30
return GetHOTPToken(secret, interval)
}