3636import org .keycloak .representations .idm .ClientRepresentation ;
3737import org .keycloak .representations .idm .RealmRepresentation ;
3838import org .keycloak .testsuite .AbstractKeycloakTest ;
39- import org .keycloak .testsuite .Assert ;
4039import org .keycloak .testsuite .AssertEvents ;
4140import org .keycloak .testsuite .admin .ApiUtil ;
4241import org .keycloak .testsuite .arquillian .annotation .EnableFeature ;
4342import org .keycloak .testsuite .arquillian .annotation .UncaughtServerErrorExpected ;
4443import org .keycloak .testsuite .pages .ConsentPage ;
4544import org .keycloak .testsuite .updaters .ClientAttributeUpdater ;
4645import org .keycloak .testsuite .util .oauth .AccessTokenResponse ;
46+ import org .keycloak .testsuite .util .oauth .TokenExchangeRequest ;
4747import org .keycloak .util .TokenUtil ;
4848
4949import java .util .Collections ;
@@ -110,6 +110,83 @@ private AccessTokenResponse tokenExchange(String subjectToken, String clientId,
110110 return oauth .tokenExchangeRequest (subjectToken ).client (clientId , secret ).audience (audience ).additionalParams (additionalParams ).send ();
111111 }
112112
113+ @ Test
114+ @ UncaughtServerErrorExpected
115+ public void testSubjectTokenType () throws Exception {
116+ oauth .realm (TEST );
117+ String accessToken = resourceOwnerLogin ("john" , "password" , "subject-client" , "secret" );
118+
119+ TokenExchangeRequest request = oauth .tokenExchangeRequest (accessToken , OAuth2Constants .ACCESS_TOKEN_TYPE );
120+ AccessTokenResponse response = request .send ();
121+ assertEquals (Response .Status .OK .getStatusCode (), response .getStatusCode ());
122+
123+ request = oauth .tokenExchangeRequest (accessToken , OAuth2Constants .REFRESH_TOKEN_TYPE );
124+ response = request .send ();
125+ assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
126+ assertEquals (OAuthErrorException .INVALID_REQUEST , response .getError ());
127+
128+ request = oauth .tokenExchangeRequest (accessToken , OAuth2Constants .ID_TOKEN_TYPE );
129+ response = request .send ();
130+ assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
131+ assertEquals (OAuthErrorException .INVALID_REQUEST , response .getError ());
132+
133+ request = oauth .tokenExchangeRequest (accessToken , OAuth2Constants .SAML2_TOKEN_TYPE );
134+ response = request .send ();
135+ assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
136+ assertEquals (OAuthErrorException .INVALID_REQUEST , response .getError ());
137+
138+ request = oauth .tokenExchangeRequest (accessToken , OAuth2Constants .JWT_TOKEN_TYPE );
139+ response = request .send ();
140+ assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
141+ assertEquals (OAuthErrorException .INVALID_REQUEST , response .getError ());
142+
143+ request = oauth .tokenExchangeRequest (accessToken , "WRONG_TOKEN_TYPE" );
144+ response = request .send ();
145+ assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
146+ assertEquals (OAuthErrorException .INVALID_REQUEST , response .getError ());
147+ }
148+
149+ @ Test
150+ @ UncaughtServerErrorExpected
151+ public void testRequestedTokenType () throws Exception {
152+ oauth .realm (TEST );
153+ String accessToken = resourceOwnerLogin ("john" , "password" , "subject-client" , "secret" );
154+
155+ AccessTokenResponse response = tokenExchange (accessToken , "requester-client" , "secret" , null , Map .of (OAuth2Constants .REQUESTED_TOKEN_TYPE , OAuth2Constants .ACCESS_TOKEN_TYPE ));
156+ assertEquals (Response .Status .OK .getStatusCode (), response .getStatusCode ());
157+ assertNotNull (response .getAccessToken ());
158+ assertEquals (TokenUtil .TOKEN_TYPE_BEARER , response .getTokenType ());
159+ assertEquals (OAuth2Constants .ACCESS_TOKEN_TYPE , response .getIssuedTokenType ());
160+
161+ response = tokenExchange (accessToken , "requester-client" , "secret" , null , Map .of (OAuth2Constants .REQUESTED_TOKEN_TYPE , OAuth2Constants .REFRESH_TOKEN_TYPE ));
162+ assertEquals (Response .Status .OK .getStatusCode (), response .getStatusCode ());
163+ assertNotNull (response .getAccessToken ());
164+ assertEquals (TokenUtil .TOKEN_TYPE_BEARER , response .getTokenType ());
165+ assertEquals (OAuth2Constants .REFRESH_TOKEN_TYPE , response .getIssuedTokenType ());
166+
167+ response = tokenExchange (accessToken , "requester-client" , "secret" , null , Map .of (OAuth2Constants .REQUESTED_TOKEN_TYPE , OAuth2Constants .ID_TOKEN_TYPE ));
168+ assertEquals (Response .Status .OK .getStatusCode (), response .getStatusCode ());
169+ assertNotNull (response .getAccessToken ());
170+ assertEquals (TokenUtil .TOKEN_TYPE_NA , response .getTokenType ());
171+ assertEquals (OAuth2Constants .ID_TOKEN_TYPE , response .getIssuedTokenType ());
172+
173+ response = tokenExchange (accessToken , "requester-client" , "secret" , null , Map .of (OAuth2Constants .REQUESTED_TOKEN_TYPE , OAuth2Constants .JWT_TOKEN_TYPE ));
174+ assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
175+ assertEquals (OAuthErrorException .INVALID_REQUEST , response .getError ());
176+ assertEquals ("requested_token_type unsupported" , response .getErrorDescription ());
177+
178+ //TODO: saml token type should not be supported
179+ // response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE));
180+ // assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
181+ // assertEquals(OAuthErrorException.INVALID_REQUEST, response.getError());
182+ //assertEquals("requested_token_type unsupported", response.getErrorDescription());
183+
184+ response = tokenExchange (accessToken , "requester-client" , "secret" , null , Map .of (OAuth2Constants .REQUESTED_TOKEN_TYPE , "WRONG_TOKEN_TYPE" ));
185+ assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
186+ assertEquals (OAuthErrorException .INVALID_REQUEST , response .getError ());
187+ assertEquals ("requested_token_type unsupported" , response .getErrorDescription ());
188+ }
189+
113190 @ Test
114191 @ UncaughtServerErrorExpected
115192 public void testExchange () throws Exception {
@@ -158,7 +235,7 @@ public void testExchangeForIdToken() throws Exception {
158235 .parse ().getToken ();
159236 assertEquals (TokenUtil .TOKEN_TYPE_BEARER , exchangedToken .getType ());
160237
161- Assert . assertNotNull ("ID Token is null, but was expected to be present" , response .getIdToken ());
238+ assertNotNull ("ID Token is null, but was expected to be present" , response .getIdToken ());
162239 IDToken exchangedIdToken = TokenVerifier .create (response .getIdToken (), IDToken .class )
163240 .parse ().getToken ();
164241 assertEquals (TokenUtil .TOKEN_TYPE_ID , exchangedIdToken .getType ());
@@ -170,15 +247,15 @@ public void testExchangeForIdToken() throws Exception {
170247 oauth .scope (null );
171248 response = tokenExchange (accessToken , "requester-client" , "secret" , null , Map .of (OAuth2Constants .REQUESTED_TOKEN_TYPE , OAuth2Constants .ACCESS_TOKEN_TYPE ));
172249 assertEquals (OAuth2Constants .ACCESS_TOKEN_TYPE , response .getIssuedTokenType ());
173- Assert . assertNotNull (response .getAccessToken ());
174- Assert . assertNull ("ID Token was present, but should not be present" , response .getIdToken ());
250+ assertNotNull (response .getAccessToken ());
251+ assertNull ("ID Token was present, but should not be present" , response .getIdToken ());
175252
176253 // Exchange request requesting id-token. ID Token should be issued inside "access_token" parameter (as per token-exchange specification https://datatracker.ietf.org/doc/html/rfc8693#name-successful-response - parameter "access_token")
177254 response = tokenExchange (accessToken , "requester-client" , "secret" , null , Map .of (OAuth2Constants .REQUESTED_TOKEN_TYPE , OAuth2Constants .ID_TOKEN_TYPE ));
178255 assertEquals (OAuth2Constants .ID_TOKEN_TYPE , response .getIssuedTokenType ());
179256 assertEquals (TokenUtil .TOKEN_TYPE_NA , response .getTokenType ());
180- Assert . assertNotNull (response .getAccessToken ());
181- Assert . assertNull ("ID Token was present, but should not be present" , response .getIdToken ());
257+ assertNotNull (response .getAccessToken ());
258+ assertNull ("ID Token was present, but should not be present" , response .getIdToken ());
182259
183260 exchangedIdToken = TokenVerifier .create (response .getAccessToken (), IDToken .class )
184261 .parse ().getToken ();
@@ -196,13 +273,13 @@ public void testExchangeUsingServiceAccount() throws Exception {
196273 String accessToken = response .getAccessToken ();
197274 TokenVerifier <AccessToken > accessTokenVerifier = TokenVerifier .create (accessToken , AccessToken .class );
198275 AccessToken token = accessTokenVerifier .parse ().getToken ();
199- Assert . assertNull (token .getSessionId ());
276+ assertNull (token .getSessionId ());
200277 response = tokenExchange (accessToken , "requester-client" , "secret" , null , null );
201278 assertEquals (OAuth2Constants .ACCESS_TOKEN_TYPE , response .getIssuedTokenType ());
202279 String exchangedTokenString = response .getAccessToken ();
203280 TokenVerifier <AccessToken > verifier = TokenVerifier .create (exchangedTokenString , AccessToken .class );
204281 AccessToken exchangedToken = verifier .parse ().getToken ();
205- Assert . assertNull (exchangedToken .getSessionId ());
282+ assertNull (exchangedToken .getSessionId ());
206283 assertEquals ("requester-client" , exchangedToken .getIssuedFor ());
207284
208285 }
@@ -272,9 +349,9 @@ public void testClientExchangeToItselfWithConsents() throws Exception {
272349 public void testExchangeWithPublicClient () throws Exception {
273350 String accessToken = resourceOwnerLogin ("john" , "password" ,"subject-client" , "secret" );
274351 AccessTokenResponse response = tokenExchange (accessToken , "requester-client-public" , null , null , null );
275- org . junit . Assert . assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
276- org . junit . Assert . assertEquals (OAuthErrorException .INVALID_CLIENT , response .getError ());
277- org . junit . Assert . assertEquals ("Public client is not allowed to exchange token" , response .getErrorDescription ());
352+ assertEquals (Response .Status .BAD_REQUEST .getStatusCode (), response .getStatusCode ());
353+ assertEquals (OAuthErrorException .INVALID_CLIENT , response .getError ());
354+ assertEquals ("Public client is not allowed to exchange token" , response .getErrorDescription ());
278355 }
279356
280357 @ Test
0 commit comments