99 "fmt"
1010 "testing"
1111
12+ "github.com/golang-jwt/jwt/v5"
1213 "github.com/stretchr/testify/assert"
1314 "github.com/stretchr/testify/require"
1415)
@@ -32,16 +33,28 @@ func TestNewKeycloakAuthorizer(t *testing.T) {
3233 }
3334 t .Run ("internal" , func (t * testing.T ) {
3435 for _ , test := range tests {
35- t .Run (test , func (t * testing.T ) {
36+ t .Run ("internal url " + test , func (t * testing.T ) {
3637 authorizer , err := NewKeycloakAuthorizer (KeycloakRealmInfo {
3738 AuthServerInternalUrl : test ,
3839 RealmId : validRealm ,
40+ AuthServerPublicUrl : validPublicUrl ,
3941 })
4042
4143 assert .ErrorContains (t , err , "invalid realm info" )
4244 assert .ErrorContains (t , err , "couldn't parse auth server internal url" )
4345 assert .Nil (t , authorizer )
4446 })
47+ t .Run ("public url " + test , func (t * testing.T ) {
48+ authorizer , err := NewKeycloakAuthorizer (KeycloakRealmInfo {
49+ AuthServerPublicUrl : test ,
50+ RealmId : validRealm ,
51+ AuthServerInternalUrl : validInternalUrl ,
52+ })
53+
54+ assert .ErrorContains (t , err , "invalid realm info" )
55+ assert .ErrorContains (t , err , "couldn't parse auth server public url" )
56+ assert .Nil (t , authorizer )
57+ })
4558 }
4659 })
4760 })
@@ -50,6 +63,7 @@ func TestNewKeycloakAuthorizer(t *testing.T) {
5063 authorizer , err := NewKeycloakAuthorizer (KeycloakRealmInfo {
5164 RealmId : validRealm ,
5265 AuthServerInternalUrl : validInternalUrl ,
66+ AuthServerPublicUrl : validPublicUrl ,
5367 })
5468
5569 assert .NoError (t , err )
@@ -58,49 +72,133 @@ func TestNewKeycloakAuthorizer(t *testing.T) {
5872}
5973
6074func TestParseJWT (t * testing.T ) {
75+ tokenIssuer , err := NewTokenIssuer (publicKeyALG , publicKeyID )
76+ require .NoError (t , err )
77+ authServer := FakeAuthServer (t , tokenIssuer )
78+
6179 authorizer , err := NewKeycloakAuthorizer (KeycloakRealmInfo {
6280 RealmId : validRealm ,
63- AuthServerInternalUrl : validInternalUrl ,
64- })
81+ AuthServerInternalUrl : authServer .URL ,
82+ AuthServerPublicUrl : validPublicUrl ,
83+ },
84+ WithValidMethods ("RS256" ),
85+ WithAudience (validAudience , "other valid audience" ),
86+ )
6587 require .NoError (t , err )
6688 require .NotNil (t , authorizer )
6789
68- FakeCertResponse (t , authorizer )
69-
7090 t .Run ("Wrong algorithm" , func (t * testing.T ) {
71- userContext , err := authorizer . ParseJWT ( context . Background (), invalidAlgorithmToken )
91+ token := tokenIssuer . GetTokenWithAlg ( t , jwt . SigningMethodHS256 . Alg (), validClaims () )
7292
73- assert .ErrorContains (t , err , "validation of token failed" )
74- assert .ErrorContains (t , err , "cannot find a key to decode the token" )
93+ userContext , err := authorizer .ParseJWT (context .Background (), token )
94+
95+ assert .ErrorContains (t , err , "invalid token signing method" )
7596 assert .Zero (t , userContext )
7697 })
7798
7899 t .Run ("Wrong signature" , func (t * testing.T ) {
79- userContext , err := authorizer .ParseJWT (context .Background (), invalidSignatureToken )
100+ token := tokenIssuer .GetToken (t , jwt.MapClaims {
101+ "iss" : validPublicUrl + "/realms/" + validRealm ,
102+ })
103+ token += "XX" // malformed signature
104+
105+ userContext , err := authorizer .ParseJWT (context .Background (), token )
80106
81107 assert .ErrorContains (t , err , "validation of token failed" )
82108 assert .ErrorContains (t , err , "crypto/rsa: verification error" )
83109 assert .Zero (t , userContext )
84110 })
85111
86112 t .Run ("Expired token" , func (t * testing.T ) {
87- userContext , err := authorizer .ParseJWT (context .Background (), expiredToken )
113+ claims := validClaims ()
114+ claims ["exp" ] = 1500000000
115+ token := tokenIssuer .GetToken (t , claims )
88116
89- assert .ErrorContains (t , err , "validation of token failed" )
117+ userContext , err := authorizer .ParseJWT (context .Background (), token )
118+
119+ assert .ErrorContains (t , err , "token has invalid claims" )
90120 assert .ErrorContains (t , err , "token is expired" )
91121 assert .Zero (t , userContext )
92122 })
93123
124+ t .Run ("missing expiration" , func (t * testing.T ) {
125+ claims := validClaims ()
126+ delete (claims , "exp" )
127+ token := tokenIssuer .GetToken (t , claims )
128+
129+ userContext , err := authorizer .ParseJWT (context .Background (), token )
130+
131+ assert .ErrorContains (t , err , "validation of token claims failed" )
132+ assert .ErrorContains (t , err , "exp claim is required" )
133+ assert .Zero (t , userContext )
134+ })
135+
136+ t .Run ("invalid issuedAt" , func (t * testing.T ) {
137+ claims := validClaims ()
138+ claims ["iat" ] = 9999999999
139+ token := tokenIssuer .GetToken (t , claims )
140+
141+ userContext , err := authorizer .ParseJWT (context .Background (), token )
142+
143+ assert .ErrorContains (t , err , "validation of token claims failed" )
144+ assert .ErrorContains (t , err , "token used before issued" )
145+ assert .Zero (t , userContext )
146+ })
147+
148+ t .Run ("Wrong issuer" , func (t * testing.T ) {
149+ claims := validClaims ()
150+ claims ["iss" ] = "invalid_issuer"
151+ token := tokenIssuer .GetToken (t , claims )
152+
153+ userContext , err := authorizer .ParseJWT (context .Background (), token )
154+
155+ assert .ErrorContains (t , err , "validation of token claims failed" )
156+ assert .ErrorContains (t , err , "token has invalid issuer" )
157+ assert .Zero (t , userContext )
158+ })
159+
160+ t .Run ("Missing subject" , func (t * testing.T ) {
161+ claims := validClaims ()
162+ delete (claims , "sub" )
163+ token := tokenIssuer .GetToken (t , claims )
164+
165+ userContext , err := authorizer .ParseJWT (context .Background (), token )
166+
167+ assert .ErrorContains (t , err , "validation of token claims failed" )
168+ assert .ErrorContains (t , err , "missing subject claim" )
169+ assert .Zero (t , userContext )
170+ })
171+
172+ t .Run ("Wrong audience" , func (t * testing.T ) {
173+ claims := validClaims ()
174+ claims ["aud" ] = "invalid_audience"
175+ token := tokenIssuer .GetToken (t , claims )
176+
177+ userContext , err := authorizer .ParseJWT (context .Background (), token )
178+
179+ assert .ErrorContains (t , err , "validation of token claims failed" )
180+ assert .ErrorContains (t , err , "token has invalid audience" )
181+ assert .Zero (t , userContext )
182+ })
183+
94184 t .Run ("Invalid claims" , func (t * testing.T ) {
95- userContext , err := authorizer .ParseJWT (context .Background (), invalidClaimsToken )
185+ claims := validClaims ()
186+ claims ["email" ] = 12345
187+ claims ["roles" ] = 1
188+ claims ["groups" ] = 2
189+ token := tokenIssuer .GetToken (t , claims )
190+
191+ userContext , err := authorizer .ParseJWT (context .Background (), token )
96192
97193 assert .ErrorContains (t , err , "parsing of token failed" )
98194 assert .ErrorContains (t , err , "cannot unmarshal number" )
99195 assert .Zero (t , userContext )
100196 })
101197
102198 t .Run ("OK" , func (t * testing.T ) {
103- userContext , err := authorizer .ParseJWT (context .Background (), validToken )
199+ token := tokenIssuer .GetToken (t , validClaims ())
200+
201+ userContext , err := authorizer .ParseJWT (context .Background (), token )
104202
105203 require .NoError (t , err )
106204 require .NotZero (t , userContext )
@@ -111,19 +209,24 @@ func TestParseJWT(t *testing.T) {
111209 assert .Equal (t , "initial" , userContext .UserName )
112210 assert .ElementsMatch (t , []string {"offline_access" , "uma_authorization" , "user" , "default-roles-user-management" }, userContext .Roles )
113211 assert .ElementsMatch (t , []string {"user-management-initial" }, userContext .Groups )
212+ assert .ElementsMatch (t , []string {validOrigin }, userContext .AllowedOrigins )
114213 })
115214}
116215
117216func TestParseAuthorizationHeader (t * testing.T ) {
217+ tokenIssuer , err := NewTokenIssuer (publicKeyALG , publicKeyID )
218+ require .NoError (t , err )
219+ authServer := FakeAuthServer (t , tokenIssuer )
220+ validToken := tokenIssuer .GetToken (t , validClaims ())
221+
118222 authorizer , err := NewKeycloakAuthorizer (KeycloakRealmInfo {
119223 RealmId : validRealm ,
120- AuthServerInternalUrl : validInternalUrl ,
224+ AuthServerInternalUrl : authServer .URL ,
225+ AuthServerPublicUrl : validPublicUrl ,
121226 })
122227 require .NoError (t , err )
123228 require .NotNil (t , authorizer )
124229
125- FakeCertResponse (t , authorizer )
126-
127230 t .Run ("Invalid fields" , func (t * testing.T ) {
128231 tests := []string {
129232 "" ,
@@ -148,6 +251,10 @@ func TestParseAuthorizationHeader(t *testing.T) {
148251 })
149252
150253 t .Run ("Invalid token" , func (t * testing.T ) {
254+ expiredClaims := validClaims ()
255+ expiredClaims ["exp" ] = 1500000000
256+ expiredToken := tokenIssuer .GetToken (t , expiredClaims )
257+
151258 userContext , err := authorizer .ParseAuthorizationHeader (context .Background (), "bearer " + expiredToken )
152259
153260 assert .ErrorContains (t , err , "validation of token failed" )
@@ -169,15 +276,19 @@ func TestParseAuthorizationHeader(t *testing.T) {
169276}
170277
171278func TestParseRequest (t * testing.T ) {
279+ tokenIssuer , err := NewTokenIssuer (publicKeyALG , publicKeyID )
280+ require .NoError (t , err )
281+ authServer := FakeAuthServer (t , tokenIssuer )
282+ validToken := tokenIssuer .GetToken (t , validClaims ())
283+
172284 authorizer , err := NewKeycloakAuthorizer (KeycloakRealmInfo {
173285 RealmId : validRealm ,
174- AuthServerInternalUrl : validInternalUrl ,
286+ AuthServerInternalUrl : authServer .URL ,
287+ AuthServerPublicUrl : validPublicUrl ,
175288 })
176289 require .NoError (t , err )
177290 require .NotNil (t , authorizer )
178291
179- FakeCertResponse (t , authorizer )
180-
181292 t .Run ("Invalid authorization header" , func (t * testing.T ) {
182293 userContext , err := authorizer .ParseRequest (context .Background (), "invalid" , validOrigin )
183294
0 commit comments