Skip to content

Commit 8c68053

Browse files
committed
Refactor token issuance process to include expiration time and update related tests
1 parent 34c36d2 commit 8c68053

File tree

9 files changed

+164
-401
lines changed

9 files changed

+164
-401
lines changed

.golangci.yml

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,65 @@
1-
linters-settings:
2-
errcheck:
3-
check-type-assertions: true
4-
goconst:
5-
min-len: 2
6-
min-occurrences: 3
7-
gocritic:
8-
enabled-tags:
9-
- diagnostic
10-
- experimental
11-
- opinionated
12-
- performance
13-
- style
14-
nolintlint:
15-
require-explanation: true
16-
require-specific: true
17-
1+
version: "2"
2+
run:
3+
issues-exit-code: 1
184
linters:
19-
disable-all: true
5+
default: none
206
enable:
217
- bodyclose
22-
#- depguard
8+
- copyloopvar
239
- dogsled
24-
#- dupl
2510
- errcheck
26-
- copyloopvar
2711
- exhaustive
28-
#- goconst TODO
29-
- gofmt
30-
- goimports
31-
#- gomnd
3212
- gocyclo
3313
- gosec
34-
- gosimple
3514
- govet
3615
- ineffassign
3716
- misspell
38-
#- nolintlint
3917
- nakedret
4018
- prealloc
4119
- predeclared
4220
- revive
4321
- staticcheck
44-
- stylecheck
4522
- thelper
4623
- tparallel
47-
- typecheck
4824
- unconvert
4925
- unparam
5026
- unused
5127
- whitespace
5228
- wsl
53-
54-
run:
55-
issues-exit-code: 1
29+
settings:
30+
errcheck:
31+
check-type-assertions: true
32+
goconst:
33+
min-len: 2
34+
min-occurrences: 3
35+
gocritic:
36+
enabled-tags:
37+
- diagnostic
38+
- experimental
39+
- opinionated
40+
- performance
41+
- style
42+
nolintlint:
43+
require-explanation: true
44+
require-specific: true
45+
exclusions:
46+
generated: lax
47+
presets:
48+
- comments
49+
- common-false-positives
50+
- legacy
51+
- std-error-handling
52+
paths:
53+
- third_party$
54+
- builtin$
55+
- examples$
56+
formatters:
57+
enable:
58+
- gofmt
59+
- goimports
60+
exclusions:
61+
generated: lax
62+
paths:
63+
- third_party$
64+
- builtin$
65+
- examples$

README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
- 🔑 **JWKS Generation**
2020
Serve JSON Web Key Sets to allow downstream systems to verify your tokens.
2121

22-
- 🌐 **Flexible Routing**
23-
Route token exchanges based on ID token claims using regex-based matching.
24-
2522
---
2623

