-
Notifications
You must be signed in to change notification settings - Fork 0
/
oauth.go
139 lines (120 loc) · 3.85 KB
/
oauth.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
136
137
138
139
package xmcnbiclient
import (
"encoding/base64"
"encoding/json"
"strings"
"time"
)
// OAuthHeaderElements stores all fields contained in the decoded header part of the raw OAuth token.
type OAuthHeaderElements struct {
RawHeader string `json:"-"`
Algorithm string `json:"alg"`
}
// OAuthPayloadElements stores all fields contained in the decoded payload part of the raw OAuth token.
type OAuthPayloadElements struct {
RawPayload string `json:"-"`
Issuer string `json:"iss,omitempty"`
Subject string `json:"sub,omitempty"`
JWTID string `json:"jti,omitempty"`
Roles []string `json:"roles,omitempty"`
IsuedAtUnixfmt int64 `json:"iat,omitempty"`
NotBeforeUnixfmt int64 `json:"nbf,omitempty"`
ExpiresAtUnixfmt int64 `json:"exp,omitempty"`
IssuedAt time.Time `json:"-"`
NotBefore time.Time `json:"-"`
ExpiresAt time.Time `json:"-"`
LongLived bool `json:"longLived,omitempty"`
}
// OAuthToken stores the raw OAuth token returned by XMC as well as the decoded representation.
type OAuthToken struct {
TokenType string `json:"token_type"`
RawToken string `json:"access_token"`
Header OAuthHeaderElements
Payload OAuthPayloadElements
Signature []byte
}
// String returns the raw header part of the OAuth token.
func (he OAuthHeaderElements) String() string {
return he.RawHeader
}
// String returns the raw payload part of the OAuth token.
func (pe OAuthPayloadElements) String() string {
return pe.RawPayload
}
// String returns the raw OAuth token.
func (t OAuthToken) String() string {
return t.RawToken
}
// decodeHeader decodes the header part of the raw OAuth token.
func (t *OAuthToken) decodeHeader() error {
var headerElements OAuthHeaderElements
rawHeader := strings.Split(t.RawToken, ".")[0]
headerData, headerErr := base64.RawURLEncoding.DecodeString(rawHeader)
if headerErr != nil {
return headerErr
}
decodeErr := json.Unmarshal(headerData, &headerElements)
if decodeErr != nil {
return decodeErr
}
t.Header.RawHeader = rawHeader
t.Header = headerElements
return nil
}
// decodePayload decodes the payload part of the raw OAuth token.
func (t *OAuthToken) decodePayload() error {
var payloadElements OAuthPayloadElements
rawPayload := strings.Split(t.RawToken, ".")[1]
payloadData, payloadErr := base64.RawURLEncoding.DecodeString(rawPayload)
if payloadErr != nil {
return payloadErr
}
decodeErr := json.Unmarshal(payloadData, &payloadElements)
if decodeErr != nil {
return decodeErr
}
payloadElements.IssuedAt = time.Unix(payloadElements.IsuedAtUnixfmt, 0)
payloadElements.NotBefore = time.Unix(payloadElements.NotBeforeUnixfmt, 0)
payloadElements.ExpiresAt = time.Unix(payloadElements.ExpiresAtUnixfmt, 0)
t.Payload = payloadElements
return nil
}
// Decode decodes the raw OAuth token into human usable representations.
func (t *OAuthToken) Decode() error {
headerErr := t.decodeHeader()
if headerErr != nil {
return headerErr
}
payloadErr := t.decodePayload()
if payloadErr != nil {
return payloadErr
}
signature, signatureErr := base64.RawURLEncoding.DecodeString(strings.Split(t.RawToken, ".")[2])
if signatureErr != nil {
return signatureErr
}
t.Signature = signature
return nil
}
// IsValid returns a boolean representing if the token is still valid (true) or not (false).
func (t *OAuthToken) IsValid() bool {
if t.RawToken == "" {
return false
}
if t.Payload.ExpiresAt.Before(time.Now()) {
return false
}
return true
}
// ExpiresSoon returns a boolean representing whether the token will expire soon (true) or not (false).
// Soon is defined as time.Now() + graceSecs.
func (t *OAuthToken) ExpiresSoon(graceSecs uint) bool {
if t.RawToken == "" {
return false
}
timeSoon := time.Now().Add(time.Second * time.Duration(graceSecs))
if t.Payload.ExpiresAt.Before(timeSoon) {
return true
}
return false
}