diff --git a/.gitignore b/.gitignore index af13bd1b..2982f76f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ buildNumber.properties # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) !/.mvn/wrapper/maven-wrapper.jar *.iml +.idea diff --git a/openid/src/main/java/fish/payara/security/openid/AzureDefinitionConverter.java b/openid/src/main/java/fish/payara/security/openid/AzureDefinitionConverter.java index 8168c2c4..df1ecbbb 100644 --- a/openid/src/main/java/fish/payara/security/openid/AzureDefinitionConverter.java +++ b/openid/src/main/java/fish/payara/security/openid/AzureDefinitionConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -169,6 +169,11 @@ public boolean tokenAutoRefresh() { public int tokenMinValidity() { return azureDefinition.tokenMinValidity(); } + + @Override + public boolean userClaimsFromIDToken() { + return azureDefinition.userClaimsFromIDToken(); + } }; } diff --git a/openid/src/main/java/fish/payara/security/openid/GoogleDefinitionConverter.java b/openid/src/main/java/fish/payara/security/openid/GoogleDefinitionConverter.java index c24e0076..e6575a2b 100644 --- a/openid/src/main/java/fish/payara/security/openid/GoogleDefinitionConverter.java +++ b/openid/src/main/java/fish/payara/security/openid/GoogleDefinitionConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -157,6 +157,11 @@ public boolean tokenAutoRefresh() { public int tokenMinValidity() { return googleDefinition.tokenMinValidity(); } + + @Override + public boolean userClaimsFromIDToken() { + return googleDefinition.userClaimsFromIDToken(); + } }; } diff --git a/openid/src/main/java/fish/payara/security/openid/controller/ConfigurationController.java b/openid/src/main/java/fish/payara/security/openid/controller/ConfigurationController.java index a5f65e78..c49789cf 100644 --- a/openid/src/main/java/fish/payara/security/openid/controller/ConfigurationController.java +++ b/openid/src/main/java/fish/payara/security/openid/controller/ConfigurationController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -215,6 +215,7 @@ public OpenIdConfiguration buildConfig(OpenIdAuthenticationDefinition definition boolean tokenAutoRefresh = OpenIdUtil.getConfiguredValue(Boolean.class, definition.tokenAutoRefresh(), provider, OpenIdAuthenticationDefinition.OPENID_MP_TOKEN_AUTO_REFRESH); int tokenMinValidity = OpenIdUtil.getConfiguredValue(Integer.class, definition.tokenMinValidity(), provider, OpenIdAuthenticationDefinition.OPENID_MP_TOKEN_MIN_VALIDITY); + boolean userClaimsFromIDToken = OpenIdUtil.getConfiguredValue(Boolean.class, definition.userClaimsFromIDToken(), provider, OpenIdAuthenticationDefinition.OPENID_MP_USER_CLAIMS_FROM_ID_TOKEN); OpenIdConfiguration configuration = new OpenIdConfiguration() .setProviderMetadata( @@ -256,7 +257,8 @@ public OpenIdConfiguration buildConfig(OpenIdAuthenticationDefinition definition .setJwksConnectTimeout(jwksConnectTimeout) .setJwksReadTimeout(jwksReadTimeout) .setTokenAutoRefresh(tokenAutoRefresh) - .setTokenMinValidity(tokenMinValidity); + .setTokenMinValidity(tokenMinValidity) + .setUserClaimsFromIDToken(userClaimsFromIDToken); validateConfiguration(configuration); diff --git a/openid/src/main/java/fish/payara/security/openid/domain/OpenIdConfiguration.java b/openid/src/main/java/fish/payara/security/openid/domain/OpenIdConfiguration.java index 2f099b8c..c508b275 100644 --- a/openid/src/main/java/fish/payara/security/openid/domain/OpenIdConfiguration.java +++ b/openid/src/main/java/fish/payara/security/openid/domain/OpenIdConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -70,6 +70,7 @@ public class OpenIdConfiguration { private boolean tokenAutoRefresh; private int tokenMinValidity; private JWTValidator validator; + private boolean userClaimsFromIDToken; static final String BASE_URL_EXPRESSION = "${baseURL}"; @@ -253,6 +254,15 @@ public OpenIdConfiguration setTokenMinValidity(int tokenMinValidity) { return this; } + public boolean isUserClaimsFromIDToken() { + return userClaimsFromIDToken; + } + + public OpenIdConfiguration setUserClaimsFromIDToken(boolean userClaimsFromIDToken) { + this.userClaimsFromIDToken = userClaimsFromIDToken; + return this; + } + @Override public String toString() { return OpenIdConfiguration.class.getSimpleName() @@ -273,6 +283,7 @@ public String toString() { + ", encryptionMetadata=" + encryptionMetadata + ", tokenAutoRefresh=" + tokenAutoRefresh + ", tokenMinValidity=" + tokenMinValidity + + ", userClaimsFromIDToken=" + userClaimsFromIDToken + '}'; } diff --git a/openid/src/main/java/fish/payara/security/openid/domain/OpenIdContextImpl.java b/openid/src/main/java/fish/payara/security/openid/domain/OpenIdContextImpl.java index 6592379f..7433bcf3 100644 --- a/openid/src/main/java/fish/payara/security/openid/domain/OpenIdContextImpl.java +++ b/openid/src/main/java/fish/payara/security/openid/domain/OpenIdContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -42,13 +42,15 @@ import fish.payara.security.openid.api.OpenIdClaims; import fish.payara.security.openid.api.OpenIdContext; import fish.payara.security.openid.api.RefreshToken; +import fish.payara.security.openid.api.JwtClaims; +import fish.payara.security.openid.api.OpenIdConstant; import fish.payara.security.openid.controller.AuthenticationController; import fish.payara.security.openid.OpenIdUtil; -import fish.payara.security.openid.api.OpenIdConstant; import fish.payara.security.openid.controller.UserInfoController; import java.io.IOException; import java.util.Optional; +import static java.util.logging.Level.FINEST; import static java.util.logging.Level.WARNING; import java.util.logging.Logger; import java.util.Set; @@ -162,7 +164,12 @@ public void setExpiresIn(Long expiresIn) { public JsonObject getClaimsJson() { if (claims == null) { if (configuration != null && accessToken != null) { - claims = userInfoController.getUserInfo(configuration, accessToken); + if(!configuration.isUserClaimsFromIDToken()) { + claims = userInfoController.getUserInfo(configuration, accessToken); + } else { + LOGGER.log(FINEST, "Processing user info from ID Token"); + claims = processUserClaimsFromIDToken(); + } } else { claims = Json.createObjectBuilder().build(); } @@ -170,6 +177,28 @@ public JsonObject getClaimsJson() { return claims; } + /** + * Method to get user information from Id Token + * @return JsonObject with user information + */ + private JsonObject processUserClaimsFromIDToken() { + JwtClaims identityTokenJWTClaims = identityToken.getJwtClaims(); + JwtClaims accessTokenJWTClaims = accessToken.getJwtClaims(); + //setting profile claims from id token + JsonObject userInfo = Json.createObjectBuilder() + .add(OpenIdConstant.SUBJECT_IDENTIFIER, identityTokenJWTClaims.getStringClaim(OpenIdConstant.SUBJECT_IDENTIFIER).orElse("")) + .add(OpenIdConstant.NAME, identityTokenJWTClaims.getStringClaim(OpenIdConstant.NAME).orElse("")) + .add(OpenIdConstant.FAMILY_NAME, accessTokenJWTClaims.getStringClaim(OpenIdConstant.FAMILY_NAME).orElse("")) + .add(OpenIdConstant.GIVEN_NAME, accessTokenJWTClaims.getStringClaim(OpenIdConstant.GIVEN_NAME).orElse("")) + .add(OpenIdConstant.EMAIL, identityTokenJWTClaims.getStringClaim(OpenIdConstant.EMAIL).orElse("")).build(); + + if(!this.getSubject().equals(userInfo.getString(OpenIdConstant.SUBJECT_IDENTIFIER))) { + throw new IllegalStateException("UserInfo Response is invalid as sub claim must match with the sub Claim in the ID Token"); + } + + return userInfo; + } + @Override public OpenIdClaims getClaims() { return new JsonClaims(getClaimsJson()); diff --git a/security-connectors-api/src/main/java/fish/payara/security/annotations/AzureAuthenticationDefinition.java b/security-connectors-api/src/main/java/fish/payara/security/annotations/AzureAuthenticationDefinition.java index d3b7140f..e28b54a9 100644 --- a/security-connectors-api/src/main/java/fish/payara/security/annotations/AzureAuthenticationDefinition.java +++ b/security-connectors-api/src/main/java/fish/payara/security/annotations/AzureAuthenticationDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -240,4 +240,11 @@ * @return */ int tokenMinValidity() default 10 * 1000; + + /** + * Optional. Indicates to skip the /userinfo endpoint call and get the user information from ID Token. + * + * @return + */ + boolean userClaimsFromIDToken() default false; } diff --git a/security-connectors-api/src/main/java/fish/payara/security/annotations/GoogleAuthenticationDefinition.java b/security-connectors-api/src/main/java/fish/payara/security/annotations/GoogleAuthenticationDefinition.java index db153b5f..7b256a61 100644 --- a/security-connectors-api/src/main/java/fish/payara/security/annotations/GoogleAuthenticationDefinition.java +++ b/security-connectors-api/src/main/java/fish/payara/security/annotations/GoogleAuthenticationDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -227,4 +227,12 @@ * @return */ int tokenMinValidity() default 10 * 1000; + + /** + * Optional. Indicates to skip the /userinfo endpoint call and get the user information from ID Token. + * + * @return + */ + boolean userClaimsFromIDToken() default false; + } diff --git a/security-connectors-api/src/main/java/fish/payara/security/annotations/OpenIdAuthenticationDefinition.java b/security-connectors-api/src/main/java/fish/payara/security/annotations/OpenIdAuthenticationDefinition.java index def24677..ce04f37b 100644 --- a/security-connectors-api/src/main/java/fish/payara/security/annotations/OpenIdAuthenticationDefinition.java +++ b/security-connectors-api/src/main/java/fish/payara/security/annotations/OpenIdAuthenticationDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -232,6 +232,13 @@ */ int tokenMinValidity() default 10 * 1000; + /** + * Optional. Indicates to skip the /userinfo endpoint call and get the user information from ID Token. + * + * @return + */ + boolean userClaimsFromIDToken() default false; + /** * The Microprofile Config key for the provider uri is {@value} */ @@ -359,4 +366,10 @@ * The Microprofile Config key for evaluating EL expressions for every HTTP session is {@value} */ String OPENID_MP_SESSION_SCOPED_CONFIGURATION = "payara.security.openid.sessionScopedConfiguration"; + + /** + * The Microprofile Config key to skip the /userinfo endpoint call + * and get the user information from ID Token is {@value} + */ + String OPENID_MP_USER_CLAIMS_FROM_ID_TOKEN = "payara.security.openid.userClaimsFromIDToken"; }