Skip to content

Commit

Permalink
feat: claims interface
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-elliott committed Oct 3, 2024
1 parent 1438817 commit 0c03ce9
Show file tree
Hide file tree
Showing 42 changed files with 721 additions and 397 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ following list of differences:
- [x] Minimum dependency is go version 1.21
- [x] Replace string values with constants where applicable
<sup>[commit](https://github.com/authelia/oauth2-provider/commit/de536dc0c9cd5f080c387621799e644319587bd0)</sup>
- [ ] Simplify the internal JWT logic to leverage `github.com/golang-jwt/jwt/v5`
- [x] Simplify the internal JWT logic to leverage `github.com/golang-jwt/jwt/v5`
or other such libraries
- [ ] Implement internal JWKS logic
- [x] Implement internal JWKS logic
- [x] Higher Debug error information visibility (Debug Field includes the
complete RFC6749 error with debug information if available)
- Fixes:
Expand Down Expand Up @@ -103,10 +103,10 @@ following list of differences:
- [x] General Refactor
- [x] Prevent Multiple Client Authentication Methods
- [x] Client Secret Validation Interface
- [ ] JWE support for Client Authentication and Issuance
- [x] JWE support for Client Authentication and Issuance
- [x] Testing Package (mocks, etc)
- [ ] Clock Drift Support
- [ ] Key Management
- [x] Key Management
- [ ] Injectable Clock Configurator
- [x] Support `s_hash`
<sup>[commit](https://github.com/authelia/oauth2-provider/commit/edbbbe9467c70a2578db4b9af4d6cd319f74886e)</sup>
Expand All @@ -125,6 +125,7 @@ following list of differences:
- [x] `github.com/gobuffalo/packr`
- [x] `github.com/form3tech-oss/jwt-go`
- [x] `github.com/dgrijalva/jwt-go`
- [x] `github.com/golang-jwt/jwt`
- Migration of the following dependencies:
- [x] `github.com/go-jose/go-jose/v3` => `github.com/go-jose/go-jose/v4`
- [x] `github.com/golang/mock` => `github.com/uber-go/mock`
Expand Down
5 changes: 3 additions & 2 deletions handler/oauth2/flow_authorize_code_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"authelia.com/provider/oauth2"
"authelia.com/provider/oauth2/internal/consts"
"authelia.com/provider/oauth2/storage"
"authelia.com/provider/oauth2/token/jwt"
"authelia.com/provider/oauth2/x/errorsx"
)

Expand Down Expand Up @@ -106,11 +107,11 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C
request.SetID(authorizeRequest.GetID())

atLifespan := oauth2.GetEffectiveLifespan(request.GetClient(), oauth2.GrantTypeAuthorizationCode, oauth2.AccessToken, c.Config.GetAccessTokenLifespan(ctx))
request.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Round(time.Second))
request.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Truncate(jwt.TimePrecision))

rtLifespan := oauth2.GetEffectiveLifespan(request.GetClient(), oauth2.GrantTypeAuthorizationCode, oauth2.RefreshToken, c.Config.GetRefreshTokenLifespan(ctx))
if rtLifespan > -1 {
request.GetSession().SetExpiresAt(oauth2.RefreshToken, time.Now().UTC().Add(rtLifespan).Round(time.Second))
request.GetSession().SetExpiresAt(oauth2.RefreshToken, time.Now().UTC().Add(rtLifespan).Truncate(jwt.TimePrecision))
}

return nil
Expand Down
5 changes: 3 additions & 2 deletions handler/oauth2/flow_authorize_code_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"authelia.com/provider/oauth2/internal/consts"
"authelia.com/provider/oauth2/storage"
"authelia.com/provider/oauth2/testing/mock"
"authelia.com/provider/oauth2/token/jwt"
)

func TestAuthorizeCode_PopulateTokenEndpointResponse(t *testing.T) {
Expand Down Expand Up @@ -462,8 +463,8 @@ func TestAuthorizeExplicitGrantHandler_HandleTokenEndpointRequest(t *testing.T)
require.NoError(t, s.InvalidateAuthorizeCodeSession(context.TODO(), sig))
},
func(t *testing.T, s CoreStorage, r *oauth2.AccessRequest, ar *oauth2.AuthorizeRequest) {
assert.Equal(t, time.Now().Add(time.Minute).UTC().Round(time.Second), r.GetSession().GetExpiresAt(oauth2.AccessToken))
assert.Equal(t, time.Now().Add(time.Minute).UTC().Round(time.Second), r.GetSession().GetExpiresAt(oauth2.RefreshToken))
assert.Equal(t, time.Now().Add(time.Minute).UTC().Truncate(jwt.TimePrecision), r.GetSession().GetExpiresAt(oauth2.AccessToken))
assert.Equal(t, time.Now().Add(time.Minute).UTC().Truncate(jwt.TimePrecision), r.GetSession().GetExpiresAt(oauth2.RefreshToken))
},
"The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. The authorization code has already been used.",
},
Expand Down
3 changes: 2 additions & 1 deletion handler/oauth2/flow_authorize_implicit.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"authelia.com/provider/oauth2"
"authelia.com/provider/oauth2/internal/consts"
"authelia.com/provider/oauth2/token/jwt"
"authelia.com/provider/oauth2/x/errorsx"
)

