diff --git a/jans-auth-server/model/src/main/java/io/jans/as/model/common/GrantType.java b/jans-auth-server/model/src/main/java/io/jans/as/model/common/GrantType.java index b10e3836902..79bfb0ee8ce 100644 --- a/jans-auth-server/model/src/main/java/io/jans/as/model/common/GrantType.java +++ b/jans-auth-server/model/src/main/java/io/jans/as/model/common/GrantType.java @@ -78,6 +78,11 @@ public enum GrantType implements HasParamName, AttributeEnum { */ OXAUTH_UMA_TICKET("urn:ietf:params:oauth:grant-type:uma-ticket"), + /** + * Token exchange grant type for OAuth 2.0 + */ + TOKEN_EXCHANGE("urn:ietf:params:oauth:grant-type:token-exchange"), + /** * CIBA (Client Initiated Backchannel Authentication) Grant Type. */ diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthzRequestService.java b/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthzRequestService.java index 4bb8ed1fc53..aba3603ac29 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthzRequestService.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/authorize/ws/rs/AuthzRequestService.java @@ -9,6 +9,7 @@ import io.jans.as.common.util.RedirectUri; import io.jans.as.model.authorize.AuthorizeErrorResponseType; import io.jans.as.model.authorize.AuthorizeResponseParam; +import io.jans.as.model.common.GrantType; import io.jans.as.model.common.Prompt; import io.jans.as.model.common.ResponseMode; import io.jans.as.model.common.ScopeConstants; @@ -110,6 +111,10 @@ public void addDeviceSecretToSession(AuthzRequest authzRequest, SessionId sessio if (!Arrays.asList(authzRequest.getScope().split(" ")).contains(ScopeConstants.DEVICE_SSO)) { return; } + if (!ArrayUtils.contains(authzRequest.getClient().getGrantTypes(), GrantType.TOKEN_EXCHANGE)) { + log.debug("Skip device secret. Scope has {} value but client does not have Token Exchange Grant Type enabled ('urn:ietf:params:oauth:grant-type:token-exchange')", ScopeConstants.DEVICE_SSO); + return; + } final String newDeviceSecret = HandleTokenFactory.generateHandleToken(); diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceImpl.java b/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceImpl.java index 80b454130d4..45ea6c80501 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceImpl.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceImpl.java @@ -200,6 +200,8 @@ public Response requestAccessToken(String grantType, String code, return processCIBA(scope, authReqId, idTokenPreProcessing, executionContext); } else if (gt == GrantType.DEVICE_CODE) { return processDeviceCodeGrantType(executionContext, deviceCode, scope); + } else if (gt == GrantType.TOKEN_EXCHANGE) { + return processTokenExchange(code, scope, executionContext); } } catch (WebApplicationException e) { throw e; @@ -211,6 +213,11 @@ public Response requestAccessToken(String grantType, String code, throw new WebApplicationException(tokenRestWebServiceValidator.error(400, TokenErrorResponseType.UNSUPPORTED_GRANT_TYPE, "Unsupported Grant Type.").build()); } + private Response processTokenExchange(String code, String scope, ExecutionContext executionContext) { + // todo + return null; + } + private Response processROPC(String username, String password, String scope, GrantType gt, Function idTokenPreProcessing, ExecutionContext executionContext) throws SearchException { boolean authenticated = false; User user = null; diff --git a/jans-auth-server/server/src/test/java/io/jans/as/server/authorize/ws/rs/AuthzRequestServiceTest.java b/jans-auth-server/server/src/test/java/io/jans/as/server/authorize/ws/rs/AuthzRequestServiceTest.java index a3d0f0d6b2a..bc2d5f3664d 100644 --- a/jans-auth-server/server/src/test/java/io/jans/as/server/authorize/ws/rs/AuthzRequestServiceTest.java +++ b/jans-auth-server/server/src/test/java/io/jans/as/server/authorize/ws/rs/AuthzRequestServiceTest.java @@ -1,7 +1,9 @@ package io.jans.as.server.authorize.ws.rs; +import io.jans.as.common.model.registration.Client; import io.jans.as.common.model.session.SessionId; import io.jans.as.common.util.RedirectUri; +import io.jans.as.model.common.GrantType; import io.jans.as.model.config.WebKeysConfiguration; import io.jans.as.model.configuration.AppConfiguration; import io.jans.as.model.crypto.AbstractCryptoProvider; @@ -69,9 +71,13 @@ public class AuthzRequestServiceTest { @Test public void addDeviceSecretToSession_withoutDeviceSsoScope_shouldNotGenerateDeviceSecret() { + Client client = new Client(); + client.setGrantTypes(new GrantType[] { GrantType.AUTHORIZATION_CODE, GrantType.TOKEN_EXCHANGE}); + AuthzRequest authzRequest = new AuthzRequest(); authzRequest.setScope("openid"); authzRequest.setRedirectUriResponse(new RedirectUriResponse(mock(RedirectUri.class), "", mock(HttpServletRequest.class), mock(ErrorResponseFactory.class))); + authzRequest.setClient(client); SessionId sessionId = new SessionId(); @@ -81,9 +87,13 @@ public void addDeviceSecretToSession_withoutDeviceSsoScope_shouldNotGenerateDevi @Test public void addDeviceSecretToSession_withDeviceSsoScope_shouldGenerateDeviceSecret() { + Client client = new Client(); + client.setGrantTypes(new GrantType[] { GrantType.AUTHORIZATION_CODE, GrantType.TOKEN_EXCHANGE}); + AuthzRequest authzRequest = new AuthzRequest(); authzRequest.setRedirectUriResponse(new RedirectUriResponse(mock(RedirectUri.class), "", mock(HttpServletRequest.class), mock(ErrorResponseFactory.class))); authzRequest.setScope("openid device_sso"); + authzRequest.setClient(client); SessionId sessionId = new SessionId(); @@ -92,4 +102,21 @@ public void addDeviceSecretToSession_withDeviceSsoScope_shouldGenerateDeviceSecr assertEquals(1, sessionId.getDeviceSecrets().size()); assertTrue(StringUtils.isNotBlank(sessionId.getDeviceSecrets().get(0))); } + + @Test + public void addDeviceSecretToSession_withClientWithoutTokenExchangeGrantType_shouldNotGenerateDeviceSecret() { + Client client = new Client(); + client.setGrantTypes(new GrantType[] { GrantType.AUTHORIZATION_CODE}); + + AuthzRequest authzRequest = new AuthzRequest(); + authzRequest.setRedirectUriResponse(new RedirectUriResponse(mock(RedirectUri.class), "", mock(HttpServletRequest.class), mock(ErrorResponseFactory.class))); + authzRequest.setScope("openid device_sso"); + authzRequest.setClient(client); + + SessionId sessionId = new SessionId(); + + assertTrue(sessionId.getDeviceSecrets().isEmpty()); + authzRequestService.addDeviceSecretToSession(authzRequest, sessionId); + assertTrue(sessionId.getDeviceSecrets().isEmpty()); + } }