From 01eb1401a39e664e76920528b858ed51a71ac8cf Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Fri, 12 Jan 2018 15:22:37 +0100 Subject: [PATCH] add hook for custom JWT claims to DefaultOIDCTokenService --- .../service/impl/DefaultOIDCTokenService.java | 16 ++++ .../impl/TestDefaultOIDCTokenService.java | 81 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultOIDCTokenService.java diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java index 1d0697204..aea5bfb26 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java @@ -151,6 +151,8 @@ public class DefaultOIDCTokenService implements OIDCTokenService { idClaims.claim("at_hash", at_hash); } + addCustomIdTokenClaims(idClaims, client, request, sub, accessToken); + if (client.getIdTokenEncryptedResponseAlg() != null && !client.getIdTokenEncryptedResponseAlg().equals(Algorithm.NONE) && client.getIdTokenEncryptedResponseEnc() != null && !client.getIdTokenEncryptedResponseEnc().equals(Algorithm.NONE) && (!Strings.isNullOrEmpty(client.getJwksUri()) || client.getJwks() != null)) { @@ -335,4 +337,18 @@ public class DefaultOIDCTokenService implements OIDCTokenService { this.authenticationHolderRepository = authenticationHolderRepository; } + /** + * Hook for subclasses that allows adding custom claims to the JWT + * that will be used as id token. + * @param idClaims the builder holding the current claims + * @param client information about the requesting client + * @param request request that caused the id token to be created + * @param sub subject auf the id token + * @param accessToken the access token + * @param authentication current authentication + */ + protected void addCustomIdTokenClaims(JWTClaimsSet.Builder idClaims, ClientDetailsEntity client, OAuth2Request request, + String sub, OAuth2AccessTokenEntity accessToken) { + } + } diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultOIDCTokenService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultOIDCTokenService.java new file mode 100644 index 000000000..01405474c --- /dev/null +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultOIDCTokenService.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright 2018 The MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +package org.mitre.openid.connect.service.impl; + +import java.util.Date; + +import org.mitre.jwt.signer.service.JWTSigningAndValidationService; +import org.mitre.oauth2.model.ClientDetailsEntity; +import org.mitre.oauth2.model.OAuth2AccessTokenEntity; +import org.mitre.openid.connect.config.ConfigurationPropertiesBean; +import org.springframework.security.oauth2.provider.OAuth2Request; + +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jwt.JWT; +import com.nimbusds.jwt.JWTClaimsSet; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class TestDefaultOIDCTokenService { + private static final String CLIENT_ID = "client"; + private static final String KEY_ID = "key"; + + private ConfigurationPropertiesBean configBean = new ConfigurationPropertiesBean(); + private ClientDetailsEntity client = new ClientDetailsEntity(); + private OAuth2AccessTokenEntity accessToken = new OAuth2AccessTokenEntity(); + private OAuth2Request request = new OAuth2Request(CLIENT_ID) { }; + + @Mock + private JWTSigningAndValidationService jwtService; + + @Before + public void prepare() { + configBean.setIssuer("https://auth.example.org/"); + + client.setClientId(CLIENT_ID); + Mockito.when(jwtService.getDefaultSigningAlgorithm()).thenReturn(JWSAlgorithm.RS256); + Mockito.when(jwtService.getDefaultSignerKeyId()).thenReturn(KEY_ID); + } + + @Test + public void invokesCustomClaimsHook() throws java.text.ParseException { + DefaultOIDCTokenService s = new DefaultOIDCTokenService() { + @Override + protected void addCustomIdTokenClaims(JWTClaimsSet.Builder idClaims, ClientDetailsEntity client, OAuth2Request request, + String sub, OAuth2AccessTokenEntity accessToken) { + idClaims.claim("test", "foo"); + } + }; + configure(s); + + JWT token = s.createIdToken(client, request, new Date(), "sub", accessToken); + Assert.assertEquals("foo", token.getJWTClaimsSet().getClaim("test")); + } + + + private void configure(DefaultOIDCTokenService s) { + s.setConfigBean(configBean); + s.setJwtService(jwtService); + } +}