Expand Down Expand Up @@ -70,7 +71,7 @@ func (c *AuthorizeImplicitGrantTypeHandler) IssueImplicitAccessToken(ctx context
// Only override expiry if none is set.
atLifespan := oauth2.GetEffectiveLifespan(requester.GetClient(), oauth2.GrantTypeImplicit, oauth2.AccessToken, c.Config.GetAccessTokenLifespan(ctx))
if requester.GetSession().GetExpiresAt(oauth2.AccessToken).IsZero() {
requester.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Round(time.Second))
requester.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Truncate(jwt.TimePrecision))
}

// Generate the code
Expand Down
5 changes: 3 additions & 2 deletions handler/oauth2/flow_generic_code_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"authelia.com/provider/oauth2"
"authelia.com/provider/oauth2/storage"
"authelia.com/provider/oauth2/token/jwt"
"authelia.com/provider/oauth2/x/errorsx"
)

Expand Down Expand Up @@ -130,11 +131,11 @@ func (c *GenericCodeTokenEndpointHandler) HandleTokenEndpointRequest(ctx context
request.SetID(authorizeRequest.GetID())

atLifespan := oauth2.GetEffectiveLifespan(request.GetClient(), oauth2.GrantTypeAuthorizationCode, oauth2.AccessToken, c.Config.GetAccessTokenLifespan(ctx))
request.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Round(time.Second))
request.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Truncate(jwt.TimePrecision))

rtLifespan := oauth2.GetEffectiveLifespan(request.GetClient(), oauth2.GrantTypeAuthorizationCode, oauth2.RefreshToken, c.Config.GetRefreshTokenLifespan(ctx))
if rtLifespan > -1 {
request.GetSession().SetExpiresAt(oauth2.RefreshToken, time.Now().UTC().Add(rtLifespan).Round(time.Second))
request.GetSession().SetExpiresAt(oauth2.RefreshToken, time.Now().UTC().Add(rtLifespan).Truncate(jwt.TimePrecision))
}

return nil
Expand Down
5 changes: 3 additions & 2 deletions handler/oauth2/flow_refresh.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"authelia.com/provider/oauth2"
"authelia.com/provider/oauth2/internal/consts"
"authelia.com/provider/oauth2/storage"
"authelia.com/provider/oauth2/token/jwt"
"authelia.com/provider/oauth2/x/errorsx"
)

Expand Down Expand Up @@ -146,11 +147,11 @@ func (c *RefreshTokenGrantHandler) HandleTokenEndpointRequest(ctx context.Contex
}

atLifespan := oauth2.GetEffectiveLifespan(request.GetClient(), oauth2.GrantTypeRefreshToken, oauth2.AccessToken, c.Config.GetAccessTokenLifespan(ctx))
request.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Round(time.Second))
request.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Truncate(jwt.TimePrecision))

rtLifespan := oauth2.GetEffectiveLifespan(request.GetClient(), oauth2.GrantTypeRefreshToken, oauth2.RefreshToken, c.Config.GetRefreshTokenLifespan(ctx))
if rtLifespan > -1 {
request.GetSession().SetExpiresAt(oauth2.RefreshToken, time.Now().UTC().Add(rtLifespan).Round(time.Second))
request.GetSession().SetExpiresAt(oauth2.RefreshToken, time.Now().UTC().Add(rtLifespan).Truncate(jwt.TimePrecision))
}

return nil
Expand Down
35 changes: 18 additions & 17 deletions handler/oauth2/flow_refresh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"authelia.com/provider/oauth2/internal/consts"
"authelia.com/provider/oauth2/storage"
"authelia.com/provider/oauth2/testing/mock"
"authelia.com/provider/oauth2/token/jwt"
)

