-
Notifications
You must be signed in to change notification settings - Fork 0
/
token.go
64 lines (55 loc) · 1.55 KB
/
token.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
package main
import (
"crypto/sha512"
"errors"
"fmt"
"net/http"
"strings"
"time"
)
// Token contains the Token itself in addition to related metadata. Use the
// function NewToken to construct a new Token.
type Token struct {
Timestamp string `json:"timestamp"`
Fingerprint string `json:"fingerprint"`
Secret string `json:"secret"`
}
// NewToken creates a token representation that includes metadata.
func NewToken(secret string) Token {
salt := "03c49494-c1f3-4b3c-a9e3-28b1c4e42177"
return Token{
Timestamp: time.Now().Format(time.RFC3339),
Fingerprint: fmt.Sprintf("%x", sha512.Sum512_256([]byte(salt+secret))),
Secret: secret,
}
}
// ExtractToken returns token value from a given map of headers based on a
// given list of possible token header names. First match is returned. Error
// is returned if no match occurs and fallbackToken is not set.
func ExtractToken(
headers http.Header,
tokenHeaderNames []string,
fallbackToken string,
) (Token, error) {
var secret string
var err error = nil
// Extract secret from header.
for _, tokenHeaderName := range tokenHeaderNames {
if tokenHeader, ok := headers[tokenHeaderName]; ok {
if len(tokenHeader) > 0 && len(tokenHeader[0]) > 0 {
secret = tokenHeader[0]
break
}
}
}
// Remove optional authorization type.
secret = strings.TrimPrefix(secret, "Bearer ")
// Use optional fallback token.
if len(secret) == 0 && len(fallbackToken) > 0 {
secret = fallbackToken
}
if len(secret) == 0 {
err = errors.New("failed to find token")
}
return NewToken(secret), err
}