-
Notifications
You must be signed in to change notification settings - Fork 4
/
token.go
93 lines (80 loc) · 2.12 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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright 2016 Lars Wiegman. All rights reserved. Use of this source code is
// governed by a BSD-style license that can be found in the LICENSE file.
package multipass
import (
"crypto/rsa"
"encoding/json"
"errors"
"net/http"
"strings"
"time"
jose "gopkg.in/square/go-jose.v1"
)
// Claims are part of the JSON web token
type Claims struct {
Handle string `json:"handle"`
Expires int64 `json:"exp"`
}
// accessToken return the serialized token given the signer and claims.
func accessToken(signer jose.Signer, claims *Claims) (token string, err error) {
payload, err := json.Marshal(claims)
if err != nil {
return "", err
}
jws, err := signer.Sign(payload)
if err != nil {
return "", err
}
return jws.CompactSerialize()
}
// GetTokenRequest returns the JWT token embedded in the given request.
// JWT tokens can be embedded in the header prefixed with "Bearer ", with a
// "token" key query parameter or a cookie named "jwt_token".
func GetTokenRequest(r *http.Request) string {
//from header
if h := r.Header.Get("Authorization"); strings.HasPrefix(h, "Bearer ") {
if len(h) > 7 {
return h[7:]
}
}
//from query parameter
if token := r.URL.Query().Get("token"); len(token) > 0 {
return token
}
//from cookie
if cookie, err := r.Cookie("jwt_token"); err == nil {
return cookie.Value
}
return ""
}
func validateToken(token string, key rsa.PublicKey) (*Claims, error) {
claims := &Claims{}
// Verify token signature
payload, err := verifyToken(token, key)
if err != nil {
return nil, err
}
// Unmarshal token claims
if err := json.Unmarshal(payload, claims); err != nil {
return nil, err
}
// Verify expire claim
if time.Unix(claims.Expires, 0).Before(time.Now()) {
return nil, errors.New("Token expired")
}
return claims, nil
}
// verifyToken returns the payload of the given token when the signature
// can be verified using the given public key.
func verifyToken(token string, key rsa.PublicKey) ([]byte, error) {
var data []byte
obj, err := jose.ParseSigned(token)
if err != nil {
return data, err
}
data, err = obj.Verify(&key)
if err != nil {
return data, err
}
return data, nil
}