Repository: Nerzal/gocloak
Pull request #307 (2021-09-28 11:36:00)

WIP: switch jwt lib
This change introduces a breaking change. 
Instead of passing the expected audience into the DecodeToken functions, we can validate the expected audience with a call to VerifyAudience: https://pkg.go.dev/github.com/golang-jwt/jwt#MapClaims.VerifyAudience

Adresses issue #292 

When using custom claims, you'd have to implement the audience check for yourself for now. 
I'm open for better ideas regarding the audience validation.



Patch:
diff --git a/README.md b/README.md
index 81ed8b6..5a0d29f 100644
--- a/README.md
+++ b/README.md
@@ -99,13 +99,13 @@ There are a lot of backward incompatible changes:
 ### Installation
 
 ```shell
-go get github.com/Nerzal/gocloak/v9
+go get github.com/Nerzal/10
 ```
 
 ### Importing
 
 ```go
- import "github.com/Nerzal/gocloak/v9"
+ import "github.com/Nerzal/gocloak/v10"
 ```
 
 ### Create New User
diff --git a/client.go b/client.go
index 29caa77..4459728 100644
--- a/client.go
+++ b/client.go
@@ -11,13 +11,13 @@ import (
 	"sync"
 	"time"
 
-	"github.com/dgrijalva/jwt-go/v4"
 	"github.com/go-resty/resty/v2"
+	"github.com/golang-jwt/jwt/v4"
 	"github.com/opentracing/opentracing-go"
 	"github.com/pkg/errors"
 	"github.com/segmentio/ksuid"
 
-	"github.com/Nerzal/gocloak/v9/pkg/jwx"
+	"github.com/Nerzal/gocloak/v10/pkg/jwx"
 )
 
 type gocloak struct {
@@ -380,7 +380,7 @@ func (client *gocloak) RetrospectToken(ctx context.Context, accessToken, clientI
 }
 
 // DecodeAccessToken decodes the accessToken
-func (client *gocloak) DecodeAccessToken(ctx context.Context, accessToken, realm, expectedAudience string) (*jwt.Token, *jwt.MapClaims, error) {
+func (client *gocloak) DecodeAccessToken(ctx context.Context, accessToken, realm string) (*jwt.Token, *jwt.MapClaims, error) {
 	const errMessage = "could not decode access token"
 	accessToken = strings.Replace(accessToken, "Bearer ", "", 1)
 
@@ -401,11 +401,11 @@ func (client *gocloak) DecodeAccessToken(ctx context.Context, accessToken, realm
 		return nil, nil, errors.Wrap(errors.New("cannot find a key to decode the token"), errMessage)
 	}
 
-	return jwx.DecodeAccessToken(accessToken, usedKey.E, usedKey.N, expectedAudience)
+	return jwx.DecodeAccessToken(accessToken, usedKey.E, usedKey.N)
 }
 
 // DecodeAccessTokenCustomClaims decodes the accessToken and writes claims into the given claims
-func (client *gocloak) DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm, expectedAudience string, claims jwt.Claims) (*jwt.Token, error) {
+func (client *gocloak) DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) {
 	const errMessage = "could not decode access token with custom claims"
 	accessToken = strings.Replace(accessToken, "Bearer ", "", 1)
 
@@ -426,7 +426,7 @@ func (client *gocloak) DecodeAccessTokenCustomClaims(ctx context.Context, access
 		return nil, errors.Wrap(errors.New("cannot find a key to decode the token"), errMessage)
 	}
 
-	return jwx.DecodeAccessTokenCustomClaims(accessToken, usedKey.E, usedKey.N, claims, expectedAudience)
+	return jwx.DecodeAccessTokenCustomClaims(accessToken, usedKey.E, usedKey.N, claims)
 }
 
 func (client *gocloak) GetToken(ctx context.Context, realm string, options TokenOptions) (*JWT, error) {
@@ -552,9 +552,9 @@ func (client *gocloak) LoginClientSignedJWT(
 	realm string,
 	key interface{},
 	signedMethod jwt.SigningMethod,
-	expiresAt *jwt.Time,
+	expiresAt *jwt.NumericDate,
 ) (*JWT, error) {
-	claims := jwt.StandardClaims{
+	claims := jwt.RegisteredClaims{
 		ExpiresAt: expiresAt,
 		Issuer:    clientID,
 		Subject:   clientID,
diff --git a/go.mod b/go.mod
index b984b1c..02cbd14 100644
--- a/go.mod
+++ b/go.mod
@@ -1,15 +1,15 @@
-module github.com/Nerzal/gocloak/v9
+module github.com/Nerzal/gocloak/v10
 
 go 1.15
 
 require (
-	github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1
-	github.com/go-resty/resty/v2 v2.3.0
+	github.com/go-resty/resty/v2 v2.6.0
+	github.com/golang-jwt/jwt/v4 v4.1.0
 	github.com/opentracing/opentracing-go v1.2.0
 	github.com/pkg/errors v0.9.1
-	github.com/segmentio/ksuid v1.0.3
-	github.com/stretchr/testify v1.6.1
-	golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
-	golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
-	gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
+	github.com/segmentio/ksuid v1.0.4
+	github.com/stretchr/testify v1.7.0
+	golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
+	golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b // indirect
+	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
 )
diff --git a/go.sum b/go.sum
index 961d516..1a7b4fd 100644
--- a/go.sum
+++ b/go.sum
@@ -1,9 +1,11 @@
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
-github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
 github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So=
 github.com/go-resty/resty/v2 v2.3.0/go.mod h1:UpN9CgLZNsv4e9XG50UU8xdI0F43UQ4HmxLBDwaroHU=
+github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4=
+github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q=
+github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
+github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -12,26 +14,45 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/segmentio/ksuid v1.0.3 h1:FoResxvleQwYiPAVKe1tMUlEirodZqlqglIuFsdDntY=
 github.com/segmentio/ksuid v1.0.3/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
+github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
+github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
+github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
+golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/gocloak.go b/gocloak.go
index e01b83a..0c2abd8 100644
--- a/gocloak.go
+++ b/gocloak.go
@@ -4,8 +4,8 @@ import (
 	"context"
 	"io"
 
-	"github.com/dgrijalva/jwt-go/v4"
 	"github.com/go-resty/resty/v2"
+	"github.com/golang-jwt/jwt/v4"
 )
 
 // GoCloak holds all methods a client should fulfill
@@ -43,15 +43,15 @@ type GoCloak interface {
 	// LoginClientTokenExchange requests a login on a specified users behalf. Returning a user's tokens.
 	LoginClientTokenExchange(ctx context.Context, clientID, token, clientSecret, realm, targetClient, userID string) (*JWT, error)
 	// LoginClientSignedJWT performs a login with client credentials and signed jwt claims
-	LoginClientSignedJWT(ctx context.Context, idOfClient, realm string, key interface{}, signedMethod jwt.SigningMethod, expiresAt *jwt.Time) (*JWT, error)
+	LoginClientSignedJWT(ctx context.Context, idOfClient, realm string, key interface{}, signedMethod jwt.SigningMethod, expiresAt *jwt.NumericDate) (*JWT, error)
 	// LoginAdmin login as admin
 	LoginAdmin(ctx context.Context, username, password, realm string) (*JWT, error)
 	// RefreshToken used to refresh the token
 	RefreshToken(ctx context.Context, refreshToken, clientID, clientSecret, realm string) (*JWT, error)
 	// DecodeAccessToken decodes the accessToken
-	DecodeAccessToken(ctx context.Context, accessToken, realm, expectedAudience string) (*jwt.Token, *jwt.MapClaims, error)
+	DecodeAccessToken(ctx context.Context, accessToken, realm string) (*jwt.Token, *jwt.MapClaims, error)
 	// DecodeAccessTokenCustomClaims decodes the accessToken and fills the given claims
-	DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm, expectedAudience string, claims jwt.Claims) (*jwt.Token, error)
+	DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error)
 	// RetrospectToken calls the openid-connect introspect endpoint
 	RetrospectToken(ctx context.Context, accessToken, clientID, clientSecret, realm string) (*RetrospecTokenResult, error)
 	// GetIssuer calls the issuer endpoint for the given realm
diff --git a/models.go b/models.go
index 026ecb0..87c7250 100644
--- a/models.go
+++ b/models.go
@@ -4,7 +4,7 @@ import (
 	"encoding/json"
 	"strings"
 
-	"github.com/dgrijalva/jwt-go/v4"
+	"github.com/golang-jwt/jwt/v4"
 )
 
 // GetQueryParams converts the struct to map[string]string
diff --git a/pkg/jwx/jwx.go b/pkg/jwx/jwx.go
index 64824fc..23b8d5f 100644
--- a/pkg/jwx/jwx.go
+++ b/pkg/jwx/jwx.go
@@ -10,7 +10,7 @@ import (
 	"math/big"
 	"strings"
 
-	jwt "github.com/dgrijalva/jwt-go/v4"
+	"github.com/golang-jwt/jwt/v4"
 	"github.com/pkg/errors"
 )
 
@@ -75,7 +75,7 @@ func decodePublicKey(e, n *string) (*rsa.PublicKey, error) {
 }
 
 // DecodeAccessToken currently only supports RSA - sorry for that
-func DecodeAccessToken(accessToken string, e, n *string, expectedAudience string) (*jwt.Token, *jwt.MapClaims, error) {
+func DecodeAccessToken(accessToken string, e, n *string) (*jwt.Token, *jwt.MapClaims, error) {
 	const errMessage = "could not decode accessToken"
 	accessToken = strings.Replace(accessToken, "Bearer ", "", 1)
 
@@ -86,18 +86,13 @@ func DecodeAccessToken(accessToken string, e, n *string, expectedAudience string
 
 	claims := &jwt.MapClaims{}
 
-	audValidation := jwt.WithoutAudienceValidation()
-	if expectedAudience != "" {
-		audValidation = jwt.WithAudience(expectedAudience)
-	}
-
 	token2, err := jwt.ParseWithClaims(accessToken, claims, func(token *jwt.Token) (interface{}, error) {
 		// Don't forget to validate the alg is what you expect:
 		if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
 			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
 		}
 		return rsaPublicKey, nil
-	}, audValidation)
+	})
 
 	if err != nil {
 		return nil, nil, errors.Wrap(err, errMessage)
@@ -107,7 +102,7 @@ func DecodeAccessToken(accessToken string, e, n *string, expectedAudience string
 }
 
 // DecodeAccessTokenCustomClaims currently only supports RSA - sorry for that
-func DecodeAccessTokenCustomClaims(accessToken string, e, n *string, customClaims jwt.Claims, expectedAudience string) (*jwt.Token, error) {
+func DecodeAccessTokenCustomClaims(accessToken string, e, n *string, customClaims jwt.Claims) (*jwt.Token, error) {
 	const errMessage = "could not decode accessToken with custom claims"
 	accessToken = strings.Replace(accessToken, "Bearer ", "", 1)
 
@@ -116,18 +111,13 @@ func DecodeAccessTokenCustomClaims(accessToken string, e, n *string, customClaim
 		return nil, errors.Wrap(err, errMessage)
 	}
 
-	audValidation := jwt.WithoutAudienceValidation()
-	if expectedAudience != "" {
-		audValidation = jwt.WithAudience(expectedAudience)
-	}
-
 	token2, err := jwt.ParseWithClaims(accessToken, customClaims, func(token *jwt.Token) (interface{}, error) {
 		// Don't forget to validate the alg is what you expect:
 		if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
 			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
 		}
 		return rsaPublicKey, nil
-	}, audValidation)
+	})
 
 	if err != nil {
 		return nil, errors.Wrap(err, errMessage)
diff --git a/pkg/jwx/models.go b/pkg/jwx/models.go
index 57d5105..48b7449 100644
--- a/pkg/jwx/models.go
+++ b/pkg/jwx/models.go
@@ -1,6 +1,6 @@
 package jwx
 
-import jwt "github.com/dgrijalva/jwt-go/v4"
+import jwt "github.com/golang-jwt/jwt/v4"
 
 // DecodedAccessTokenHeader is the decoded header from the access token
 type DecodedAccessTokenHeader struct {


Test patch:
diff --git a/client_benchmark_test.go b/client_benchmark_test.go
index 0a5711d..c526509 100644
--- a/client_benchmark_test.go
+++ b/client_benchmark_test.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"testing"
 
-	"github.com/Nerzal/gocloak/v9"
+	"github.com/Nerzal/gocloak/v10"
 
 	"github.com/stretchr/testify/assert"
 )
diff --git a/client_test.go b/client_test.go
index 93cc560..7b4a331 100644
--- a/client_test.go
+++ b/client_test.go
@@ -21,12 +21,12 @@ import (
 	"testing"
 	"time"
 
-	"github.com/dgrijalva/jwt-go/v4"
 	"github.com/go-resty/resty/v2"
+	"github.com/golang-jwt/jwt/v4"
 	"github.com/stretchr/testify/require"
 	"golang.org/x/crypto/pkcs12"
 
-	"github.com/Nerzal/gocloak/v9"
+	"github.com/Nerzal/gocloak/v10"
 )
 
 type configAdmin struct {
@@ -872,7 +872,6 @@ func Test_DecodeAccessToken(t *testing.T) {
 		context.Background(),
 		token.AccessToken,
 		cfg.GoCloak.Realm,
-		"",
 	)
 	require.NoError(t, err)
 	t.Log(resultToken)
@@ -889,7 +888,6 @@ func Test_DecodeAccessTokenCustomClaims(t *testing.T) {
 		context.Background(),
 		token.AccessToken,
 		cfg.GoCloak.Realm,
-		"",
 		claims,
 	)
 	require.NoError(t, err)
@@ -994,9 +992,7 @@ func Test_LoginSignedJWT(t *testing.T) {
 		cfg.GoCloak.Realm,
 		rsaKey,
 		jwt.SigningMethodRS256,
-		&jwt.Time{
-			Time: time.Now().Add(time.Hour),
-		},
+		&jwt.NumericDate{},
 	)
 	require.NoError(t, err, "Login failed")
 }
diff --git a/model_test.go b/model_test.go
index 59300ab..88458df 100644
--- a/model_test.go
+++ b/model_test.go
@@ -5,7 +5,7 @@ import (
 	"errors"
 	"testing"
 
-	"github.com/Nerzal/gocloak/v9"
+	"github.com/Nerzal/gocloak/v10"
 
 	"github.com/stretchr/testify/assert"
 )
diff --git a/utils_test.go b/utils_test.go
index 8a80f07..30c8afb 100644
--- a/utils_test.go
+++ b/utils_test.go
@@ -5,7 +5,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 
-	"github.com/Nerzal/gocloak/v9"
+	"github.com/Nerzal/gocloak/v10"
 )
 
 func TestStringP(t *testing.T) {