forked from dschenkelman/auth0
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauth0.go
135 lines (114 loc) · 3.83 KB
/
auth0.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package auth0
import (
"errors"
"net/http"
"time"
"gopkg.in/square/go-jose.v2"
"gopkg.in/square/go-jose.v2/jwt"
)
// SecretProvider will provide everything
// needed retrieve the secret.
type SecretProvider interface {
GetSecret(r *http.Request) (interface{}, error)
}
// SecretProviderFunc simple wrappers to provide
// secret with functions.
type SecretProviderFunc func(*http.Request) (interface{}, error)
// GetSecret implements the SecretProvider interface.
func (f SecretProviderFunc) GetSecret(r *http.Request) (interface{}, error) {
return f(r)
}
// NewKeyProvider provide a simple passphrase key provider.
func NewKeyProvider(key interface{}) SecretProvider {
return SecretProviderFunc(func(_ *http.Request) (interface{}, error) {
return key, nil
})
}
var (
// ErrNoJWTHeaders is returned when there are no headers in the JWT.
ErrNoJWTHeaders = errors.New("No headers in the token")
)
// Configuration contains
// all the information about the
// Auth0 service.
type Configuration struct {
secretProvider SecretProvider
expectedClaims jwt.Expected
signIn jose.SignatureAlgorithm
}
// NewConfiguration creates a configuration for server
func NewConfiguration(provider SecretProvider, audience []string, issuer string, method jose.SignatureAlgorithm) Configuration {
return Configuration{
secretProvider: provider,
expectedClaims: jwt.Expected{Issuer: issuer, Audience: audience},
signIn: method,
}
}
// NewConfigurationTrustProvider creates a configuration for server with no enforcement for token sig alg type, instead trust provider
func NewConfigurationTrustProvider(provider SecretProvider, audience []string, issuer string) Configuration {
return Configuration{
secretProvider: provider,
expectedClaims: jwt.Expected{Issuer: issuer, Audience: audience},
}
}
// JWTValidator helps middleware
// to validate token
type JWTValidator struct {
config Configuration
extractor RequestTokenExtractor
}
// NewValidator creates a new
// validator with the provided configuration.
func NewValidator(config Configuration, extractor RequestTokenExtractor) *JWTValidator {
if extractor == nil {
extractor = RequestTokenExtractorFunc(FromHeader)
}
return &JWTValidator{config, extractor}
}
// ValidateRequest validates the token within
// the http request.
// A default leeway value of one minute is used to compare time values.
func (v *JWTValidator) ValidateRequest(r *http.Request) (*jwt.JSONWebToken, error) {
return v.validateRequestWithLeeway(r, jwt.DefaultLeeway)
}
// ValidateRequestWithLeeway validates the token within
// the http request.
// The provided leeway value is used to compare time values.
func (v *JWTValidator) ValidateRequestWithLeeway(r *http.Request, leeway time.Duration) (*jwt.JSONWebToken, error) {
return v.validateRequestWithLeeway(r, leeway)
}
func (v *JWTValidator) validateRequestWithLeeway(r *http.Request, leeway time.Duration) (*jwt.JSONWebToken, error) {
token, err := v.extractor.Extract(r)
if err != nil {
return nil, err
}
if len(token.Headers) < 1 {
return nil, ErrNoJWTHeaders
}
// trust secret provider when sig alg not configured and skip check
if v.config.signIn != "" {
header := token.Headers[0]
if header.Algorithm != string(v.config.signIn) {
return nil, ErrInvalidAlgorithm
}
}
claims := jwt.Claims{}
key, err := v.config.secretProvider.GetSecret(r)
if err != nil {
return nil, err
}
if err = token.Claims(key, &claims); err != nil {
return nil, err
}
expected := v.config.expectedClaims.WithTime(time.Now())
err = claims.ValidateWithLeeway(expected, leeway)
return token, err
}
// Claims unmarshall the claims of the provided token
func (v *JWTValidator) Claims(r *http.Request, token *jwt.JSONWebToken, values ...interface{}) error {
key, err := v.config.secretProvider.GetSecret(r)
if err != nil {
return err
}
return token.Claims(key, values...)
}