2724
## 🧭 Architecture
@@ -44,8 +41,8 @@ Here's how TokenBridge works in a typical token exchange flow:
4441
| 3. Returns Access Token | |
4542
+<--------------------------+ |
4643
| | |
47-
4844
```
45+
4946
## 🧩 Components
5047

5148
### 👤 Client

_example/main.go

Lines changed: 0 additions & 149 deletions
This file was deleted.

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ require (
1919

2020
require (
2121
github.com/aws/aws-sdk-go-v2 v1.36.3
22-
github.com/aws/aws-sdk-go-v2/service/kms v1.38.2
22+
github.com/aws/aws-sdk-go-v2/service/kms v1.38.3
2323
github.com/coreos/go-oidc/v3 v3.14.1
24-
golang.org/x/crypto v0.37.0 // indirect
25-
golang.org/x/oauth2 v0.29.0
24+
golang.org/x/crypto v0.38.0 // indirect
25+
golang.org/x/oauth2 v0.30.0
2626
)

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+
44
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
55
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
66
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
7-
github.com/aws/aws-sdk-go-v2/service/kms v1.38.2 h1:945yEU8s1zYwy9s/2JzEJoHKvbAaZEkPqt8TOuO6r/g=
8-
github.com/aws/aws-sdk-go-v2/service/kms v1.38.2/go.mod h1:cQn6tAF77Di6m4huxovNM7NVAozWTZLsDRp9t8Z/WYk=
7+
github.com/aws/aws-sdk-go-v2/service/kms v1.38.3 h1:RivOtUH3eEu6SWnUMFHKAW4MqDOzWn1vGQ3S38Y5QMg=
8+
github.com/aws/aws-sdk-go-v2/service/kms v1.38.3/go.mod h1:cQn6tAF77Di6m4huxovNM7NVAozWTZLsDRp9t8Z/WYk=
99
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
1010
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
1111
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
@@ -22,10 +22,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
2222
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2323
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
2424
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
25-
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
26-
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
27-
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
28-
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
25+
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
26+
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
27+
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
28+
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
2929
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
3030
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3131
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

issuer.go

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package tokenbridge
33
import (
44
"context"
55
"fmt"
6-
"slices"
76
"time"
87

98
"github.com/coreos/go-oidc/v3/oidc"
@@ -101,29 +100,25 @@ func checkMandatoryClaims(claims jwt.MapClaims, mandatoryClaims []string) error
101100
// Returns:
102101
// - The signed JWT access token as a string if successful.
103102
// - An error if there is a problem generating or signing the token.
104-
func (ti *TokenIssuerWithJWKS) IssueAccessToken(ctx context.Context, idToken *oidc.IDToken) (string, error) {
103+
func (ti *TokenIssuerWithJWKS) IssueAccessToken(ctx context.Context, idToken *oidc.IDToken) (string, int64, error) {
105104
claims, err := ti.opts.OnTokenCreate(ctx, ti.iss, idToken)
106105
if err != nil {
107-
return "", fmt.Errorf("failed to create token claims: %w", err)
106+
return "", 0, fmt.Errorf("failed to create token claims: %w", err)
108107
}
109108

110109
// Ensure the "exp" claim is set to the token expiration time
111110
if _, exists := claims["exp"]; !exists {
112-
if slices.Contains(ti.opts.MandatoryClaims, "exp") {
113-
claims["exp"] = time.Now().Add(ti.opts.TokenExpiration).Unix()
114-
}
111+
claims["exp"] = time.Now().Add(ti.opts.TokenExpiration).Unix()
115112
}
116113

117114
// Ensure the "iat" claim is set to the current time
118115
if _, exists := claims["iat"]; !exists {
119-
if slices.Contains(ti.opts.MandatoryClaims, "iat") {
120-
claims["iat"] = time.Now().Unix()
121-
}
116+
claims["iat"] = time.Now().Unix()
122117
}
123118

124119
// Check for mandatory claims
125120
if err := checkMandatoryClaims(claims, ti.opts.MandatoryClaims); err != nil {
126-
return "", err
121+
return "", 0, err
127122
}
128123

129124
// Create a new JWT token with the required claims
@@ -135,10 +130,22 @@ func (ti *TokenIssuerWithJWKS) IssueAccessToken(ctx context.Context, idToken *oi
135130
// Sign the token using the provided signer
136131
tokenString, err := ti.signer.SignToken(ctx, token)
137132
if err != nil {
138-
return "", fmt.Errorf("failed to sign token: %w", err)
133+
return "", 0, fmt.Errorf("failed to sign token: %w", err)
134+
}
135+
136+
expiresVal, ok := claims["exp"]
137+
if !ok {
138+
return "", 0, fmt.Errorf("missing 'exp' claim after setting mandatory claims")
139139
}
140140

141-
return tokenString, nil
141+
expInt, ok := expiresVal.(int64)
142+
if !ok {
143+
return "", 0, fmt.Errorf("'exp' claim is not an int64 or float64")
144+
}
145+
146+
expiresIn := expInt - time.Now().Unix()
147+
148+
return tokenString, expiresIn, nil
142149
}
143150

144151
// GetJWKS retrieves the JSON Web Key Set (JWKS) containing the public keys used to verify the signed tokens.
@@ -177,12 +184,12 @@ func NewClientCredentialIssuer(config *clientcredentials.Config) *ClientCredenti
177184
// Returns:
178185
// - The access token as a string if successful.
179186
// - An error if there is a problem generating the access token.
180-
func (cci *ClientCredentialIssuer) IssueAccessToken(ctx context.Context, _ *oidc.IDToken) (string, error) {
187+
func (cci *ClientCredentialIssuer) IssueAccessToken(ctx context.Context, _ *oidc.IDToken) (string, int64, error) {
181188
// Use the client credentials config to retrieve a token
182189
token, err := cci.config.Token(ctx)
183190
if err != nil {
184-
return "", fmt.Errorf("failed to retrieve access token: %w", err)
191+
return "", 0, fmt.Errorf("failed to retrieve access token: %w", err)
185192
}
186193

187-
return token.AccessToken, nil
194+
return token.AccessToken, token.ExpiresIn, nil
188195
}

0 commit comments

Comments
 (0)