func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
Expand Down Expand Up @@ -114,7 +115,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "bar", consts.ScopeOffline},
Session: expiredSess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
Expand All @@ -139,7 +140,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", consts.ScopeOffline},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
Expand All @@ -165,18 +166,18 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "bar", consts.ScopeOffline},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
expect: func(t *testing.T) {
assert.NotEqual(t, sess, areq.Session)
assert.NotEqual(t, time.Now().UTC().Add(-time.Hour).Round(time.Hour), areq.RequestedAt)
assert.NotEqual(t, time.Now().UTC().Add(-time.Hour).Truncate(time.Hour), areq.RequestedAt)
assert.Equal(t, oauth2.Arguments{"foo", consts.ScopeOffline}, areq.GrantedScope)
assert.Equal(t, oauth2.Arguments{"foo", consts.ScopeOffline}, areq.RequestedScope)
assert.NotEqual(t, url.Values{"foo": []string{"bar"}}, areq.Form)
assert.Equal(t, time.Now().Add(time.Hour).UTC().Round(time.Second), areq.GetSession().GetExpiresAt(oauth2.AccessToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Round(time.Second), areq.GetSession().GetExpiresAt(oauth2.RefreshToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Truncate(jwt.TimePrecision), areq.GetSession().GetExpiresAt(oauth2.AccessToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Truncate(jwt.TimePrecision), areq.GetSession().GetExpiresAt(oauth2.RefreshToken))
},
},
{
Expand All @@ -200,7 +201,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "bar", "baz", consts.ScopeOffline},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
Expand Down Expand Up @@ -232,7 +233,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "bar", "baz", consts.ScopeOffline},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
Expand Down Expand Up @@ -264,7 +265,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "baz", consts.ScopeOffline},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
Expand Down Expand Up @@ -294,13 +295,13 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "bar", consts.ScopeOffline},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
expect: func(t *testing.T) {
assert.NotEqual(t, sess, areq.Session)
assert.NotEqual(t, time.Now().UTC().Add(-time.Hour).Round(time.Hour), areq.RequestedAt)
assert.NotEqual(t, time.Now().UTC().Add(-time.Hour).Truncate(time.Hour), areq.RequestedAt)
assert.Equal(t, oauth2.Arguments{"foo", consts.ScopeOffline}, areq.GrantedScope)
assert.Equal(t, oauth2.Arguments{"foo", consts.ScopeOffline}, areq.RequestedScope)
assert.NotEqual(t, url.Values{"foo": []string{"bar"}}, areq.Form)
Expand Down Expand Up @@ -328,7 +329,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "bar"},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
Expand All @@ -355,18 +356,18 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "bar"},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
})
require.NoError(t, err)
},
expect: func(t *testing.T) {
assert.NotEqual(t, sess, areq.Session)
assert.NotEqual(t, time.Now().UTC().Add(-time.Hour).Round(time.Hour), areq.RequestedAt)
assert.NotEqual(t, time.Now().UTC().Add(-time.Hour).Truncate(time.Hour), areq.RequestedAt)
assert.Equal(t, oauth2.Arguments{"foo"}, areq.GrantedScope)
assert.Equal(t, oauth2.Arguments{"foo"}, areq.RequestedScope)
assert.NotEqual(t, url.Values{"foo": []string{"bar"}}, areq.Form)
assert.Equal(t, time.Now().Add(time.Hour).UTC().Round(time.Second), areq.GetSession().GetExpiresAt(oauth2.AccessToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Round(time.Second), areq.GetSession().GetExpiresAt(oauth2.RefreshToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Truncate(jwt.TimePrecision), areq.GetSession().GetExpiresAt(oauth2.AccessToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Truncate(jwt.TimePrecision), areq.GetSession().GetExpiresAt(oauth2.RefreshToken))
},
},
{
Expand All @@ -389,7 +390,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
RequestedScope: oauth2.Arguments{"foo", "bar", consts.ScopeOffline},
Session: sess,
Form: url.Values{"foo": []string{"bar"}},
RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour),
RequestedAt: time.Now().UTC().Add(-time.Hour).Truncate(time.Hour),
}
err = store.CreateRefreshTokenSession(context.TODO(), sig, req)
require.NoError(t, err)
Expand Down
5 changes: 3 additions & 2 deletions handler/oauth2/flow_resource_owner.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"authelia.com/provider/oauth2"
"authelia.com/provider/oauth2/internal/consts"
"authelia.com/provider/oauth2/token/jwt"
"authelia.com/provider/oauth2/x/errorsx"
)

Expand Down Expand Up @@ -70,11 +71,11 @@ func (c *ResourceOwnerPasswordCredentialsGrantHandler) HandleTokenEndpointReques
delete(request.GetRequestForm(), consts.FormParameterPassword)

atLifespan := oauth2.GetEffectiveLifespan(request.GetClient(), oauth2.GrantTypePassword, oauth2.AccessToken, c.Config.GetAccessTokenLifespan(ctx))
request.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Round(time.Second))
request.GetSession().SetExpiresAt(oauth2.AccessToken, time.Now().UTC().Add(atLifespan).Truncate(jwt.TimePrecision))

