/
authenticator.go
67 lines (55 loc) · 1.76 KB
/
authenticator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package authenticator
import (
"encoding/base64"
"fmt"
"net/url"
"github.com/skip2/go-qrcode"
)
const (
QRSize = 256
)
// The KeyUri type holds all the config necessary to generate a valid
// registration URI for any authenticator app, e.g.: Google Authenticator, Authy,
// etc.
type KeyUri struct {
Type string // hotp | totp
Label Label
Parameters paramsFormatter
}
// String encodes all the KeyUri info as a valid URI.
func (ku *KeyUri) String() string {
format := "otpauth://%s/%s?%s"
raw := fmt.Sprintf(format, ku.Type, ku.Label.String(), ku.Parameters.AsUrlValues(ku.Label.Issuer).Encode())
uri, _ := url.Parse(raw)
return uri.String()
}
// QRCode will encode the value returned by KeyUri.String into a base64
// encoded image containing a QR code that can be displayed and then scanned by
// the user. The return value is the base64 encoded image data.
func (ku *KeyUri) QRCode() (string, error) {
uri := ku.String()
qr, err := qrcode.New(uri, qrcode.Medium)
if err != nil {
return "", err
}
bytes, err := qr.PNG(QRSize)
if err != nil {
return "", err
}
return "data:image/png;base64," + base64.StdEncoding.EncodeToString(bytes), nil
}
// The Label is used to identify which account a key is associated with.
type Label struct {
AccountName string // Should be a username, email, etc.
Issuer string // Should be the domain, company, org that is issuing the auth
}
// The String method will encode the Label in a valid format to be included in
// the key URI.
func (l *Label) String() string {
return fmt.Sprintf("%s:%s", l.Issuer, l.AccountName)
}
// The paramsFormatter type has the ability to encode the OTP params into
// expected formats to be used for exporting.
type paramsFormatter interface {
AsUrlValues(issuer string) url.Values
}