rtLifespan := oauth2.GetEffectiveLifespan(request.GetClient(), oauth2.GrantTypePassword, oauth2.RefreshToken, c.Config.GetRefreshTokenLifespan(ctx))
if rtLifespan > -1 {
request.GetSession().SetExpiresAt(oauth2.RefreshToken, time.Now().UTC().Add(rtLifespan).Round(time.Second))
request.GetSession().SetExpiresAt(oauth2.RefreshToken, time.Now().UTC().Add(rtLifespan).Truncate(jwt.TimePrecision))
}

return nil
Expand Down
5 changes: 3 additions & 2 deletions handler/oauth2/flow_resource_owner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"authelia.com/provider/oauth2"
"authelia.com/provider/oauth2/internal/consts"
"authelia.com/provider/oauth2/testing/mock"
"authelia.com/provider/oauth2/token/jwt"
)

func TestResourceOwnerFlow_HandleTokenEndpointRequest(t *testing.T) {
Expand Down Expand Up @@ -89,8 +90,8 @@ func TestResourceOwnerFlow_HandleTokenEndpointRequest(t *testing.T) {
store.EXPECT().Authenticate(context.TODO(), "peter", "pan").Return(nil)
},
check: func(areq *oauth2.AccessRequest) {
assert.Equal(t, time.Now().Add(time.Hour).UTC().Round(time.Second), areq.GetSession().GetExpiresAt(oauth2.AccessToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Round(time.Second), areq.GetSession().GetExpiresAt(oauth2.RefreshToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Truncate(jwt.TimePrecision), areq.GetSession().GetExpiresAt(oauth2.AccessToken))
assert.Equal(t, time.Now().Add(time.Hour).UTC().Truncate(jwt.TimePrecision), areq.GetSession().GetExpiresAt(oauth2.RefreshToken))
},
},
} {
Expand Down
10 changes: 5 additions & 5 deletions handler/oauth2/strategy_jwt_profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import (

var rsaKey = gen.MustRSAKey()

// returns a valid JWT type. The JWTClaims.ExpiresAt time is intentionally
// left empty to ensure it is pulled from the session's ExpiresAt map for
// returns a valid JWT type. The JWTClaims.ExpirationTime time is intentionally
// left empty to ensure it is pulled from the session's ExpirationTime map for
// the given oauth2.TokenType.
var jwtValidCase = func(tokenType oauth2.TokenType) *oauth2.Request {
r := &oauth2.Request{
Expand Down Expand Up @@ -132,7 +132,7 @@ var jwtValidCaseWithRefreshExpiry = func(tokenType oauth2.TokenType) *oauth2.Req
},
ExpiresAt: map[oauth2.TokenType]time.Time{
tokenType: time.Now().UTC().Add(time.Hour),
oauth2.RefreshToken: time.Now().UTC().Add(time.Hour * 2).Round(time.Hour),
oauth2.RefreshToken: time.Now().UTC().Add(time.Hour * 2).Truncate(time.Hour),
},
},
}
Expand All @@ -144,8 +144,8 @@ var jwtValidCaseWithRefreshExpiry = func(tokenType oauth2.TokenType) *oauth2.Req
return r
}

// returns an expired JWT type. The JWTClaims.ExpiresAt time is intentionally
// left empty to ensure it is pulled from the session's ExpiresAt map for
// returns an expired JWT type. The JWTClaims.ExpirationTime time is intentionally
// left empty to ensure it is pulled from the session's ExpirationTime map for
// the given oauth2.TokenType.
var jwtExpiredCase = func(tokenType oauth2.TokenType, now time.Time) *oauth2.Request {
r := &oauth2.Request{
Expand Down
4 changes: 2 additions & 2 deletions handler/openid/flow_device_authorization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func TestOpenIDConnectDeviceAuthorizeHandler_PopulateTokenEndpointResponse(t *te
setup: func() {
sess := &DefaultSession{
Claims: &jwt.IDTokenClaims{
RequestedAt: time.Now().UTC(),
RequestedAt: jwt.Now(),
Subject: "foobar",
},
Headers: &jwt.Headers{},
Expand Down Expand Up @@ -297,7 +297,7 @@ func TestOpenIDConnectDeviceAuthorizeHandler_PopulateTokenEndpointResponse(t *te
setup: func() {
sess := &DefaultSession{
Claims: &jwt.IDTokenClaims{
RequestedAt: time.Now().UTC(),
RequestedAt: jwt.Now(),
Subject: "",
},
Headers: &jwt.Headers{},
Expand Down
Loading

0 comments on commit 0c03ce9

Please sign in to comment.