From 3546cafb4942247edf298996186fcdfa32eb9954 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 17 Dec 2013 08:33:18 +0100 Subject: First version for testing -> Exthex OAuth implementation --- .project | 10 +- .../moa/id/configuration/Constants.java | 1 + .../id/configuration/data/oa/OAOAuth20Config.java | 82 +++ .../configuration/struts/action/EditOAAction.java | 500 ++++++++-------- .../validation/oa/OAOAUTH20ConfigValidation.java | 33 ++ .../main/resources/applicationResources.properties | 13 + id/ConfigWebTool/src/main/webapp/js/common.js | 12 + .../src/main/webapp/jsp/editOAGeneral.jsp | 28 +- .../auth/src/main/webapp/WEB-INF/urlrewrite.xml | 10 + id/server/idserverlib/pom.xml | 128 ++-- .../auth/builder/StartAuthenticationBuilder.java | 7 +- .../moa/id/auth/data/AuthenticationSession.java | 649 ++++++++++----------- .../gv/egovernment/moa/id/config/OAParameter.java | 123 ++-- .../id/config/auth/AuthConfigurationProvider.java | 19 +- .../moa/id/entrypoints/DispatcherServlet.java | 2 +- .../gv/egovernment/moa/id/moduls/ModulStorage.java | 3 +- .../id/protocols/oauth20/OAuth20AuthAction.java | 92 +++ .../id/protocols/oauth20/OAuth20Configuration.java | 51 ++ .../moa/id/protocols/oauth20/OAuth20Constants.java | 45 ++ .../moa/id/protocols/oauth20/OAuth20Protocol.java | 166 ++++++ .../id/protocols/oauth20/OAuth20SessionObject.java | 39 ++ .../id/protocols/oauth20/OAuth20TokenAction.java | 346 +++++++++++ .../moa/id/protocols/oauth20/OAuth20Util.java | 134 +++++ .../exceptions/OAuth20AccessDeniedException.java | 12 + .../OAuth20CertificateErrorException.java | 12 + .../oauth20/exceptions/OAuth20Exception.java | 49 ++ .../exceptions/OAuth20InvalidClientException.java | 12 + .../exceptions/OAuth20InvalidGrantException.java | 12 + .../exceptions/OAuth20InvalidRequestException.java | 13 + .../exceptions/OAuth20ResponseTypeException.java | 12 + .../exceptions/OAuth20ServerErrorException.java | 12 + .../OAuth20UnauthorizedClientException.java | 12 + .../exceptions/OAuth20WrongParameterException.java | 12 + .../oauth20/requests/OAuth20AuthRequest.java | 134 +++++ .../oauth20/requests/OAuth20BaseRequest.java | 118 ++++ .../oauth20/requests/OAuth20TokenRequest.java | 118 ++++ .../resources/properties/id_messages_de.properties | 13 +- .../gv/egovernment/moa/id/auth/oauth/CertTest.java | 86 +++ .../moa/id/auth/oauth/OAuth20ErrorsTests.java | 190 ++++++ .../id/auth/oauth/OAuth20GoogleClientTestCase.java | 136 +++++ .../moa/id/auth/oauth/OAuth20UtilTest.java | 48 ++ .../db/dao/session/AuthenticatedSessionStore.java | 4 +- .../src/main/resources/config/moaid_config_2.0.xsd | 11 + 43 files changed, 2791 insertions(+), 718 deletions(-) create mode 100644 id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/data/oa/OAOAuth20Config.java create mode 100644 id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/validation/oa/OAOAUTH20ConfigValidation.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20AuthAction.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Configuration.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Constants.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Protocol.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20SessionObject.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20TokenAction.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Util.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20AccessDeniedException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20CertificateErrorException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20Exception.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidClientException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidGrantException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidRequestException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20ResponseTypeException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20ServerErrorException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20UnauthorizedClientException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20WrongParameterException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20AuthRequest.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20BaseRequest.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20TokenRequest.java create mode 100644 id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/CertTest.java create mode 100644 id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20ErrorsTests.java create mode 100644 id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20GoogleClientTestCase.java create mode 100644 id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20UtilTest.java diff --git a/.project b/.project index 04de71285..19ca19d10 100644 --- a/.project +++ b/.project @@ -16,7 +16,7 @@ - org.maven.ide.eclipse.maven2Builder + org.eclipse.m2e.core.maven2Builder @@ -25,18 +25,12 @@ - - org.eclipse.m2e.core.maven2Builder - - - - org.eclipse.m2e.core.maven2Nature org.eclipse.jem.workbench.JavaEMFNature org.eclipse.wst.common.modulecore.ModuleCoreNature org.eclipse.jdt.core.javanature - org.maven.ide.eclipse.maven2Nature org.eclipse.wst.common.project.facet.core.nature + org.eclipse.m2e.core.maven2Nature diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java index 9dc49bba8..536cc0522 100644 --- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java @@ -23,6 +23,7 @@ public class Constants { public static final String SESSION_PVP2REQUESTID = "pvp2requestid"; public static final String SESSION_RETURNAREA = "returnarea"; public static final String SESSION_BKUFORMPREVIEW = "bkuformpreview"; + public static final String SESSION_OAUTH20SECRET = "oauth20secret"; public static enum STRUTS_RETURNAREA_VALUES {adminRequestsInit, main, usermanagementInit}; diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/data/oa/OAOAuth20Config.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/data/oa/OAOAuth20Config.java new file mode 100644 index 000000000..b153e02a8 --- /dev/null +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/data/oa/OAOAuth20Config.java @@ -0,0 +1,82 @@ +package at.gv.egovernment.moa.id.configuration.data.oa; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import at.gv.egovernment.moa.id.commons.db.dao.config.AuthComponentOA; +import at.gv.egovernment.moa.id.commons.db.dao.config.OAOAUTH20; +import at.gv.egovernment.moa.id.commons.db.dao.config.OnlineApplication; +import at.gv.egovernment.moa.id.configuration.helper.LanguageHelper; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Util; + +public class OAOAuth20Config { + + private final Logger log = Logger.getLogger(OAOAuth20Config.class); + + private String clientId = null; + private String clientSecret = null; + private String redirectUri = null; + + public OAOAuth20Config() { + } + + public List parse(OnlineApplication dbOAConfig) { + List errors = new ArrayList(); + + AuthComponentOA authdata = dbOAConfig.getAuthComponentOA(); + if (authdata != null) { + OAOAUTH20 config = authdata.getOAOAUTH20(); + // set client id to public url prefix + this.clientId = dbOAConfig.getPublicURLPrefix(); + + // validate secret + if (StringUtils.isNotEmpty(config.getOAuthClientSecret())) { + this.clientSecret = config.getOAuthClientSecret(); + } else { + this.generateClientSecret(); + } + + // validate redirectUri + if (StringUtils.isNotEmpty(config.getOAuthRedirectUri()) && OAuth20Util.isUrl(config.getOAuthRedirectUri())) { + this.redirectUri = config.getOAuthRedirectUri(); + } else { + errors.add(LanguageHelper.getErrorString("error.oa.oauth.redirecturi")); + } + } + + return errors; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public String getRedirectUri() { + return redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public void generateClientSecret() { + this.clientSecret = UUID.randomUUID().toString(); + } + +} diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/EditOAAction.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/EditOAAction.java index 04b4da19a..fc66eede4 100644 --- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/EditOAAction.java +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/EditOAAction.java @@ -19,7 +19,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; @@ -35,6 +34,7 @@ import at.gv.egovernment.moa.id.commons.db.dao.config.IdentificationNumber; import at.gv.egovernment.moa.id.commons.db.dao.config.MOAIDConfiguration; import at.gv.egovernment.moa.id.commons.db.dao.config.MOAKeyBoxSelector; import at.gv.egovernment.moa.id.commons.db.dao.config.Mandates; +import at.gv.egovernment.moa.id.commons.db.dao.config.OAOAUTH20; import at.gv.egovernment.moa.id.commons.db.dao.config.OAPVP2; import at.gv.egovernment.moa.id.commons.db.dao.config.OASAML1; import at.gv.egovernment.moa.id.commons.db.dao.config.OASSO; @@ -46,12 +46,12 @@ import at.gv.egovernment.moa.id.commons.db.dao.config.TemplatesType; import at.gv.egovernment.moa.id.commons.db.dao.config.TransformsInfoType; import at.gv.egovernment.moa.id.commons.db.dao.config.UserDatabase; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.configuration.Constants; import at.gv.egovernment.moa.id.configuration.auth.AuthenticatedUser; import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider; import at.gv.egovernment.moa.id.configuration.data.FormularCustomization; import at.gv.egovernment.moa.id.configuration.data.oa.OAGeneralConfig; +import at.gv.egovernment.moa.id.configuration.data.oa.OAOAuth20Config; import at.gv.egovernment.moa.id.configuration.data.oa.OAPVP2Config; import at.gv.egovernment.moa.id.configuration.data.oa.OASAML1Config; import at.gv.egovernment.moa.id.configuration.data.oa.OASSOConfig; @@ -63,28 +63,27 @@ import at.gv.egovernment.moa.id.configuration.validation.FormularCustomizationVa import at.gv.egovernment.moa.id.configuration.validation.TargetValidator; import at.gv.egovernment.moa.id.configuration.validation.ValidationHelper; import at.gv.egovernment.moa.id.configuration.validation.oa.OAGeneralConfigValidation; +import at.gv.egovernment.moa.id.configuration.validation.oa.OAOAUTH20ConfigValidation; import at.gv.egovernment.moa.id.configuration.validation.oa.OAPVP2ConfigValidation; import at.gv.egovernment.moa.id.configuration.validation.oa.OASAML1ConfigValidation; import at.gv.egovernment.moa.id.configuration.validation.oa.OASSOConfigValidation; import at.gv.egovernment.moa.id.configuration.validation.oa.OASTORKConfigValidation; import at.gv.egovernment.moa.id.util.FormBuildUtils; -import at.gv.egovernment.moa.id.util.HTTPUtils; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.util.MiscUtil; import com.opensymphony.xwork2.ActionSupport; -public class EditOAAction extends ActionSupport implements ServletRequestAware, -ServletResponseAware { - +public class EditOAAction extends ActionSupport implements ServletRequestAware, ServletResponseAware { + private final Logger log = Logger.getLogger(EditOAAction.class); private static final long serialVersionUID = 1L; - + private HttpServletRequest request; private HttpServletResponse response; - private AuthenticatedUser authUser; + private AuthenticatedUser authUser; private String oaidobj; private boolean newOA; @@ -96,17 +95,18 @@ ServletResponseAware { private boolean isMetaDataRefreshRequired = false; private String nextPage; - + private OAGeneralConfig generalOA = new OAGeneralConfig(); private OAPVP2Config pvp2OA = new OAPVP2Config(); private OASAML1Config saml1OA = new OASAML1Config(); private OASSOConfig ssoOA = new OASSOConfig(); + private OAOAuth20Config oauth20OA = new OAOAuth20Config(); private OASTORKConfig storkOA; private FormularCustomization formOA = new FormularCustomization(); private InputStream stream; - //STRUTS actions + // STRUTS actions public String inital() { HttpSession session = request.getSession(); if (session == null) { @@ -127,40 +127,39 @@ ServletResponseAware { oaid = Long.valueOf(oaidobj); UserDatabase userdb = null; - OnlineApplication onlineapplication = null;; + OnlineApplication onlineapplication = null; if (authUser.isAdmin()) onlineapplication = ConfigurationDBRead.getOnlineApplication(oaid); else { userdb = ConfigurationDBRead.getUserWithID(authUser.getUserID()); - - if (!authUser.isAdmin() && userdb.isIsMailAddressVerified() != null - && !userdb.isIsMailAddressVerified()) { + + if (!authUser.isAdmin() && userdb.isIsMailAddressVerified() != null && !userdb.isIsMailAddressVerified()) { log.info("Online-Applikation managemant disabled. Mail address is not verified."); addActionError(LanguageHelper.getErrorString("error.editoa.mailverification")); return Constants.STRUTS_SUCCESS; } - - //TODO: change to direct Database operation + // TODO: change to direct Database operation List oas = userdb.getOnlineApplication(); for (OnlineApplication oa : oas) { if (oa.getHjid() == oaid) { onlineapplication = oa; break; } - } + } if (onlineapplication == null) { addActionError(LanguageHelper.getErrorString("errors.edit.oa.oaid", request)); return Constants.STRUTS_ERROR; } } - + generalOA.parse(onlineapplication); ssoOA.parse(onlineapplication); saml1OA.parse(onlineapplication); - + oauth20OA.parse(onlineapplication); + session.setAttribute(Constants.SESSION_OAUTH20SECRET, this.oauth20OA.getClientSecret()); Map map = new HashMap(); map.putAll(FormBuildUtils.getDefaultMap()); @@ -172,14 +171,13 @@ ServletResponseAware { if (errors.size() > 0) { for (String el : errors) - addActionError(el); + addActionError(el); } subTargetSet = MiscUtil.isNotEmpty(generalOA.getTarget_subsector()); - //set UserSpezific OA Parameters - if (!authUser.isAdmin()) - generateUserSpecificConfigurationOptions(userdb); + // set UserSpezific OA Parameters + if (!authUser.isAdmin()) generateUserSpecificConfigurationOptions(userdb); ConfigurationDBUtils.closeSession(); session.setAttribute(Constants.SESSION_OAID, oaid); @@ -194,24 +192,23 @@ ServletResponseAware { public String newOA() { log.debug("insert new Online-Application"); - + HttpSession session = request.getSession(); if (session == null) { log.info("No http Session found."); return Constants.STRUTS_ERROR; } - + session.setAttribute(Constants.SESSION_OAID, null); nextPage = Constants.STRUTS_RETURNAREA_VALUES.main.name(); Object authUserObj = session.getAttribute(Constants.SESSION_AUTH); authUser = (AuthenticatedUser) authUserObj; - + UserDatabase userdb = ConfigurationDBRead.getUserWithID(authUser.getUserID()); - if (!authUser.isAdmin() && userdb.isIsMailAddressVerified() != null - && !userdb.isIsMailAddressVerified()) { + if (!authUser.isAdmin() && userdb.isIsMailAddressVerified() != null && !userdb.isIsMailAddressVerified()) { log.info("Online-Applikation managemant disabled. Mail address is not verified."); addActionError(LanguageHelper.getErrorString("error.editoa.mailverification")); return Constants.STRUTS_SUCCESS; @@ -227,10 +224,8 @@ ServletResponseAware { } } - //set UserSpezific OA Parameters - if (!authUser.isAdmin()) - generateUserSpecificConfigurationOptions(userdb); - + // set UserSpezific OA Parameters + if (!authUser.isAdmin()) generateUserSpecificConfigurationOptions(userdb); ConfigurationDBUtils.closeSession(); @@ -240,6 +235,9 @@ ServletResponseAware { session.setAttribute(Constants.SESSION_BKUFORMPREVIEW, null); + this.oauth20OA.generateClientSecret(); + session.setAttribute(Constants.SESSION_OAUTH20SECRET, this.oauth20OA.getClientSecret()); + return Constants.STRUTS_OA_EDIT; } @@ -252,25 +250,24 @@ ServletResponseAware { Object authUserObj = session.getAttribute(Constants.SESSION_AUTH); authUser = (AuthenticatedUser) authUserObj; - + Object formidobj = session.getAttribute(Constants.SESSION_FORMID); if (formidobj != null && formidobj instanceof String) { String formid = (String) formidobj; if (!formid.equals(formID)) { - log.warn("FormIDs does not match. Some suspect Form is received from user " - + authUser.getFamilyName() + authUser.getGivenName() + authUser.getUserID()); + log.warn("FormIDs does not match. Some suspect Form is received from user " + authUser.getFamilyName() + + authUser.getGivenName() + authUser.getUserID()); return Constants.STRUTS_ERROR; - } + } } else { - log.warn("FormIDs does not match. Some suspect Form is received from user " - + authUser.getFamilyName() + authUser.getGivenName() + authUser.getUserID()); + log.warn("FormIDs does not match. Some suspect Form is received from user " + authUser.getFamilyName() + + authUser.getGivenName() + authUser.getUserID()); return Constants.STRUTS_ERROR; } session.setAttribute(Constants.SESSION_FORMID, null); UserDatabase userdb = ConfigurationDBRead.getUserWithID(authUser.getUserID()); - if (!authUser.isAdmin() && - userdb.isIsMailAddressVerified() != null && !userdb.isIsMailAddressVerified()) { + if (!authUser.isAdmin() && userdb.isIsMailAddressVerified() != null && !userdb.isIsMailAddressVerified()) { log.info("Online-Applikation managemant disabled. Mail address is not verified."); addActionError(LanguageHelper.getErrorString("error.editoa.mailverification")); return Constants.STRUTS_SUCCESS; @@ -282,21 +279,22 @@ ServletResponseAware { Object oadbid = request.getSession().getAttribute(Constants.SESSION_OAID); Long oaid = (long) -1; - if (oadbid != null ) { + if (oadbid != null) { try { - oaid = (Long) oadbid; + oaid = (Long) oadbid; if (oaid < 0 || oaid > Long.MAX_VALUE) { addActionError(LanguageHelper.getErrorString("errors.edit.oa.oaid", request)); - return Constants.STRUTS_ERROR; + return Constants.STRUTS_ERROR; } - } catch (Throwable t) { + } + catch (Throwable t) { addActionError(LanguageHelper.getErrorString("errors.edit.oa.oaid", request)); - return Constants.STRUTS_ERROR; + return Constants.STRUTS_ERROR; } } - //valid DBID and check entry + // valid DBID and check entry String oaidentifier = generalOA.getIdentifier(); if (MiscUtil.isEmpty(oaidentifier)) { log.info("Empty OA identifier"); @@ -306,14 +304,14 @@ ServletResponseAware { if (!ValidationHelper.validateURL(oaidentifier)) { log.warn("OnlineapplikationIdentifier is not a valid URL: " + oaidentifier); - errors.add(LanguageHelper.getErrorString("validation.general.oaidentifier.valid", - new Object[] {ValidationHelper.getNotValidOAIdentifierCharacters()} )); + errors.add(LanguageHelper.getErrorString("validation.general.oaidentifier.valid", + new Object[] { ValidationHelper.getNotValidOAIdentifierCharacters() })); } else { - + if (oaid == -1) { onlineapplication = ConfigurationDBRead.getOnlineApplication(oaidentifier); newOA = true; - if (onlineapplication != null) { + if (onlineapplication != null) { log.info("The OAIdentifier is not unique"); errors.add(LanguageHelper.getErrorString("validation.general.oaidentifier.notunique")); } @@ -322,7 +320,7 @@ ServletResponseAware { onlineapplication = ConfigurationDBRead.getOnlineApplication(oaid); if (!oaidentifier.equals(onlineapplication.getPublicURLPrefix())) { - if (ConfigurationDBRead.getOnlineApplication(oaidentifier) != null) { + if (ConfigurationDBRead.getOnlineApplication(oaidentifier) != null) { log.info("The OAIdentifier is not unique"); errors.add(LanguageHelper.getErrorString("validation.general.oaidentifier.notunique")); } @@ -331,113 +329,104 @@ ServletResponseAware { } } - //set UserSpezific OA Parameters - if (!authUser.isAdmin()) - generateUserSpecificConfigurationOptions(userdb); + // set UserSpezific OA Parameters + if (!authUser.isAdmin()) generateUserSpecificConfigurationOptions(userdb); - //check form + // check form OAGeneralConfigValidation validatior_general = new OAGeneralConfigValidation(); OAPVP2ConfigValidation validatior_pvp2 = new OAPVP2ConfigValidation(); OASAML1ConfigValidation validatior_saml1 = new OASAML1ConfigValidation(); OASSOConfigValidation validatior_sso = new OASSOConfigValidation(); OASTORKConfigValidation validator_stork = new OASTORKConfigValidation(); FormularCustomizationValitator validator_form = new FormularCustomizationValitator(); + OAOAUTH20ConfigValidation validatior_oauth20 = new OAOAUTH20ConfigValidation(); - errors.addAll(validatior_general.validate(generalOA, authUser.isAdmin())); + errors.addAll(validatior_general.validate(generalOA, authUser.isAdmin())); errors.addAll(validatior_pvp2.validate(pvp2OA)); errors.addAll(validatior_saml1.validate(saml1OA, generalOA)); errors.addAll(validatior_sso.validate(ssoOA, authUser.isAdmin())); - errors.addAll(validator_stork.validate(storkOA)); + errors.addAll(validator_stork.validate(storkOA)); errors.addAll(validator_form.validate(formOA)); + errors.addAll(validatior_oauth20.validate(oauth20OA)); - //Do not allow SSO in combination with special BKUSelection features - if (ssoOA.isUseSSO() && - ( formOA.isOnlyMandateAllowed() || !formOA.isShowMandateLoginButton()) ) { + // Do not allow SSO in combination with special BKUSelection features + if (ssoOA.isUseSSO() && (formOA.isOnlyMandateAllowed() || !formOA.isShowMandateLoginButton())) { log.warn("Special BKUSelection features can not be used in combination with SSO"); - errors.add(LanguageHelper.getErrorString("validation.general.bkuselection.specialfeatures.valid")); + errors.add(LanguageHelper.getErrorString("validation.general.bkuselection.specialfeatures.valid")); } if (errors.size() > 0) { log.info("OAConfiguration with ID " + generalOA.getIdentifier() + " has some errors."); for (String el : errors) - addActionError(el); + addActionError(el); formID = Random.nextRandom(); session.setAttribute(Constants.SESSION_FORMID, formID); return Constants.STRUTS_ERROR_VALIDATION; } else { - + boolean newentry = false; if (onlineapplication == null) { onlineapplication = new OnlineApplication(); newentry = true; onlineapplication.setIsActive(false); - + if (!authUser.isAdmin()) { onlineapplication.setIsAdminRequired(true); } else isMetaDataRefreshRequired = true; - } else { - if (!authUser.isAdmin() && - !onlineapplication.getPublicURLPrefix(). - equals(generalOA.getIdentifier())) { + if (!authUser.isAdmin() && !onlineapplication.getPublicURLPrefix().equals(generalOA.getIdentifier())) { onlineapplication.setIsAdminRequired(true); onlineapplication.setIsActive(false); - log.info("User with ID " + authUser.getUserID() - + " change OA-PublicURLPrefix. Reaktivation is required."); + log.info("User with ID " + authUser.getUserID() + " change OA-PublicURLPrefix. Reaktivation is required."); } } - if ( (onlineapplication.isIsAdminRequired() == null) || - (authUser.isAdmin() && generalOA.isActive() - && onlineapplication.isIsAdminRequired()) ) { + if ((onlineapplication.isIsAdminRequired() == null) + || (authUser.isAdmin() && generalOA.isActive() && onlineapplication.isIsAdminRequired())) { onlineapplication.setIsAdminRequired(false); isMetaDataRefreshRequired = true; - if (onlineapplication.getHjid() != null) - userdb = ConfigurationDBRead.getUsersWithOADBID(onlineapplication.getHjid()); + if (onlineapplication.getHjid() != null) userdb = ConfigurationDBRead.getUsersWithOADBID(onlineapplication.getHjid()); - if (userdb != null && !userdb.isIsAdmin() ) { + if (userdb != null && !userdb.isIsAdmin()) { try { - MailHelper.sendUserOnlineApplicationActivationMail( - userdb.getGivenname(), - userdb.getFamilyname(), - userdb.getInstitut(), - onlineapplication.getPublicURLPrefix(), - userdb.getMail()); - } catch (ConfigurationException e) { + MailHelper.sendUserOnlineApplicationActivationMail(userdb.getGivenname(), userdb.getFamilyname(), + userdb.getInstitut(), onlineapplication.getPublicURLPrefix(), userdb.getMail()); + } + catch (ConfigurationException e) { log.warn("Sending Mail to User " + userdb.getMail() + " failed", e); } - } + } } if (pvp2OA.getMetaDataURL() != null) { try { - if (isMetaDataRefreshRequired || !pvp2OA.getMetaDataURL(). - equals(onlineapplication.getAuthComponentOA().getOAPVP2().getMetadataURL())) { - + if (isMetaDataRefreshRequired + || !pvp2OA.getMetaDataURL().equals(onlineapplication.getAuthComponentOA().getOAPVP2().getMetadataURL())) { + log.debug("Set PVP2 Metadata refresh flag."); MOAIDConfiguration moaconfig = ConfigurationDBRead.getMOAIDConfiguration(); moaconfig.setPvp2RefreshItem(new Date()); ConfigurationDBUtils.saveOrUpdate(moaconfig); - + } - } catch (Throwable e) { + } + catch (Throwable e) { log.info("Found no MetadataURL in OA-Databaseconfig!", e); } } - String error = saveOAConfigToDatabase(onlineapplication, newentry); if (MiscUtil.isNotEmpty(error)) { log.warn("OA configuration can not be stored!"); @@ -449,7 +438,7 @@ ServletResponseAware { } } - Object nextPageAttr = session.getAttribute(Constants.SESSION_RETURNAREA); + Object nextPageAttr = session.getAttribute(Constants.SESSION_RETURNAREA); if (nextPageAttr != null && nextPageAttr instanceof String) { nextPage = (String) nextPageAttr; session.setAttribute(Constants.SESSION_RETURNAREA, null); @@ -458,33 +447,29 @@ ServletResponseAware { nextPage = Constants.STRUTS_RETURNAREA_VALUES.main.name(); } - if (onlineapplication.isIsAdminRequired()) { int numoas = 0; int numusers = 0; List openOAs = ConfigurationDBRead.getAllNewOnlineApplications(); - if (openOAs != null) - numoas = openOAs.size(); + if (openOAs != null) numoas = openOAs.size(); List openUsers = ConfigurationDBRead.getAllNewUsers(); - if (openUsers != null) - numusers = openUsers.size(); + if (openUsers != null) numusers = openUsers.size(); try { addActionMessage(LanguageHelper.getGUIString("webpages.oaconfig.success.admin", generalOA.getIdentifier(), request)); - if (numusers > 0 || numoas > 0) - MailHelper.sendAdminMail(numoas, numusers); + if (numusers > 0 || numoas > 0) MailHelper.sendAdminMail(numoas, numusers); - } catch (ConfigurationException e) { + } + catch (ConfigurationException e) { log.warn("Sending Mail to Admin failed.", e); } } else - addActionMessage(LanguageHelper.getGUIString("webpages.oaconfig.success", generalOA.getIdentifier(), request)); + addActionMessage(LanguageHelper.getGUIString("webpages.oaconfig.success", generalOA.getIdentifier(), request)); - request.getSession().setAttribute(Constants.SESSION_OAID, null); ConfigurationDBUtils.closeSession(); @@ -498,8 +483,8 @@ ServletResponseAware { log.info("No http Session found."); return Constants.STRUTS_ERROR; } - - Object nextPageAttr = session.getAttribute(Constants.SESSION_RETURNAREA); + + Object nextPageAttr = session.getAttribute(Constants.SESSION_RETURNAREA); if (nextPageAttr != null && nextPageAttr instanceof String) { nextPage = (String) nextPageAttr; session.setAttribute(Constants.SESSION_RETURNAREA, null); @@ -531,28 +516,27 @@ ServletResponseAware { if (formidobj != null && formidobj instanceof String) { String formid = (String) formidobj; if (!formid.equals(formID)) { - log.warn("FormIDs does not match. Some suspect Form is received from user " - + authUser.getFamilyName() + authUser.getGivenName() + authUser.getUserID()); + log.warn("FormIDs does not match. Some suspect Form is received from user " + authUser.getFamilyName() + + authUser.getGivenName() + authUser.getUserID()); return Constants.STRUTS_ERROR; - } + } } else { - log.warn("FormIDs does not match. Some suspect Form is received from user " - + authUser.getFamilyName() + authUser.getGivenName() + authUser.getUserID()); + log.warn("FormIDs does not match. Some suspect Form is received from user " + authUser.getFamilyName() + + authUser.getGivenName() + authUser.getUserID()); return Constants.STRUTS_ERROR; } session.setAttribute(Constants.SESSION_FORMID, null); - Object nextPageAttr = session.getAttribute(Constants.SESSION_RETURNAREA); + Object nextPageAttr = session.getAttribute(Constants.SESSION_RETURNAREA); if (nextPageAttr != null && nextPageAttr instanceof String) { nextPage = (String) nextPageAttr; } else { nextPage = Constants.STRUTS_RETURNAREA_VALUES.main.name(); } - + UserDatabase userdb = ConfigurationDBRead.getUserWithID(authUser.getUserID()); - if (!authUser.isAdmin() && userdb.isIsMailAddressVerified() != null && - !userdb.isIsMailAddressVerified()) { + if (!authUser.isAdmin() && userdb.isIsMailAddressVerified() != null && !userdb.isIsMailAddressVerified()) { log.info("Online-Applikation managemant disabled. Mail address is not verified."); addActionError(LanguageHelper.getErrorString("error.editoa.mailverification")); return Constants.STRUTS_SUCCESS; @@ -570,32 +554,31 @@ ServletResponseAware { } else { if (ValidationHelper.isValidOAIdentifier(oaidentifier)) { log.warn("IdentificationNumber contains potentail XSS characters: " + oaidentifier); - addActionError(LanguageHelper.getErrorString("validation.general.oaidentifier.valid", - new Object[] {ValidationHelper.getNotValidOAIdentifierCharacters()} )); + addActionError(LanguageHelper.getErrorString("validation.general.oaidentifier.valid", + new Object[] { ValidationHelper.getNotValidOAIdentifierCharacters() })); formID = Random.nextRandom(); session.setAttribute(Constants.SESSION_FORMID, formID); return Constants.STRUTS_ERROR_VALIDATION; } } - + OnlineApplication onlineapplication = ConfigurationDBRead.getOnlineApplication(oaidentifier); request.getSession().setAttribute(Constants.SESSION_OAID, null); - try { if (MiscUtil.isNotEmpty(onlineapplication.getAuthComponentOA().getOAPVP2().getMetadataURL())) { - + MOAIDConfiguration moaconfig = ConfigurationDBRead.getMOAIDConfiguration(); moaconfig.setPvp2RefreshItem(new Date()); ConfigurationDBUtils.saveOrUpdate(moaconfig); - + } - } catch (Throwable e) { + } + catch (Throwable e) { log.info("Found no MetadataURL in OA-Databaseconfig!", e); } - if (ConfigurationDBUtils.delete(onlineapplication)) { if (!authUser.isAdmin()) { @@ -611,7 +594,8 @@ ServletResponseAware { try { ConfigurationDBUtils.saveOrUpdate(user); - } catch (MOADatabaseException e) { + } + catch (MOADatabaseException e) { log.warn("User information can not be updated in database", e); addActionError(LanguageHelper.getGUIString("error.db.oa.store", request)); return Constants.STRUTS_ERROR; @@ -627,15 +611,13 @@ ServletResponseAware { } else { ConfigurationDBUtils.closeSession(); addActionError(LanguageHelper.getGUIString("webpages.oaconfig.delete.error", generalOA.getIdentifier(), request)); - return Constants.STRUTS_SUCCESS; + return Constants.STRUTS_SUCCESS; } - - } public String bkuFramePreview() { - + String preview = null; HttpSession session = request.getSession(); @@ -651,12 +633,11 @@ ServletResponseAware { if (mapobj != null && mapobj instanceof Map) { ConfigurationProvider config = ConfigurationProvider.getInstance(); - String templateURL = config.getConfigRootDir() + - ConfigurationProvider.HTMLTEMPLATE_DIR + - ConfigurationProvider.HTMLTEMPLATE_FILE; + String templateURL = config.getConfigRootDir() + ConfigurationProvider.HTMLTEMPLATE_DIR + + ConfigurationProvider.HTMLTEMPLATE_FILE; File file = new File(templateURL); - input = new FileInputStream(file); + input = new FileInputStream(file); String contextpath = config.getMOAIDInstanceURL(); if (MiscUtil.isEmpty(contextpath)) { @@ -667,7 +648,6 @@ ServletResponseAware { preview = LoginFormBuilder.getTemplate(input); preview = preview.replace(LoginFormBuilder.CONTEXTPATH, contextpath); - Map map = (Map) mapobj; request.setCharacterEncoding("UTF-8"); @@ -679,22 +659,20 @@ ServletResponseAware { String[] query = URLDecoder.decode(request.getQueryString()).split("&"); value = query[1].substring("value=".length()); } - + synchronized (map) { - + if (MiscUtil.isNotEmpty(module)) { - if (map.containsKey("#"+module+"#")) { + if (map.containsKey("#" + module + "#")) { if (MiscUtil.isNotEmpty(value)) { - if (FormBuildUtils.FONTFAMILY.contains(module) || - FormBuildUtils.HEADER_TEXT.contains(module) || - value.startsWith("#")) - map.put("#"+module+"#", value); + if (FormBuildUtils.FONTFAMILY.contains(module) || FormBuildUtils.HEADER_TEXT.contains(module) + || value.startsWith("#")) + map.put("#" + module + "#", value); else - map.put("#"+module+"#", "#"+value); - + map.put("#" + module + "#", "#" + value); + } else { - map.put("#"+module+"#", - FormBuildUtils.getDefaultMap().get("#"+module+"#")); + map.put("#" + module + "#", FormBuildUtils.getDefaultMap().get("#" + module + "#")); } } } @@ -705,12 +683,13 @@ ServletResponseAware { preview = LanguageHelper.getErrorString("error.bkuformpreview.notpossible"); } - - } catch (Exception e) { + + } + catch (Exception e) { log.warn("BKUSelection Preview can not be generated.", e); preview = LanguageHelper.getErrorString("error.bkuformpreview.notpossible"); - } + } } stream = new ByteArrayInputStream(preview.getBytes()); @@ -719,15 +698,14 @@ ServletResponseAware { } private String saveOAConfigToDatabase(OnlineApplication dboa, boolean newentry) { - + AuthComponentOA authoa = dboa.getAuthComponentOA(); - if (authoa == null) { + if (authoa == null) { authoa = new AuthComponentOA(); dboa.setAuthComponentOA(authoa); } - - if (authUser.isAdmin()) - dboa.setIsActive(generalOA.isActive()); + + if (authUser.isAdmin()) dboa.setIsActive(generalOA.isActive()); dboa.setFriendlyName(generalOA.getFriendlyName()); dboa.setCalculateHPI(generalOA.isCalculateHPI()); @@ -736,8 +714,7 @@ ServletResponseAware { if (authUser.isAdmin()) dboa.setKeyBoxIdentifier(MOAKeyBoxSelector.fromValue(generalOA.getKeyBoxIdentifier())); else { - if (newentry) - dboa.setKeyBoxIdentifier(MOAKeyBoxSelector.SECURE_SIGNATURE_KEYPAIR); + if (newentry) dboa.setKeyBoxIdentifier(MOAKeyBoxSelector.SECURE_SIGNATURE_KEYPAIR); } dboa.setPublicURLPrefix(generalOA.getIdentifier()); @@ -752,46 +729,37 @@ ServletResponseAware { num = at.gv.egovernment.moa.util.StringUtils.deleteLeadingZeros(num); - //num = StringUtils.leftPad(num, 7, '0'); + // num = StringUtils.leftPad(num, 7, '0'); } - if (num.startsWith(Constants.IDENIFICATIONTYPE_ZVR)) - num = num.substring(Constants.IDENIFICATIONTYPE_ZVR.length()); + if (num.startsWith(Constants.IDENIFICATIONTYPE_ZVR)) num = num.substring(Constants.IDENIFICATIONTYPE_ZVR.length()); - if (num.startsWith(Constants.IDENIFICATIONTYPE_ERSB)) - num = num.substring(Constants.IDENIFICATIONTYPE_ERSB.length()); + if (num.startsWith(Constants.IDENIFICATIONTYPE_ERSB)) num = num.substring(Constants.IDENIFICATIONTYPE_ERSB.length()); IdentificationNumber idnumber = new IdentificationNumber(); - idnumber.setValue( - Constants.PREFIX_WPBK + - generalOA.getIdentificationType() + - "+" + - num); + idnumber.setValue(Constants.PREFIX_WPBK + generalOA.getIdentificationType() + "+" + num); authoa.setIdentificationNumber(idnumber); - } - else { + } else { dboa.setType(null); if (authUser.isAdmin()) { - if (MiscUtil.isNotEmpty(generalOA.getTarget_admin()) && - generalOA.isAdminTarget() ) { + if (MiscUtil.isNotEmpty(generalOA.getTarget_admin()) && generalOA.isAdminTarget()) { dboa.setTarget(generalOA.getTarget_admin()); dboa.setTargetFriendlyName(generalOA.getTargetFriendlyName()); } else { String target = generalOA.getTarget(); - + if (MiscUtil.isNotEmpty(generalOA.getTarget_subsector()) && subTargetSet) dboa.setTarget(target + "-" + generalOA.getTarget_subsector()); else dboa.setTarget(target); String targetname = TargetValidator.getTargetFriendlyName(target); - if (MiscUtil.isNotEmpty(targetname)) - dboa.setTargetFriendlyName(targetname); + if (MiscUtil.isNotEmpty(targetname)) dboa.setTargetFriendlyName(targetname); } @@ -800,7 +768,7 @@ ServletResponseAware { if (MiscUtil.isNotEmpty(generalOA.getTarget())) { String target = generalOA.getTarget(); - + if (MiscUtil.isNotEmpty(generalOA.getTarget_subsector()) && subTargetSet) dboa.setTarget(target + "-" + generalOA.getTarget_subsector()); @@ -808,11 +776,10 @@ ServletResponseAware { dboa.setTarget(target); String targetname = TargetValidator.getTargetFriendlyName(target); - if (MiscUtil.isNotEmpty(targetname)) - dboa.setTargetFriendlyName(targetname); + if (MiscUtil.isNotEmpty(targetname)) dboa.setTargetFriendlyName(targetname); } - } + } } BKUURLS bkuruls = new BKUURLS(); @@ -822,7 +789,7 @@ ServletResponseAware { bkuruls.setLocalBKU(generalOA.getBkuLocalURL()); bkuruls.setOnlineBKU(generalOA.getBkuOnlineURL()); } - + TemplatesType templates = authoa.getTemplates(); if (templates == null) { templates = new TemplatesType(); @@ -849,15 +816,15 @@ ServletResponseAware { if (authUser.isAdmin()) { templates.setAditionalAuthBlockText(generalOA.getAditionalAuthBlockText()); - + List template = templates.getTemplate(); if (generalOA.isLegacy()) { - + if (template == null) template = new ArrayList(); else template.clear(); - + if (MiscUtil.isNotEmpty(generalOA.getSLTemplateURL1())) { TemplateType el = new TemplateType(); el.setURL(generalOA.getSLTemplateURL1()); @@ -875,10 +842,9 @@ ServletResponseAware { } } else { - if (template != null && template.size() > 0) - template.clear(); + if (template != null && template.size() > 0) template.clear(); } - + bkuselectioncustom.setBackGroundColor(parseColor(formOA.getBackGroundColor())); bkuselectioncustom.setFrontColor(parseColor(formOA.getFrontColor())); @@ -889,19 +855,19 @@ ServletResponseAware { bkuselectioncustom.setButtonBackGroundColor(parseColor(formOA.getButton_BackGroundColor())); bkuselectioncustom.setButtonBackGroundColorFocus(parseColor(formOA.getButton_BackGroundColorFocus())); bkuselectioncustom.setButtonFontColor(parseColor(formOA.getButton_FrontColor())); - + if (MiscUtil.isNotEmpty(formOA.getAppletRedirectTarget())) bkuselectioncustom.setAppletRedirectTarget(formOA.getAppletRedirectTarget()); - bkuselectioncustom.setFontType(formOA.getFontType()); - + bkuselectioncustom.setFontType(formOA.getFontType()); + } - - //set default transformation if it is empty + + // set default transformation if it is empty List transformsInfo = authoa.getTransformsInfo(); if (transformsInfo == null) { - //TODO: set OA specific transformation if it is required - + // TODO: set OA specific transformation if it is required + } OAPVP2 pvp2 = authoa.getOAPVP2(); @@ -913,17 +879,18 @@ ServletResponseAware { pvp2.setMetadataURL(pvp2OA.getMetaDataURL()); try { - if (pvp2OA.getFileUpload() != null) - pvp2.setCertificate(pvp2OA.getCertificate()); + if (pvp2OA.getFileUpload() != null) pvp2.setCertificate(pvp2OA.getCertificate()); - } catch (CertificateException e) { + } + catch (CertificateException e) { log.info("Uploaded Certificate can not be found", e); return LanguageHelper.getErrorString("validation.pvp2.certificate.notfound"); - } catch (IOException e) { + } + catch (IOException e) { log.info("Uploaded Certificate can not be parsed", e); return LanguageHelper.getErrorString("validation.pvp2.certificate.format"); } - + OASAML1 saml1 = authoa.getOASAML1(); if (saml1 == null) { saml1 = new OASAML1(); @@ -934,7 +901,7 @@ ServletResponseAware { if (authUser.isAdmin()) { saml1.setIsActive(saml1OA.isActive()); } - + if (saml1.isIsActive() != null && saml1.isIsActive()) { saml1.setProvideAUTHBlock(saml1OA.isProvideAuthBlock()); saml1.setProvideCertificate(saml1OA.isProvideCertificate()); @@ -943,8 +910,8 @@ ServletResponseAware { saml1.setProvideStammzahl(saml1OA.isProvideStammZahl()); saml1.setUseCondition(saml1OA.isUseCondition()); saml1.setConditionLength(BigInteger.valueOf(saml1OA.getConditionLength())); - //TODO: set sourceID - //saml1.setSourceID(""); + // TODO: set sourceID + // saml1.setSourceID(""); } OASSO sso = authoa.getOASSO(); @@ -955,42 +922,60 @@ ServletResponseAware { } sso.setUseSSO(ssoOA.isUseSSO()); - if (authUser.isAdmin()) - sso.setAuthDataFrame(ssoOA.isShowAuthDataFrame()); + if (authUser.isAdmin()) sso.setAuthDataFrame(ssoOA.isShowAuthDataFrame()); sso.setSingleLogOutURL(ssoOA.getSingleLogOutURL()); - STORK stork = authoa.getSTORK(); if (stork == null) { - //TODO: make stork configurable + // TODO: make stork configurable } - + + if (oauth20OA != null) { + log.debug("Saving OAuth 2.0 configuration:"); + OAOAUTH20 oaOAuth20 = authoa.getOAOAUTH20(); + if (oaOAuth20 == null) { + oaOAuth20 = new OAOAUTH20(); + authoa.setOAOAUTH20(oaOAuth20); + } + + oaOAuth20.setOAuthClientId(generalOA.getIdentifier()); + // oaOAuth20.setOAuthClientSecret(oauth20OA.getClientSecret()); + oaOAuth20.setOAuthRedirectUri(oauth20OA.getRedirectUri()); + log.debug("client id: " + oauth20OA.getClientId()); + log.debug("client secret: " + oauth20OA.getClientSecret()); + log.debug("redirect uri:" + oauth20OA.getRedirectUri()); + + oaOAuth20.setOAuthClientSecret((String) request.getSession().getAttribute(Constants.SESSION_OAUTH20SECRET)); + request.getSession().setAttribute(Constants.SESSION_OAUTH20SECRET, null); + + } + try { if (newentry) { ConfigurationDBUtils.save(dboa); - + if (!authUser.isAdmin()) { UserDatabase user = ConfigurationDBRead.getUserWithID(authUser.getUserID()); - + List useroas = user.getOnlineApplication(); - if (useroas == null) - useroas = new ArrayList(); + if (useroas == null) useroas = new ArrayList(); useroas.add(dboa); - ConfigurationDBUtils.saveOrUpdate(user); + ConfigurationDBUtils.saveOrUpdate(user); } } else ConfigurationDBUtils.saveOrUpdate(dboa); - } catch (MOADatabaseException e) { + } + catch (MOADatabaseException e) { log.warn("Online-Application can not be stored.", e); return LanguageHelper.getErrorString("error.db.oa.store"); } - + return null; } @@ -1009,9 +994,8 @@ ServletResponseAware { private void generateUserSpecificConfigurationOptions(UserDatabase userdb) { if (userdb.isIsMandateUser() != null && userdb.isIsMandateUser()) { - String bpk = userdb.getBpk(); - if (bpk.startsWith(Constants.IDENIFICATIONTYPE_BASEID_FN) || - bpk.startsWith(Constants.IDENIFICATIONTYPE_BASEID_ZVR)) { + String bpk = userdb.getBpk(); + if (bpk.startsWith(Constants.IDENIFICATIONTYPE_BASEID_FN) || bpk.startsWith(Constants.IDENIFICATIONTYPE_BASEID_ZVR)) { onlyBusinessService = true; generalOA.setBusinessService(true); @@ -1023,15 +1007,12 @@ ServletResponseAware { generalOA.setIdentificationType(split[1].substring(1)); if (bpk.startsWith(Constants.IDENIFICATIONTYPE_BASEID_FN)) - generalOA.setIdentificationNumber( - at.gv.egovernment.moa.util.StringUtils.deleteLeadingZeros(split[2])); + generalOA.setIdentificationNumber(at.gv.egovernment.moa.util.StringUtils.deleteLeadingZeros(split[2])); else generalOA.setIdentificationNumber(split[2]); } - - } public String setGeneralOAConfig() { @@ -1059,179 +1040,185 @@ ServletResponseAware { return Constants.STRUTS_SUCCESS; } - - //Getter and Setter + // Getter and Setter public void setServletResponse(HttpServletResponse arg0) { this.response = arg0; } - + public void setServletRequest(HttpServletRequest arg0) { this.request = arg0; } - + public HttpServletRequest getRequest() { return request; } - + public void setRequest(HttpServletRequest request) { this.request = request; } - + public HttpServletResponse getResponse() { return response; } - + public void setResponse(HttpServletResponse response) { this.response = response; } - + public OAGeneralConfig getGeneralOA() { return generalOA; } - + public void setGeneralOA(OAGeneralConfig generalOA) { this.generalOA = generalOA; } - + public OAPVP2Config getPvp2OA() { return pvp2OA; } - + public void setPvp2OA(OAPVP2Config pvp2oa) { pvp2OA = pvp2oa; } - + public OASAML1Config getSaml1OA() { return saml1OA; } - + public void setSaml1OA(OASAML1Config saml1oa) { saml1OA = saml1oa; } - + public OASSOConfig getSsoOA() { return ssoOA; } - + public void setSsoOA(OASSOConfig ssoOA) { this.ssoOA = ssoOA; } - + public OASTORKConfig getStorkOA() { return storkOA; } - + public void setStorkOA(OASTORKConfig storkOA) { this.storkOA = storkOA; } - + /** - * @param oaidobj the oaidobj to set + * @param oaidobj + * the oaidobj to set */ public void setOaidobj(String oaidobj) { this.oaidobj = oaidobj; } - + /** * @return the authUser */ public AuthenticatedUser getAuthUser() { return authUser; } - + /** * @return the newOA */ public boolean isNewOA() { return newOA; } - + /** - * @param newOA the newOA to set + * @param newOA + * the newOA to set */ public void setNewOA(boolean newOA) { this.newOA = newOA; } - + /** * @return the nextPage */ public String getNextPage() { return nextPage; } - + /** * @return the formID */ public String getFormID() { return formID; } - + /** - * @param formID the formID to set + * @param formID + * the formID to set */ public void setFormID(String formID) { this.formID = formID; } - + /** * @return the onlyBusinessService */ public boolean isOnlyBusinessService() { return onlyBusinessService; } - + /** - * @param onlyBusinessService the onlyBusinessService to set + * @param onlyBusinessService + * the onlyBusinessService to set */ public void setOnlyBusinessService(boolean onlyBusinessService) { this.onlyBusinessService = onlyBusinessService; } - + /** * @return the subTargetSet */ public boolean isSubTargetSet() { return subTargetSet; } - + /** - * @param subTargetSet the subTargetSet to set + * @param subTargetSet + * the subTargetSet to set */ public void setSubTargetSet(boolean subTargetSet) { this.subTargetSet = subTargetSet; } - + /** * @return the deaktivededBusinessService */ public boolean isDeaktivededBusinessService() { return deaktivededBusinessService; } - + /** - * @param deaktivededBusinessService the deaktivededBusinessService to set + * @param deaktivededBusinessService + * the deaktivededBusinessService to set */ public void setDeaktivededBusinessService(boolean deaktivededBusinessService) { this.deaktivededBusinessService = deaktivededBusinessService; } - + /** * @return the formOA */ public FormularCustomization getFormOA() { return formOA; } - + /** - * @param formOA the formOA to set + * @param formOA + * the formOA to set */ public void setFormOA(FormularCustomization formOA) { this.formOA = formOA; } - + /** * @return the stream */ @@ -1239,5 +1226,12 @@ ServletResponseAware { return stream; } + public OAOAuth20Config getOauth20OA() { + return oauth20OA; + } + + public void setOauth20OA(OAOAuth20Config oauth20OA) { + this.oauth20OA = oauth20OA; + } } diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/validation/oa/OAOAUTH20ConfigValidation.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/validation/oa/OAOAUTH20ConfigValidation.java new file mode 100644 index 000000000..867abafc3 --- /dev/null +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/validation/oa/OAOAUTH20ConfigValidation.java @@ -0,0 +1,33 @@ +package at.gv.egovernment.moa.id.configuration.validation.oa; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import at.gv.egovernment.moa.id.configuration.data.oa.OAOAuth20Config; +import at.gv.egovernment.moa.id.configuration.helper.LanguageHelper; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Util; + +public class OAOAUTH20ConfigValidation { + + private static final Logger log = Logger.getLogger(OAOAUTH20ConfigValidation.class); + + public List validate(OAOAuth20Config form) { + + List errors = new ArrayList(); + + // validate secret +// if (StringUtils.isEmpty(form.getClientSecret())) { +// errors.add(LanguageHelper.getErrorString("error.oa.oauth.clientSecret")); +// } + + // validate redirectUri + if (StringUtils.isNotEmpty(form.getRedirectUri()) && !OAuth20Util.isUrl(form.getRedirectUri())) { + errors.add(LanguageHelper.getErrorString("error.oa.oauth.redirecturi")); + } + + return errors; + } +} diff --git a/id/ConfigWebTool/src/main/resources/applicationResources.properties b/id/ConfigWebTool/src/main/resources/applicationResources.properties index cad135b95..456c37ff1 100644 --- a/id/ConfigWebTool/src/main/resources/applicationResources.properties +++ b/id/ConfigWebTool/src/main/resources/applicationResources.properties @@ -27,6 +27,10 @@ error.mail.send=An die angegebene Mailadresse konnte keine Nachticht versendet w error.mail.verification=Der Verifikationsvorgang wurde durch einen internen Fehler unterbrochen. Bitte Versuchen sie es noch einmal. error.editoa.mailverification=Die Verwaltung von Online-Applikationen ist vor\u00FCbergehend deaktiviert, da die Mailadresse des Benutzeraccounts noch nicht verifiziert wurde. error.bkuformpreview.notpossible="Die Vorschau konnte nicht generiert werden da ein interner Fehler auftreten ist." +error.oa.oauth.redirecturi=Redirect URL ist keine richtige URL +error.oa.oauth.clientSecret=Client-Secret darf nicht leer sein +error.oa.oauth.keyname=Key-Name darf nicht leer sein +error.oa.oauth.keystore=Keystore darf nicht leer sein und muss eine richtige URL sein. mail.userrequest.subject=Accountanforderung MOA-ID 2.x Konfigurationstool @@ -189,6 +193,9 @@ webpages.oaconfig.menu.saml1.show=SAML1 Konfiguration einblenden webpages.oaconfig.menu.saml1.hidden=SAML1 Konfiguration ausblenden webpages.oaconfig.menu.pvp2.show=PVP2 Konfiguration einblenden webpages.oaconfig.menu.pvp2.hidden=PVP2 Konfiguration ausblenden +webpages.oaconfig.menu.oauth20.show=OAuth 2.0 Konfiguration einblenden +webpages.oaconfig.menu.oauth20.hidden=OAuth 2.0 Konfiguration ausblenden + webpages.oaconfig.menu.stork=STORK Konfiguration @@ -230,6 +237,12 @@ webpages.oaconfig.pvp2.metaDataURL=URL zu den Metadaten webpages.oaconfig.pvp2.certifcate=Zertifikat hochladen webpages.oaconfig.pvp2.certifcate.info=Infos zum Zertifikat +webpages.oaconfig.protocols.oauth20.header=OAuth 2.0 Konfiguration +webpages.oaconfig.oauth20.clientId=Client ID +webpages.oaconfig.oauth20.clientSecret=Client Passwort +webpages.oaconfig.oauth20.redirectUri=Redirect Uri + + message.title=Meldung: webpages.oaconfig.success=Die Online-Applikation {0} konnte erfolgreich gespeichert werden. webpages.oaconfig.success.admin=Die Online-Applikation {0} konnte erfolgreich gespeichert werden. Es ist jedoch eine Aktivierung durch den Administrator erforderlich. diff --git a/id/ConfigWebTool/src/main/webapp/js/common.js b/id/ConfigWebTool/src/main/webapp/js/common.js index b94fd9ec2..ff9509895 100644 --- a/id/ConfigWebTool/src/main/webapp/js/common.js +++ b/id/ConfigWebTool/src/main/webapp/js/common.js @@ -44,6 +44,17 @@ function oaPVP2(){ $('#button_pvp2_hidden').css('display', "block"); } } +function oaOAuth20(){ + if ($('#oa_oauth20_area').css('display') == "block") { + $('#oa_oauth20_area').css('display', "none"); + $('#button_oauth20_show').css('display', "block"); + $('#button_oauth20_hidden').css('display', "none"); + } else { + $('#oa_oauth20_area').css('display', "block"); + $('#button_oauth20_show').css('display', "none"); + $('#button_oauth20_hidden').css('display', "block"); + } +} function oaFormCustom() { if ($('#formcustom_area').css('display') == "block") { $('#formcustom_area').css('display', "none"); @@ -141,6 +152,7 @@ function updateBKUFormPreview(module) { $("#formCustomPreview>iframe").attr("src", "./bkuFramePreview.action?module="+module+"&value="+encodeURIComponent(value.replace("#",""))); } + function userOnLoad() { UseUserNamePassword(); return true; diff --git a/id/ConfigWebTool/src/main/webapp/jsp/editOAGeneral.jsp b/id/ConfigWebTool/src/main/webapp/jsp/editOAGeneral.jsp index e8bb346a6..0341fc49b 100644 --- a/id/ConfigWebTool/src/main/webapp/jsp/editOAGeneral.jsp +++ b/id/ConfigWebTool/src/main/webapp/jsp/editOAGeneral.jsp @@ -1,7 +1,7 @@ <%@ page contentType="text/html;charset=UTF-8" %> <%@page import="at.gv.egovernment.moa.id.configuration.helper.LanguageHelper"%> <%@ taglib prefix="s" uri="/struts-tags" %> - + @@ -13,7 +13,6 @@ - @@ -272,7 +271,7 @@
-

<%=LanguageHelper.getGUIString("webpages.oaconfig.sso.header", request) %>

+

<%=LanguageHelper.getGUIString("webpages.oaconfig.sso.header", request) %>

<%=LanguageHelper.getGUIString("webpages.oaconfig.menu.pvp2.hidden", request) %> + + +

<%=LanguageHelper.getGUIString("webpages.oaconfig.protocols.saml1.header", request) %>

@@ -398,6 +404,20 @@
+ +
+

<%=LanguageHelper.getGUIString("webpages.oaconfig.protocols.oauth20.header", request) %>

+ + + + + + + +
@@ -480,7 +500,7 @@ id="HEADER_TEXT"> - <%-- /dispatcher?mod=id_pvp2x&action=Soap + + ^/oauth2/auth\\?(.*)$ + /dispatcher?mod=id_oauth20&action=AUTH&%{query-string} + + + ^/oauth2/token\\?(.*)$ + /dispatcher?mod=id_oauth20&action=TOKEN&%{query-string} + + + The outbound-rule specifies that when response.encodeURL is called (if diff --git a/id/server/idserverlib/pom.xml b/id/server/idserverlib/pom.xml index ab1a28091..3cc7c38de 100644 --- a/id/server/idserverlib/pom.xml +++ b/id/server/idserverlib/pom.xml @@ -1,4 +1,5 @@ - + MOA.id moa-id @@ -16,30 +17,30 @@ - - shibboleth.internet2.edu - Internet2 - https://build.shibboleth.net/nexus/content/groups/public/ - + + shibboleth.internet2.edu + Internet2 + https://build.shibboleth.net/nexus/content/groups/public/ + - + - - MOA.id - stork-saml-engine - 1.5.2 - - - MOA.id.server - moa-id-commons - ${pom.version} - + + MOA.id + stork-saml-engine + 1.5.2 + + + MOA.id.server + moa-id-commons + ${pom.version} + MOA moa-common jar - + MOA moa-common test-jar @@ -96,10 +97,10 @@ commons-fileupload commons-fileupload - - commons-httpclient - commons-httpclient - + + commons-httpclient + commons-httpclient + dav4j dav4j @@ -129,11 +130,8 @@ iaik.prod iaik_X509TrustManager - + edu.internet2.middleware shibboleth-common @@ -149,37 +147,69 @@ regexp regexp - - + + + + commons-lang + commons-lang + 2.6 + + + + + + com.googlecode.jsontoken + jsontoken + 1.0 + + - commons-lang - commons-lang - 2.6 - + commons-codec + commons-codec + 1.8 + + + + + com.google.http-client + google-http-client-jackson2 + 1.17.0-rc + test + + + com.google.oauth-client + google-oauth-client-jetty + 1.17.0-rc + test + + + + + org.testng + testng + 6.1.1 + test + + - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + - + org.apache.maven.plugins maven-jar-plugin - true + true false diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java index 3bc152ec8..e4bf37417 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java @@ -36,7 +36,8 @@ public class StartAuthenticationBuilder { Logger.info("Starting authentication for a citizen of country: " + (StringUtils.isEmpty(moasession.getCcc()) ? "AT" : moasession.getCcc())); // STORK or normal authentication - if (storkConfig.isSTORKAuthentication(moasession.getCcc())) { + //TODO: commented because npe was thrown + /*if (storkConfig.isSTORKAuthentication(moasession.getCcc())) { //STORK authentication Logger.trace("Found C-PEPS configuration for citizen of country: " + moasession.getCcc()); Logger.debug("Starting STORK authentication"); @@ -44,13 +45,13 @@ public class StartAuthenticationBuilder { AuthenticationServer.startSTORKAuthentication(req, resp, moasession); return ""; - } else { + } else {*/ //normal MOA-ID authentication Logger.debug("Starting normal MOA-ID authentication"); String getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(moasession, req); return getIdentityLinkForm; - } + //} } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java index 9eaa13f04..1061a2802 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java @@ -1,24 +1,15 @@ /* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. + * Copyright 2003 Federal Chancellery Austria MOA-ID has been developed in a cooperation between + * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. This product combines work with different licenses. See the "NOTICE" text file for + * details on the various modules and licenses. The "NOTICE" text file is part of the distribution. + * Any derivative works that you distribute must include a readable copy of the "NOTICE" text file. */ package at.gv.egovernment.moa.id.auth.data; @@ -37,6 +28,7 @@ import org.w3c.dom.Element; import at.gv.egovernment.moa.id.auth.validator.InfoboxValidator; import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20SessionObject; import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; @@ -44,43 +36,40 @@ import at.gv.egovernment.moa.util.DOMUtils; import eu.stork.mw.messages.saml.STORKAuthnRequest; /** - * Session data to be stored between AuthenticationServer API - * calls. + * Session data to be stored between AuthenticationServer API calls. * * @author Paul Ivancsics * @version $Id$ */ public class AuthenticationSession implements Serializable { - + /** * */ private static final long serialVersionUID = 1L; public static final String TARGET_PREFIX_ = Constants.URN_PREFIX_CDID + "+"; - public static final String REGISTERANDORDNR_PREFIX_ = Constants.URN_PREFIX_WBPK - + "+"; - + public static final String REGISTERANDORDNR_PREFIX_ = Constants.URN_PREFIX_WBPK + "+"; + /** * session ID */ private String sessionID; /** - * "Geschäftsbereich" the online application belongs to; maybe - * null if the online application is a business application + * "Geschäftsbereich" the online application belongs to; maybe null if the + * online application is a business application */ private String target; /** - * Friendly name for the target, if target is configured via MOA-ID - * configuration + * Friendly name for the target, if target is configured via MOA-ID configuration */ private String targetFriendlyName; - + /** * SourceID */ private String sourceID; - + /** * public online application URL requested */ @@ -97,28 +86,25 @@ public class AuthenticationSession implements Serializable { * HTML template URL */ private String templateURL; - + /** * URL of the BKU */ private String bkuURL; - + /** - * Indicates whether the corresponding online application is a business - * service or not + * Indicates whether the corresponding online application is a business service or not */ private boolean businessService; - //Store Mandate + // Store Mandate /** * Use mandate */ private boolean useMandate; - private boolean isOW = false; - /** * STORK */ @@ -126,33 +112,32 @@ public class AuthenticationSession implements Serializable { /** * - * Mandate element + * Mandate element */ private MISMandate mandate; /** - * Reference value for mandate - * bussiness service for the assertion + * Reference value for mandate bussiness service for the assertion */ private String mandateReferenceValue; - + /** * SessionID for MIS */ private String misSessionID; - //store Identitylink + // store Identitylink /** * identity link read from smartcard */ private IdentityLink identityLink; - -// /** -// * timestamp logging when identity link has been received -// */ -// private Date timestampIdentityLink; - //store Authblock + // /** + // * timestamp logging when identity link has been received + // */ + // private Date timestampIdentityLink; + + // store Authblock /** * authentication block to be signed by the user */ @@ -164,61 +149,56 @@ public class AuthenticationSession implements Serializable { * The issuing time of the AUTH-Block SAML assertion. */ private String issueInstant; - - //Signer certificate + + // Signer certificate /** * Signer certificate of the foreign citizen or for mandate mode */ - //private X509Certificate signerCertificate; + // private X509Certificate signerCertificate; private byte[] signerCertificate; - /** - * SAML attributes from an extended infobox validation to be appended to the - * SAML assertion delivered to the final online application. + * SAML attributes from an extended infobox validation to be appended to the SAML assertion + * delivered to the final online application. */ private List extendedSAMLAttributesOA; - + /** - * The boolean value for either a target or a wbPK is provided as SAML - * Attribute in the SAML Assertion or not. + * The boolean value for either a target or a wbPK is provided as SAML Attribute in the SAML + * Assertion or not. */ private boolean samlAttributeGebeORwbpk; - + /** - * SAML attributes from an extended infobox validation to be appended to the - * SAML assertion of the AUTHBlock. + * SAML attributes from an extended infobox validation to be appended to the SAML assertion of + * the AUTHBlock. */ private List extendedSAMLAttributesAUTH; - + /** - * If infobox validators are needed after signing, they can be stored in - * this list. + * If infobox validators are needed after signing, they can be stored in this list. */ private List infoboxValidators; - + /** - * The register and number in the register parameter in case of a business - * service application. + * The register and number in the register parameter in case of a business service application. */ private String domainIdentifier; - + /** - * This string contains all identifiers of infoboxes, the online application - * is configured to accept. The infobox identifiers are comma separated. + * This string contains all identifiers of infoboxes, the online application is configured to + * accept. The infobox identifiers are comma separated. */ private String pushInfobox; - + /** * The STORK AuthRequest to be sent to the C-PEPS */ private STORKAuthnRequest storkAuthnRequest; + // private AuthenticationData authData; - - //private AuthenticationData authData; - - //protocol selection + // protocol selection private String action; private String modul; @@ -227,82 +207,83 @@ public class AuthenticationSession implements Serializable { private boolean ssoRequested = false; -// /** -// * Indicates if target from configuration is used or not -// */ -// private boolean useTargetFromConfig; - -// /** -// * Authentication data for the assertion -// */ -// private AuthenticationData assertionAuthData; -// -// /** -// * Persondata for the assertion -// */ -// private String assertionPrPerson; -// -// /** -// * Authblock for the assertion -// */ -// private String assertionAuthBlock; -// -// /** -// * Identitylink assertion for the (MOA) assertion -// */ -// private String assertionIlAssertion; -// -// /** -// * Signer certificate (base64 encoded) for the assertion -// */ -// private String assertionSignerCertificateBase64; -// -// /** -// * bussiness service for the assertion -// */ -// boolean assertionBusinessService; -// -// /** -// * timestamp logging when authentication session has been created -// */ -// private Date timestampStart; -// private CreateXMLSignatureResponse XMLCreateSignatureResponse; + private OAuth20SessionObject oAuth20SessionObject; + + // /** + // * Indicates if target from configuration is used or not + // */ + // private boolean useTargetFromConfig; + + // /** + // * Authentication data for the assertion + // */ + // private AuthenticationData assertionAuthData; + // + // /** + // * Persondata for the assertion + // */ + // private String assertionPrPerson; + // + // /** + // * Authblock for the assertion + // */ + // private String assertionAuthBlock; + // + // /** + // * Identitylink assertion for the (MOA) assertion + // */ + // private String assertionIlAssertion; + // + // /** + // * Signer certificate (base64 encoded) for the assertion + // */ + // private String assertionSignerCertificateBase64; + // + // /** + // * bussiness service for the assertion + // */ + // boolean assertionBusinessService; + // + // /** + // * timestamp logging when authentication session has been created + // */ + // private Date timestampStart; + // private CreateXMLSignatureResponse XMLCreateSignatureResponse; private VerifyXMLSignatureResponse XMLVerifySignatureResponse; private boolean isForeigner; -// private String requestedProtocolURL = null; - + // private String requestedProtocolURL = null; + public String getModul() { return modul; } - + public void setModul(String modul) { this.modul = modul; } - + public String getAction() { return action; } - + public void setAction(String action) { this.action = action; } - -// public AuthenticationData getAuthData() { -// return authData; -// } -// -// public void setAuthData(AuthenticationData authData) { -// this.authData = authData; -// } - - + + // public AuthenticationData getAuthData() { + // return authData; + // } + // + // public void setAuthData(AuthenticationData authData) { + // this.authData = authData; + // } + public boolean isAuthenticatedUsed() { return authenticatedUsed; } - + public void setAuthenticatedUsed(boolean authenticatedUsed) { this.authenticatedUsed = authenticatedUsed; } @@ -314,16 +295,15 @@ public class AuthenticationSession implements Serializable { public void setAuthenticated(boolean authenticated) { this.authenticated = authenticated; } - - -// public String getRequestedProtocolURL() { -// return requestedProtocolURL; -// } -// -// public void setRequestedProtocolURL(String requestedProtocolURL) { -// this.requestedProtocolURL = requestedProtocolURL; -// } - + + // public String getRequestedProtocolURL() { + // return requestedProtocolURL; + // } + // + // public void setRequestedProtocolURL(String requestedProtocolURL) { + // this.requestedProtocolURL = requestedProtocolURL; + // } + /** * Constructor for AuthenticationSession. * @@ -332,14 +312,15 @@ public class AuthenticationSession implements Serializable { */ public AuthenticationSession(String id) { sessionID = id; -// setTimestampStart(); + // setTimestampStart(); infoboxValidators = new ArrayList(); } - - public X509Certificate getSignerCertificate(){ + + public X509Certificate getSignerCertificate() { try { return new X509Certificate(signerCertificate); - } catch (CertificateException e) { + } + catch (CertificateException e) { Logger.warn("Signer certificate can not be loaded from session database!", e); return null; } @@ -348,15 +329,16 @@ public class AuthenticationSession implements Serializable { public byte[] getEncodedSignerCertificate() { return this.signerCertificate; } - + public void setSignerCertificate(X509Certificate signerCertificate) { try { this.signerCertificate = signerCertificate.getEncoded(); - } catch (CertificateEncodingException e) { + } + catch (CertificateEncodingException e) { Logger.warn("Signer certificate can not be stored to session database!", e); } } - + /** * Returns the identityLink. * @@ -365,7 +347,7 @@ public class AuthenticationSession implements Serializable { public IdentityLink getIdentityLink() { return identityLink; } - + /** * Returns the sessionID. * @@ -374,7 +356,7 @@ public class AuthenticationSession implements Serializable { public String getSessionID() { return sessionID; } - + /** * Sets the identityLink. * @@ -384,7 +366,7 @@ public class AuthenticationSession implements Serializable { public void setIdentityLink(IdentityLink identityLink) { this.identityLink = identityLink; } - + /** * Sets the sessionID. * @@ -394,7 +376,7 @@ public class AuthenticationSession implements Serializable { public void setSessionID(String sessionId) { this.sessionID = sessionId; } - + /** * Returns the oaURLRequested. * @@ -403,7 +385,7 @@ public class AuthenticationSession implements Serializable { public String getOAURLRequested() { return oaURLRequested; } - + /** * Returns the oaURLRequested. * @@ -412,7 +394,7 @@ public class AuthenticationSession implements Serializable { public String getPublicOAURLPrefix() { return oaPublicURLPrefix; } - + /** * Returns the BKU URL. * @@ -421,7 +403,7 @@ public class AuthenticationSession implements Serializable { public String getBkuURL() { return bkuURL; } - + /** * Returns the target. * @@ -430,7 +412,7 @@ public class AuthenticationSession implements Serializable { public String getTarget() { return target; } - + /** * Returns the sourceID. * @@ -439,7 +421,7 @@ public class AuthenticationSession implements Serializable { public String getSourceID() { return sourceID; } - + /** * Returns the target friendly name. * @@ -448,7 +430,7 @@ public class AuthenticationSession implements Serializable { public String getTargetFriendlyName() { return targetFriendlyName; } - + /** * Sets the oaURLRequested. * @@ -458,7 +440,7 @@ public class AuthenticationSession implements Serializable { public void setOAURLRequested(String oaURLRequested) { this.oaURLRequested = oaURLRequested; } - + /** * Sets the oaPublicURLPrefix * @@ -468,7 +450,7 @@ public class AuthenticationSession implements Serializable { public void setPublicOAURLPrefix(String oaPublicURLPrefix) { this.oaPublicURLPrefix = oaPublicURLPrefix; } - + /** * Sets the bkuURL * @@ -478,10 +460,9 @@ public class AuthenticationSession implements Serializable { public void setBkuURL(String bkuURL) { this.bkuURL = bkuURL; } - + /** - * Sets the target. If the target includes the target prefix, the prefix - * will be stripped off. + * Sets the target. If the target includes the target prefix, the prefix will be stripped off. * * @param target * The target to set @@ -491,13 +472,12 @@ public class AuthenticationSession implements Serializable { // If target starts with prefix "urn:publicid:gv.at:cdid+"; remove // prefix this.target = target.substring(TARGET_PREFIX_.length()); - Logger.debug("Target prefix stripped off; resulting target: " - + this.target); + Logger.debug("Target prefix stripped off; resulting target: " + this.target); } else { this.target = target; } } - + /** * Sets the sourceID * @@ -507,10 +487,9 @@ public class AuthenticationSession implements Serializable { public void setSourceID(String sourceID) { this.sourceID = sourceID; } - + /** - * Sets the target. If the target includes the target prefix, the prefix - * will be stripped off. + * Sets the target. If the target includes the target prefix, the prefix will be stripped off. * * @param target * The target to set @@ -518,7 +497,7 @@ public class AuthenticationSession implements Serializable { public void setTargetFriendlyName(String targetFriendlyName) { this.targetFriendlyName = targetFriendlyName; } - + /** * Returns the authURL. * @@ -527,7 +506,7 @@ public class AuthenticationSession implements Serializable { public String getAuthURL() { return authURL; } - + /** * Sets the authURL. * @@ -537,7 +516,7 @@ public class AuthenticationSession implements Serializable { public void setAuthURL(String authURL) { this.authURL = authURL; } - + /** * Returns the authBlock. * @@ -546,7 +525,7 @@ public class AuthenticationSession implements Serializable { public String getAuthBlock() { return authBlock; } - + /** * Sets the authBlock. * @@ -556,17 +535,17 @@ public class AuthenticationSession implements Serializable { public void setAuthBlock(String authBlock) { this.authBlock = authBlock; } - + /** * Returns the businessService. * - * @return true if the corresponding online application is a - * business application, otherwise false + * @return true if the corresponding online application is a business application, + * otherwise false */ public boolean getBusinessService() { return businessService; } - + /** * Sets the businessService variable. * @@ -576,15 +555,14 @@ public class AuthenticationSession implements Serializable { public void setBusinessService(boolean businessService) { this.businessService = businessService; } - - + /** * @return template URL */ public String getTemplateURL() { return templateURL; } - + /** * @param string * the template URL @@ -592,21 +570,18 @@ public class AuthenticationSession implements Serializable { public void setTemplateURL(String string) { templateURL = string; } - + /** - * Returns the SAML Attributes to be appended to the AUTHBlock. Maybe - * null. + * Returns the SAML Attributes to be appended to the AUTHBlock. Maybe null. * - * @return The SAML Attributes to be appended to the AUTHBlock. Maybe - * null. + * @return The SAML Attributes to be appended to the AUTHBlock. Maybe null. */ public List getExtendedSAMLAttributesAUTH() { - if (extendedSAMLAttributesAUTH == null) - extendedSAMLAttributesAUTH = new ArrayList(); + if (extendedSAMLAttributesAUTH == null) extendedSAMLAttributesAUTH = new ArrayList(); return extendedSAMLAttributesAUTH; } - + /** * Sets the SAML Attributes to be appended to the AUTHBlock. * @@ -616,53 +591,53 @@ public class AuthenticationSession implements Serializable { public void setExtendedSAMLAttributesAUTH(List extendedSAMLAttributesAUTH) { this.extendedSAMLAttributesAUTH = extendedSAMLAttributesAUTH; } - + /** - * Returns the SAML Attributes to be appended to the SAML assertion - * delivered to the online application. Maybe null. + * Returns the SAML Attributes to be appended to the SAML assertion delivered to the online + * application. Maybe null. * - * @return The SAML Attributes to be appended to the SAML assertion - * delivered to the online application + * @return The SAML Attributes to be appended to the SAML assertion delivered to the online + * application */ public List getExtendedSAMLAttributesOA() { return extendedSAMLAttributesOA; } - + /** - * Sets the SAML Attributes to be appended to the SAML assertion delivered - * to the online application. + * Sets the SAML Attributes to be appended to the SAML assertion delivered to the online + * application. * * @param extendedSAMLAttributesOA - * The SAML Attributes to be appended to the SAML assertion - * delivered to the online application. + * The SAML Attributes to be appended to the SAML assertion delivered to the online + * application. */ public void setExtendedSAMLAttributesOA(List extendedSAMLAttributesOA) { this.extendedSAMLAttributesOA = extendedSAMLAttributesOA; } - + /** - * Returns the boolean value for either a target or a wbPK is provided as - * SAML Attribute in the SAML Assertion or not. + * Returns the boolean value for either a target or a wbPK is provided as SAML Attribute in the + * SAML Assertion or not. * - * @return true either a target or a wbPK is provided as SAML Attribute in - * the SAML Assertion or false if not. + * @return true either a target or a wbPK is provided as SAML Attribute in the SAML Assertion or + * false if not. */ public boolean getSAMLAttributeGebeORwbpk() { return this.samlAttributeGebeORwbpk; } - + /** - * Sets the boolean value for either a target or a wbPK is provided as SAML - * Attribute in the SAML Assertion or not. + * Sets the boolean value for either a target or a wbPK is provided as SAML Attribute in the + * SAML Assertion or not. * * @param samlAttributeGebeORwbpk - * The boolean for value either a target or wbPK is provided as - * SAML Attribute in the SAML Assertion or not. + * The boolean for value either a target or wbPK is provided as SAML Attribute in the + * SAML Assertion or not. */ public void setSAMLAttributeGebeORwbpk(boolean samlAttributeGebeORwbpk) { this.samlAttributeGebeORwbpk = samlAttributeGebeORwbpk; } - + /** * Returns the issuing time of the AUTH-Block SAML assertion. * @@ -671,7 +646,7 @@ public class AuthenticationSession implements Serializable { public String getIssueInstant() { return issueInstant; } - + /** * Sets the issuing time of the AUTH-Block SAML assertion. * @@ -681,40 +656,39 @@ public class AuthenticationSession implements Serializable { public void setIssueInstant(String issueInstant) { this.issueInstant = issueInstant; } - + /** * Returns the iterator to the stored infobox validators. * * @return Iterator */ public Iterator getInfoboxValidatorIterator() { - if (infoboxValidators == null) - return null; + if (infoboxValidators == null) return null; return infoboxValidators.iterator(); } - -// /** -// * Adds an infobox validator class to the stored infobox validators. -// * -// * @param infoboxIdentifier -// * the identifier of the infobox the validator belongs to -// * @param infoboxFriendlyName -// * the friendly name of the infobox -// * @param infoboxValidator -// * the infobox validator to add -// */ -// public Iterator addInfoboxValidator(String infoboxIdentifier, -// String infoboxFriendlyName, InfoboxValidator infoboxValidator) { -// if (infoboxValidators == null) -// infoboxValidators = new ArrayList(); -// Vector v = new Vector(3); -// v.add(infoboxIdentifier); -// v.add(infoboxFriendlyName); -// v.add(infoboxValidator); -// infoboxValidators.add(v); -// return infoboxValidators.iterator(); -// } - + + // /** + // * Adds an infobox validator class to the stored infobox validators. + // * + // * @param infoboxIdentifier + // * the identifier of the infobox the validator belongs to + // * @param infoboxFriendlyName + // * the friendly name of the infobox + // * @param infoboxValidator + // * the infobox validator to add + // */ + // public Iterator addInfoboxValidator(String infoboxIdentifier, + // String infoboxFriendlyName, InfoboxValidator infoboxValidator) { + // if (infoboxValidators == null) + // infoboxValidators = new ArrayList(); + // Vector v = new Vector(3); + // v.add(infoboxIdentifier); + // v.add(infoboxFriendlyName); + // v.add(infoboxValidator); + // infoboxValidators.add(v); + // return infoboxValidators.iterator(); + // } + /** * Tests for pending input events of the infobox validators. * @@ -726,100 +700,94 @@ public class AuthenticationSession implements Serializable { if (iter != null) { while (!result && iter.hasNext()) { Vector infoboxValidatorVector = (Vector) iter.next(); - InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector - .get(2); - if (!ParepUtils.isEmpty(infoboxvalidator.getForm())) - result = true; + InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector.get(2); + if (!ParepUtils.isEmpty(infoboxvalidator.getForm())) result = true; } } return result; } - -// /** -// * Returns the first pending infobox validator. -// * -// * @return the infobox validator class -// */ -// public InfoboxValidator getFirstPendingValidator() { -// Iterator iter = getInfoboxValidatorIterator(); -// if (iter != null) { -// while (iter.hasNext()) { -// Vector infoboxValidatorVector = (Vector) iter.next(); -// InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector -// .get(2); -// String form = infoboxvalidator.getForm(); -// if (!ParepUtils.isEmpty(form)) -// return infoboxvalidator; -// } -// } -// return null; -// } - -// /** -// * Returns the input form of the first pending infobox validator input -// * processor. -// * -// * @return the form to show -// */ -// public String getFirstValidatorInputForm() { -// Iterator iter = getInfoboxValidatorIterator(); -// if (iter != null) { -// while (iter.hasNext()) { -// Vector infoboxValidatorVector = (Vector) iter.next(); -// InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector -// .get(2); -// String form = infoboxvalidator.getForm(); -// if (!ParepUtils.isEmpty(form)) -// return form; -// } -// } -// return null; -// } - - /** - * Returns domain identifier (the register and number in the register - * parameter). null in the case of not a business service. + + // /** + // * Returns the first pending infobox validator. + // * + // * @return the infobox validator class + // */ + // public InfoboxValidator getFirstPendingValidator() { + // Iterator iter = getInfoboxValidatorIterator(); + // if (iter != null) { + // while (iter.hasNext()) { + // Vector infoboxValidatorVector = (Vector) iter.next(); + // InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector + // .get(2); + // String form = infoboxvalidator.getForm(); + // if (!ParepUtils.isEmpty(form)) + // return infoboxvalidator; + // } + // } + // return null; + // } + + // /** + // * Returns the input form of the first pending infobox validator input + // * processor. + // * + // * @return the form to show + // */ + // public String getFirstValidatorInputForm() { + // Iterator iter = getInfoboxValidatorIterator(); + // if (iter != null) { + // while (iter.hasNext()) { + // Vector infoboxValidatorVector = (Vector) iter.next(); + // InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector + // .get(2); + // String form = infoboxvalidator.getForm(); + // if (!ParepUtils.isEmpty(form)) + // return form; + // } + // } + // return null; + // } + + /** + * Returns domain identifier (the register and number in the register parameter). + * null in the case of not a business service. * * @return the domainIdentifier */ public String getDomainIdentifier() { return domainIdentifier; } - + /** - * Sets the register and number in the register parameter if the application - * is a business service. If the domain identifier includes the - * registerAndOrdNr prefix, the prefix will be stripped off. + * Sets the register and number in the register parameter if the application is a business + * service. If the domain identifier includes the registerAndOrdNr prefix, the prefix will be + * stripped off. * * @param domainIdentifier * the domain identifier to set */ public void setDomainIdentifier(String domainIdentifier) { - if (domainIdentifier != null - && domainIdentifier.startsWith(REGISTERANDORDNR_PREFIX_)) { + if (domainIdentifier != null && domainIdentifier.startsWith(REGISTERANDORDNR_PREFIX_)) { // If domainIdentifier starts with prefix // "urn:publicid:gv.at:wbpk+"; remove this prefix - this.domainIdentifier = domainIdentifier - .substring(REGISTERANDORDNR_PREFIX_.length()); - Logger.debug("Register and ordernumber prefix stripped off; resulting register string: " - + this.domainIdentifier); + this.domainIdentifier = domainIdentifier.substring(REGISTERANDORDNR_PREFIX_.length()); + Logger.debug("Register and ordernumber prefix stripped off; resulting register string: " + this.domainIdentifier); } else { this.domainIdentifier = domainIdentifier; } } - + /** - * Gets all identifiers of infoboxes, the online application is configured - * to accept. The infobox identifiers are comma separated. + * Gets all identifiers of infoboxes, the online application is configured to accept. The + * infobox identifiers are comma separated. * * @return the string containing infobox identifiers */ public String getPushInfobox() { - if (pushInfobox == null) - return ""; + if (pushInfobox == null) return ""; return pushInfobox; } - + /** * @param pushInfobox * the infobox identifiers to set (comma separated) @@ -827,7 +795,7 @@ public class AuthenticationSession implements Serializable { public void setPushInfobox(String pushInfobox) { this.pushInfobox = pushInfobox; } - + /** * * @param useMandate @@ -838,9 +806,9 @@ public class AuthenticationSession implements Serializable { this.useMandate = true; else this.useMandate = false; - + } - + /** * Returns if mandate is used or not * @@ -849,7 +817,7 @@ public class AuthenticationSession implements Serializable { public boolean getUseMandate() { return this.useMandate; } - + /** * * @param misSessionID @@ -858,7 +826,7 @@ public class AuthenticationSession implements Serializable { public void setMISSessionID(String misSessionID) { this.misSessionID = misSessionID; } - + /** * Returns the MIS session ID * @@ -867,14 +835,14 @@ public class AuthenticationSession implements Serializable { public String getMISSessionID() { return this.misSessionID; } - + /** * @return the mandateReferenceValue */ public String getMandateReferenceValue() { return mandateReferenceValue; } - + /** * @param mandateReferenceValue * the mandateReferenceValue to set @@ -882,7 +850,7 @@ public class AuthenticationSession implements Serializable { public void setMandateReferenceValue(String mandateReferenceValue) { this.mandateReferenceValue = mandateReferenceValue; } - + /** * Gets the STORK SAML AuthnRequest * @@ -891,7 +859,7 @@ public class AuthenticationSession implements Serializable { public STORKAuthnRequest getStorkAuthnRequest() { return storkAuthnRequest; } - + /** * Sets the STORK SAML AuthnRequest * @@ -901,11 +869,11 @@ public class AuthenticationSession implements Serializable { public void setStorkAuthnRequest(STORKAuthnRequest storkAuthnRequest) { this.storkAuthnRequest = storkAuthnRequest; } - + public String getCcc() { return ccc; } - + public void setCcc(String ccc) { this.ccc = ccc; } @@ -913,23 +881,23 @@ public class AuthenticationSession implements Serializable { public boolean isForeigner() { return isForeigner; } - + public void setForeigner(boolean isForeigner) { this.isForeigner = isForeigner; } - + public VerifyXMLSignatureResponse getXMLVerifySignatureResponse() { return XMLVerifySignatureResponse; } - + public void setXMLVerifySignatureResponse(VerifyXMLSignatureResponse xMLVerifySignatureResponse) { XMLVerifySignatureResponse = xMLVerifySignatureResponse; } - + public MISMandate getMISMandate() { return mandate; } - + public void setMISMandate(MISMandate mandate) { this.mandate = mandate; } @@ -938,60 +906,75 @@ public class AuthenticationSession implements Serializable { try { byte[] byteMandate = mandate.getMandate(); String stringMandate = new String(byteMandate); - return DOMUtils.parseDocument(stringMandate, false, - null, null).getDocumentElement(); + return DOMUtils.parseDocument(stringMandate, false, null, null).getDocumentElement(); - }catch (Throwable e) { + } + catch (Throwable e) { Logger.warn("Mandate content could not be generated from MISMandate."); return null; - } + } } - + /** * @return the ssoRequested */ - //TODO: SSO only allowed without mandates, actually!!!!!! + // TODO: SSO only allowed without mandates, actually!!!!!! public boolean isSsoRequested() { return ssoRequested && !useMandate; } - + /** - * @param ssoRequested the ssoRequested to set + * @param ssoRequested + * the ssoRequested to set */ public void setSsoRequested(boolean ssoRequested) { this.ssoRequested = ssoRequested; } - + /** * @return the isOW */ public boolean isOW() { return isOW; } - + /** - * @param isOW the isOW to set + * @param isOW + * the isOW to set */ public void setOW(boolean isOW) { this.isOW = isOW; } - + /** * @return the authBlockTokken */ public String getAuthBlockTokken() { return authBlockTokken; } - + /** - * @param authBlockTokken the authBlockTokken to set + * @param authBlockTokken + * the authBlockTokken to set */ public void setAuthBlockTokken(String authBlockTokken) { this.authBlockTokken = authBlockTokken; } + /** + * @return the oAuth20SessionObject + */ + public OAuth20SessionObject getoAuth20SessionObject() { + return oAuth20SessionObject; + } - + /** + * @param oAuth20SessionObject + * the oAuth20SessionObject to set + */ + public void setoAuth20SessionObject(OAuth20SessionObject oAuth20SessionObject) { + this.oAuth20SessionObject = oAuth20SessionObject; + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/OAParameter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/OAParameter.java index 7d76ce9d5..e5cf14d50 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/OAParameter.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/OAParameter.java @@ -1,40 +1,30 @@ /* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. + * Copyright 2003 Federal Chancellery Austria MOA-ID has been developed in a cooperation between + * BRZ, the Federal Chancellery Austria - ICT staff unit, and Graz University of Technology. + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: http://www.osor.eu/eupl/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. This product combines work with different licenses. See the "NOTICE" text file for + * details on the various modules and licenses. The "NOTICE" text file is part of the distribution. + * Any derivative works that you distribute must include a readable copy of the "NOTICE" text file. */ - package at.gv.egovernment.moa.id.config; +import at.gv.egovernment.moa.id.commons.db.dao.config.OAOAUTH20; import at.gv.egovernment.moa.id.commons.db.dao.config.OnlineApplication; /** - * Configuration parameters belonging to an online application, - * to be used within both, the MOA ID Auth and the - * MOA ID PROXY component. + * Configuration parameters belonging to an online application, to be used within both, the MOA ID + * Auth and the MOA ID PROXY component. * * @author Harald Bratko */ public class OAParameter { - + public OAParameter(OnlineApplication oa) { this.oaType = oa.getType(); @@ -54,55 +44,68 @@ public class OAParameter { this.removePBKFromAuthblock = oa.isRemoveBPKFromAuthBlock(); + this.oAuth20Config = oa.getAuthComponentOA().getOAOAUTH20(); + + } - /** - * type of the online application (maybe "PublicService" or "BusinessService") - */ - private String oaType; - - /** - * specifies whether the online application is a business application or not - * (true if value of {@link #oaType} is "businessService" - */ - private boolean businessService; - - /** - * public URL prefix of the online application - */ - private String publicURLPrefix; - - /** - * specifies a human readable name of the Online Application - */ - private String friendlyName; - - /** - * specified a specific target for the Online Application (overwrites the target in der request) - */ - private String target; - /** - * specifies a friendly name for the target - */ - private String targetFriendlyName; - - private boolean removePBKFromAuthblock; - + /** + * type of the online application (maybe "PublicService" or "BusinessService") + */ + private String oaType; + + /** + * specifies whether the online application is a business application or not (true + * if value of {@link #oaType} is "businessService" + */ + private boolean businessService; + + /** + * public URL prefix of the online application + */ + private String publicURLPrefix; + + /** + * specifies a human readable name of the Online Application + */ + private String friendlyName; + + /** + * specified a specific target for the Online Application (overwrites the target in der request) + */ + private String target; + /** + * specifies a friendly name for the target + */ + private String targetFriendlyName; + + private boolean removePBKFromAuthblock; + + /** + * Contains the oAuth 2.0 configuration (client id, secret and redirect uri) + */ + private OAOAUTH20 oAuth20Config; + public String getOaType() { return oaType; } + public boolean getBusinessService() { return businessService; } + public String getPublicURLPrefix() { return publicURLPrefix; } + public String getFriendlyName() { return friendlyName; } + public String getTarget() { return target; } + public String getTargetFriendlyName() { return targetFriendlyName; } @@ -110,5 +113,9 @@ public class OAParameter { public boolean isRemovePBKFromAuthBlock() { return removePBKFromAuthblock; } - + + public OAOAUTH20 getoAuth20Config() { + return oAuth20Config; + } + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java index 304771edf..29f567324 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java @@ -76,7 +76,6 @@ import at.gv.egovernment.moa.id.commons.db.dao.session.ExceptionStore; import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; import at.gv.egovernment.moa.id.commons.db.dao.session.OldSSOSessionIDStore; import at.gv.egovernment.moa.id.commons.db.dao.statistic.StatisticLog; -import at.gv.egovernment.moa.id.config.legacy.BuildFromLegacyConfig; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.ConfigurationProvider; import at.gv.egovernment.moa.id.config.ConfigurationUtils; @@ -84,6 +83,7 @@ import at.gv.egovernment.moa.id.config.ConnectionParameter; import at.gv.egovernment.moa.id.config.ConnectionParameterForeign; import at.gv.egovernment.moa.id.config.ConnectionParameterMOASP; import at.gv.egovernment.moa.id.config.ConnectionParameterMandate; +import at.gv.egovernment.moa.id.config.legacy.BuildFromLegacyConfig; import at.gv.egovernment.moa.id.config.stork.STORKConfig; import at.gv.egovernment.moa.id.data.IssuerAndSerial; import at.gv.egovernment.moa.logging.Logger; @@ -432,8 +432,10 @@ public class AuthConfigurationProvider extends ConfigurationProvider { if (foreign == null ) { Logger.warn("Error in MOA-ID Configuration. No STORK configuration found."); - } else - storkconfig = new STORKConfig(foreign.getSTORK(), props, rootConfigFileDir); + } + //TODO: commented because npe was thrown + //else + //storkconfig = new STORKConfig(foreign.getSTORK(), props, rootConfigFileDir); //load Chaining modes @@ -687,10 +689,9 @@ public class AuthConfigurationProvider extends ConfigurationProvider { } - public Properties getGeneralPVP2ProperiesConfig() { + private Properties getGeneralProperiesConfig(final String propPrefix) { Properties configProp = new Properties(); for (Object key : props.keySet()) { - String propPrefix = "protocols.pvp2."; if (key.toString().startsWith(propPrefix)) { String propertyName = key.toString().substring(propPrefix.length()); configProp.put(propertyName, props.get(key.toString())); @@ -699,6 +700,14 @@ public class AuthConfigurationProvider extends ConfigurationProvider { return configProp; } + public Properties getGeneralPVP2ProperiesConfig() { + return this.getGeneralProperiesConfig("protocols.pvp2."); + } + + public Properties getGeneralOAuth20ProperiesConfig() { + return this.getGeneralProperiesConfig("protocols.oauth20."); + } + public PVP2 getGeneralPVP2DBConfig() { return pvp2general; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java index 234641b4a..7130089ae 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java @@ -69,7 +69,6 @@ public class DispatcherServlet extends AuthServlet{ protected void processRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - boolean isValidSSOSession = false; boolean useSSOOA = false; String protocolRequestID = null; @@ -350,6 +349,7 @@ public class DispatcherServlet extends AuthServlet{ isValidSSOSession = ssomanager.isValidSSOSession(ssoId, req); useSSOOA = oaParam.useSSO(); + //if a legacy request is used SSO should not be allowed, actually boolean isUseMandateRequested = LegacyHelper.isUseMandateRequested(req); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulStorage.java index 2a92f3ce5..31bf1ff58 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulStorage.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulStorage.java @@ -10,7 +10,8 @@ public class ModulStorage { private static final String[] modulClasses = new String[]{ "at.gv.egovernment.moa.id.protocols.saml1.SAML1Protocol", - "at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol" + "at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol", + "at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Protocol" }; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20AuthAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20AuthAction.java new file mode 100644 index 000000000..949b06bb2 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20AuthAction.java @@ -0,0 +1,92 @@ +package at.gv.egovernment.moa.id.protocols.oauth20; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20ResponseTypeException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20ServerErrorException; +import at.gv.egovernment.moa.id.protocols.oauth20.requests.OAuth20AuthRequest; +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.logging.Logger; + +public class OAuth20AuthAction implements IAction { + + public String processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, + AuthenticationSession moasession) throws MOAIDException { + + OAuth20AuthRequest oAuthRequest = (OAuth20AuthRequest) req; + + // OAAuthParameter oaParam = + // AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oAuthRequest.getOAURL()); + // AuthenticationData authData = + // AuthenticationServer.buildAuthenticationData(moasession, oaParam, + // oAuthRequest.getTarget()); + + String responseType = oAuthRequest.getResponseType(); + + String code = AuthenticationSessionStoreage.changeSessionID(moasession); + Logger.debug("Stored session with id: " + code); + if (responseType.equals(OAuth20Constants.RESPONSE_CODE)) { + OAuth20SessionObject o = new OAuth20SessionObject(); + o.setScope(oAuthRequest.getScope()); + o.setCode(code); + moasession.setoAuth20SessionObject(o); + try { + AuthenticationSessionStoreage.storeSession(moasession); + } + catch (MOADatabaseException e) { + throw new OAuth20ServerErrorException(); + } + + Logger.debug("Saved OAuth20SessionObject in session with id: " + moasession.getSessionID()); + } else if (responseType.equals(OAuth20Constants.RESPONSE_TOKEN)) { + throw new OAuth20ResponseTypeException(); + } + + // add code and state to redirect url + httpResp.setStatus(HttpServletResponse.SC_FOUND); + String redirectURI = oAuthRequest.getRedirectUri(); + String state = oAuthRequest.getState(); + + redirectURI = this.addURLParameter(redirectURI, OAuth20Constants.RESPONSE_CODE, code); + redirectURI = this.addURLParameter(redirectURI, OAuth20Constants.PARAM_STATE, state); + + String finalUrl = redirectURI; + httpResp.addHeader("Location", finalUrl); + Logger.debug("REDIRECT TO: " + finalUrl.toString()); + return null; + } + + /* + * (non-Javadoc) + * @see + * at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls + * .IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { + return true; + } + + private String addURLParameter(String url, String name, String value) { + String param = name + "=" + value; + if (url.indexOf("?") < 0) { + return url + "?" + param; + } else { + return url + "&" + param; + } + } + + /* + * (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() + */ + public String getDefaultActionName() { + return OAuth20Protocol.AUTH_ACTION; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Configuration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Configuration.java new file mode 100644 index 000000000..54c285b96 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Configuration.java @@ -0,0 +1,51 @@ +package at.gv.egovernment.moa.id.protocols.oauth20; + +import java.util.Properties; + +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; + +public class OAuth20Configuration { + + private static OAuth20Configuration instance; + + public static OAuth20Configuration getInstance() { + if (instance == null) { + instance = new OAuth20Configuration(); + } + return instance; + } + + public static final String JWT_KEYSTORE = "jwt.ks.file"; + public static final String JWT_KEYSTORE_PASSWORD = "jwt.ks.password"; + public static final String JWT_KEY_NAME = "jwt.ks.key.name"; + public static final String JWT_KEY_PASSWORD = "jwt.ks.key.password"; + + private Properties props; + + private OAuth20Configuration() { + try { + props = AuthConfigurationProvider.getInstance().getGeneralOAuth20ProperiesConfig(); + } + catch (ConfigurationException e) { + e.printStackTrace(); + } + } + + public String getJWTKeyStore() { + return props.getProperty(JWT_KEYSTORE); + } + + public String getJWTKeyStorePassword() { + return props.getProperty(JWT_KEYSTORE_PASSWORD); + } + + public String getJWTKeyName() { + return props.getProperty(JWT_KEY_NAME); + } + + public String getJWTKeyPassword() { + return props.getProperty(JWT_KEY_PASSWORD); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Constants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Constants.java new file mode 100644 index 000000000..8189aa01b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Constants.java @@ -0,0 +1,45 @@ +package at.gv.egovernment.moa.id.protocols.oauth20; + +public class OAuth20Constants { + + private OAuth20Constants() { + + } + + // error parameters and error codes + public static final String PARAM_ERROR = "error"; + public static final String PARAM_ERROR_DESCRIPTION = "error_description"; + public static final String PARAM_ERROR_URI = "error_uri"; + + public static final String ERROR_INVALID_REQUEST = "invalid_request"; + public static final String ERROR_UNSUPPORTED_RESPONSE_TYPE = "unsupported_response_type"; + public static final String ERROR_INVALID_CLIENT = "invalid_client"; + public static final String ERROR_ACCESS_DENIED = "access_denied"; + public static final String ERROR_SERVER_ERROR = "server_error"; + public static final String ERROR_INVALID_GRANT = "invalid_grant"; + public static final String ERROR_UNAUTHORIZED_CLIENT = "unauthorized_client"; + + // request parameters + //public static final String PARAM_OA_URL = "oaURL"; + public static final String PARAM_RESPONSE_TYPE = "response_type"; + public static final String PARAM_REDIRECT_URI = "redirect_uri"; + public static final String PARAM_STATE = "state"; + public static final String PARAM_GRANT_TYPE = "grant_type"; + public static final String PARAM_GRANT_TYPE_VALUE_AUTHORIZATION_CODE = "authorization_code"; + public static final String PARAM_CLIENT_ID = "client_id"; + public static final String PARAM_CLIENT_SECRET = "client_secret"; + public static final String PARAM_SCOPE = "scope"; + public static final String PARAM_MOA_MOD = "mod"; + public static final String PARAM_MOA_ACTION = "action"; + + + // reponse parameters + public static final String RESPONSE_CODE = "code"; + public static final String RESPONSE_TOKEN = "token"; + public static final String RESPONSE_ACCESS_TOKEN = "access_token"; + public static final String RESPONSE_ID_TOKEN = "id_token"; + public static final String RESPONSE_EXPIRES_IN = "expires_in"; + public static final String RESPONSE_TOKEN_TYPE = "token_type"; + public static final String RESPONSE_TOKEN_TYPE_VALUE_BEARER = "Bearer"; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Protocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Protocol.java new file mode 100644 index 000000000..2c8aa8a73 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Protocol.java @@ -0,0 +1,166 @@ +package at.gv.egovernment.moa.id.protocols.oauth20; + +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IModulInfo; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20Exception; +import at.gv.egovernment.moa.id.protocols.oauth20.requests.OAuth20BaseRequest; +import at.gv.egovernment.moa.logging.Logger; + +import com.google.gson.JsonObject; + +public class OAuth20Protocol implements IModulInfo { + + public static final String NAME = OAuth20Protocol.class.getName(); + public static final String PATH = "id_oauth20"; + + public static final String AUTH_ACTION = "AUTH"; + public static final String TOKEN_ACTION = "TOKEN"; + + private static HashMap actions = new HashMap(); + + static { + actions.put(AUTH_ACTION, new OAuth20AuthAction()); + actions.put(TOKEN_ACTION, new OAuth20TokenAction()); + } + + public String getName() { + return NAME; + } + + public String getPath() { + return PATH; + } + + public IAction getAction(String action) { + return actions.get(action); + } + + /* + * (non-Javadoc) + * @see + * at.gv.egovernment.moa.id.moduls.IModulInfo#preProcess(javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse, java.lang.String) + */ + public IRequest preProcess(HttpServletRequest request, HttpServletResponse resp, String action) throws MOAIDException { + // validation is done inside creation + OAuth20BaseRequest res = OAuth20BaseRequest.newInstance(action, request); + Logger.debug("Created: " + res); + return res; + } + + /* + * (non-Javadoc) + * @see + * at.gv.egovernment.moa.id.moduls.IModulInfo#canHandleRequest(javax.servlet.http.HttpServletRequest + * , javax.servlet.http.HttpServletResponse) + */ + public IAction canHandleRequest(HttpServletRequest request, HttpServletResponse response) { + if (request.getParameter("action").equals(AUTH_ACTION)) { + return getAction(AUTH_ACTION); + } else if (request.getParameter("action").equals(TOKEN_ACTION)) { + return getAction(TOKEN_ACTION); + } + + return null;// getAction(AUTH_ACTION); + } + + /* + * (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IModulInfo#generateErrorMessage(java.lang.Throwable, + * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, + * at.gv.egovernment.moa.id.moduls.IRequest) + */ + public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) + throws Throwable { + + StringBuilder url = new StringBuilder(); + + String paramRedirect = request.getParameter(OAuth20Constants.PARAM_REDIRECT_URI); + + if (e instanceof OAuth20Exception) { + + String action = request.getParameter("action"); + + Logger.debug("Going to throw O OAuth20Exception for action: " + action); + OAuth20Exception oAuth20Exception = ((OAuth20Exception) e); + + String errorCode = oAuth20Exception.getErrorCode(); + String errorDescription = oAuth20Exception.getMessage(); + // String errorUri = "http://tools.ietf.org/html/draft-ietf-oauth-v2-11"; + + if (action.equals(AUTH_ACTION)) { + + // check if given redirect url is ok + if (StringUtils.isNotEmpty(paramRedirect) && OAuth20Util.isUrl(paramRedirect)) { + url.append(paramRedirect); + + // otherwise throw an + } else { + throw new MOAIDException("oauth20.01", new Object[] {}); + } + + String state = request.getParameter(OAuth20Constants.PARAM_STATE); + + OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR, errorCode); + OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR_DESCRIPTION, + URLEncoder.encode(oAuth20Exception.getMessageId() + ": " + errorDescription, "UTF-8")); + // OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR_URI, errorUri); + OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_STATE, state); + + response.setContentType("text/html"); + response.setStatus(HttpServletResponse.SC_FOUND); + response.addHeader("Location", url.toString()); + Logger.debug("REDIRECT TO: " + url.toString()); + return true; + + } else if (action.equals(TOKEN_ACTION)) { + Map params = new HashMap(); + params.put(OAuth20Constants.PARAM_ERROR, errorCode); + params.put(OAuth20Constants.PARAM_ERROR_DESCRIPTION, + URLEncoder.encode(oAuth20Exception.getMessageId() + ": " + errorDescription, "UTF-8")); + // params.put(OAuth20Constants.PARAM_ERROR_URI, errorUri); + + // create response + JsonObject jsonObject = new JsonObject(); + OAuth20Util.addProperytiesToJsonObject(jsonObject, params); + String jsonResponse = jsonObject.toString(); + Logger.debug("JSON Response: " + jsonResponse); + + // write respone to http response + response.setContentType("application/json"); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + response.getOutputStream().print(jsonResponse); + response.getOutputStream().close(); + + return true; + } + + } + + return false; + + } + + /* + * (non-Javadoc) + * @see + * at.gv.egovernment.moa.id.moduls.IModulInfo#validate(javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.moduls.IRequest) + */ + public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { + // we validate in the preProcess + return true; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20SessionObject.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20SessionObject.java new file mode 100644 index 000000000..91c099d2c --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20SessionObject.java @@ -0,0 +1,39 @@ +package at.gv.egovernment.moa.id.protocols.oauth20; + +import java.io.Serializable; + +public class OAuth20SessionObject implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private String scope; + + private String code; + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + /** + * @return the code + */ + public String getCode() { + return code; + } + + /** + * @param code + * the code to set + */ + public void setCode(String code) { + this.code = code; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20TokenAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20TokenAction.java new file mode 100644 index 000000000..70f425148 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20TokenAction.java @@ -0,0 +1,346 @@ +package at.gv.egovernment.moa.id.protocols.oauth20; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import net.oauth.jsontoken.JsonToken; +import net.oauth.jsontoken.crypto.Signer; + +import org.w3c.dom.Element; + +import at.gv.e_government.reference.namespace.mandates._20040701_.Mandate; +import at.gv.e_government.reference.namespace.persondata._20020228_.CorporateBodyType; +import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType; +import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameType.FamilyName; +import at.gv.e_government.reference.namespace.persondata._20020228_.PhysicalPersonType; +import at.gv.egovernment.moa.id.auth.AuthenticationServer; +import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.AuthenticationData; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20ServerErrorException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20UnauthorizedClientException; +import at.gv.egovernment.moa.id.protocols.oauth20.requests.OAuth20TokenRequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AttributeExtractor; +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; +import at.gv.egovernment.moa.id.util.MandateBuilder; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DOMUtils; + +import com.google.gson.JsonObject; + +public class OAuth20TokenAction implements IAction { + + private int expirationTime = 5 * 60; // in seconds + + public class Pair { + private T1 first; + private T2 second; + + public Pair(T1 newFirst, T2 newSecond) { + first = newFirst; + second = newSecond; + } + + public T1 getFirst() { + return first; + } + + public T2 getSecond() { + return second; + } + } + + public String processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, + AuthenticationSession moasession) throws MOAIDException { + + AuthenticationSession session = null; + try { + OAuth20TokenRequest oAuthRequest = (OAuth20TokenRequest) req; + + session = AuthenticationSessionStoreage.getSession(oAuthRequest.getCode()); + if (session == null) { + throw new OAuth20UnauthorizedClientException(); + } + + OAuth20SessionObject auth20SessionObject = session.getoAuth20SessionObject(); + Logger.debug("Loaded OAuth20SessionObject from session: " + auth20SessionObject); + + // do checking for different grant types and code + if (!auth20SessionObject.getCode().equals(oAuthRequest.getCode())) { + throw new OAuth20UnauthorizedClientException(); + + } + + final String accessToken = UUID.randomUUID().toString(); + + // create response + Map params = new HashMap(); + params.put(OAuth20Constants.RESPONSE_ACCESS_TOKEN, accessToken); + params.put(OAuth20Constants.RESPONSE_TOKEN_TYPE, OAuth20Constants.RESPONSE_TOKEN_TYPE_VALUE_BEARER); + params.put(OAuth20Constants.RESPONSE_EXPIRES_IN, this.expirationTime); + + // build id token and scope + Pair pair = buildIdToken(auth20SessionObject.getScope(), oAuthRequest, session); + Logger.debug("RESPONSE ID_TOKEN: " + pair.getFirst()); + params.put(OAuth20Constants.RESPONSE_ID_TOKEN, pair.getFirst()); + Logger.debug("RESPONSE SCOPE: " + pair.getSecond()); + params.put(OAuth20Constants.PARAM_SCOPE, pair.getSecond()); + + // create response + JsonObject jsonObject = new JsonObject(); + OAuth20Util.addProperytiesToJsonObject(jsonObject, params); + String jsonResponse = jsonObject.toString(); + Logger.debug("JSON Response: " + jsonResponse); + + // write respone to http response + httpResp.setContentType("application/json"); + httpResp.setStatus(HttpServletResponse.SC_OK); + httpResp.getOutputStream().print(jsonResponse); + httpResp.getOutputStream().close(); + + return null; + } + catch (Exception e) { + throw new OAuth20ServerErrorException(); + } + finally { + if (session != null) { + // destroy session for clean up + try { + Logger.debug("Going to destroy session: " + session.getSessionID()); + AuthenticationSessionStoreage.destroySession(session.getSessionID()); + } + catch (MOADatabaseException e) { + } + } + } + } + + /* + * (non-Javadoc) + * @see + * at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls + * .IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { + return false; + } + + /* + * (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() + */ + public String getDefaultActionName() { + return OAuth20Protocol.TOKEN_ACTION; + } + + private Pair buildIdToken(String scope, OAuth20TokenRequest oAuthRequest, AuthenticationSession session) + throws Exception { + OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oAuthRequest.getOAURL()); + AuthenticationData authData = AuthenticationServer.buildAuthenticationData(session, oaParam, oAuthRequest.getTarget()); + + Map params = new HashMap(); + StringBuilder resultScopes = new StringBuilder(); + // always fill with open id + this.fillScopeOpenId(params, authData); + resultScopes.append("openId"); + + for (String s : scope.split(" ")) { + + try { + if (s.equalsIgnoreCase("profile")) { + this.fillScopeProfile(params, authData); + resultScopes.append(" profile"); + } else if (s.equalsIgnoreCase("eID")) { + this.fillScopeEID(params, authData, session); + resultScopes.append(" eID"); + } else if (s.equalsIgnoreCase("eID_gov") && oaParam.getBusinessService()) { + this.fillScopeEID_GOV(params, authData, session); + resultScopes.append(" eID_gov"); + } else if (s.equalsIgnoreCase("mandate") && session.getUseMandate() && oaParam.getBusinessService()) { + this.fillScopeMandate(params, oaParam, authData, session); + resultScopes.append(" mandate"); + } + } + catch (Exception e) { + Logger.warn(e.getMessage(), e); + } + // TODO parser STORK + } + + // add properties and sign + // HmacSHA256Signer signer = new HmacSHA256Signer("testSigner", "key_id", + // "super_secure_pwd".getBytes()); + // Signer signer = OAuth20Util.loadSigner(authData.getIssuer(), oaParam.getoAuth20Config()); + Signer signer = OAuth20Util.loadSigner(authData.getIssuer()); + JsonToken token = new JsonToken(signer); + OAuth20Util.addProperytiesToJsonObject(token.getPayloadAsJsonObject(), params); + return new Pair(token.serializeAndSign(), resultScopes.toString()); + } + + private void fillScopeProfile(Map params, AuthenticationData authData) { + params.put("given_name", authData.getGivenName()); + params.put("family_name", authData.getFamilyName()); + params.put("birthdate", authData.getDateOfBirth()); + } + + private void fillScopeOpenId(Map params, AuthenticationData authData) { + params.put("iss", authData.getIssuer()); + params.put("sub", authData.getBPK()); + // params.put("aud", ""); // not used + params.put("exp", (long) (new Date().getTime() / 1000 + this.expirationTime)); + params.put("iat", (long) (new Date().getTime() / 1000)); + params.put("auth_time", (long) (authData.getTimestamp().getTime() / 1000)); + // params.put("acr", ""); //? + } + + private void fillScopeEID(Map params, AuthenticationData authData, AuthenticationSession session) throws Exception { + params.put(PVPConstants.EID_CCS_URL_FRIENDLY_NAME, authData.getBkuURL()); + // params.put("ENC-BPK-LIST", ); // not used + // params.put("MAIL", ); //not used + // params.put("TEL", ); //not used + + params.put(PVPConstants.EID_CITIZEN_QAA_LEVEL_FRIENDLY_NAME, 4); + params.put(PVPConstants.EID_ISSUING_NATION_FRIENDLY_NAME, "AT"); + params.put(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, authData.getBPKType()); + params.put(PVPConstants.EID_AUTH_BLOCK_FRIENDLY_NAME, Base64Utils.encode(session.getAuthBlock().getBytes())); + params.put(PVPConstants.EID_SIGNER_CERTIFICATE_FRIENDLY_NAME, Base64Utils.encode(session.getEncodedSignerCertificate())); + // params.put(PVPConstants.EID_STORK_TOKEN_FRIENDLY_NAME, ); //not used + + // bpk + String bpk = authData.getBPK(); + String type = authData.getBPKType(); + if (type.startsWith(Constants.URN_PREFIX_WBPK)) + type = type.substring((Constants.URN_PREFIX_WBPK + "+").length()); + else if (type.startsWith(Constants.URN_PREFIX_CDID)) type = type.substring((Constants.URN_PREFIX_CDID + "+").length()); + if (bpk.length() > PVPConstants.BPK_MAX_LENGTH) { + bpk = bpk.substring(0, PVPConstants.BPK_MAX_LENGTH); + } + params.put(PVPConstants.BPK_FRIENDLY_NAME, type + ":" + bpk); + } + + private void fillScopeEID_GOV(Map params, AuthenticationData authData, AuthenticationSession session) + throws Exception { + params.put(PVPConstants.EID_SOURCE_PIN_FRIENDLY_NAME, authData.getIdentificationValue()); + params.put(PVPConstants.EID_SOURCE_PIN_TYPE_FRIENDLY_NAME, authData.getIdentificationType()); + + IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance(); + Element resignedilAssertion = identitylinkresigner.resignIdentityLink(authData.getIdentityLink().getSamlAssertion()); + params.put(PVPConstants.EID_IDENTITY_LINK_FRIENDLY_NAME, + Base64Utils.encode(DOMUtils.serializeNode(resignedilAssertion).getBytes())); + } + + private void fillScopeMandate(Map params, OAAuthParameter oaParam, AuthenticationData authData, + AuthenticationSession session) { + Element mandate = session.getMandate(); + + if (mandate == null) { + throw new OAuth20ServerErrorException(); + } + Mandate mandateObject = MandateBuilder.buildMandate(mandate); + if (mandateObject == null) { + throw new OAuth20ServerErrorException(); + } + + params.put(PVPConstants.MANDATE_TYPE_FRIENDLY_NAME, mandateObject.getAnnotation()); + params.put(PVPConstants.MANDATE_REFERENCE_VALUE_FRIENDLY_NAME, mandateObject.getMandateID()); + + // natural person + PhysicalPersonType physicalPerson = mandateObject.getMandator().getPhysicalPerson(); + if (physicalPerson != null && physicalPerson.getIdentification().size() != 0) { + IdentificationType id = physicalPerson.getIdentification().get(0); + params.put(PVPConstants.MANDATE_NAT_PER_SOURCE_PIN_FRIENDLY_NAME, id.getValue().getValue()); + params.put(PVPConstants.MANDATE_NAT_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME, id.getType()); + + try { + String bpk; + if (id.getType().equals(Constants.URN_PREFIX_BASEID)) { + if (session.getBusinessService()) { + bpk = new BPKBuilder().buildWBPK(id.getValue().getValue(), oaParam.getIdentityLinkDomainIdentifier()); + } else { + bpk = new BPKBuilder().buildBPK(id.getValue().getValue(), oaParam.getTarget()); + } + } else { + bpk = id.getValue().getValue(); + } + params.put(PVPConstants.MANDATE_NAT_PER_BPK_FRIENDLY_NAME, bpk); + } + catch (BuildException e) { + // ignore + } + + // params.put(PVPConstants.MANDATE_NAT_PER_ENC_BPK_LIST_FRIENDLY_NAME, ); //not used + + StringBuilder sb = new StringBuilder(); + Iterator fNamesit = physicalPerson.getName().getFamilyName().iterator(); + + while (fNamesit.hasNext()) { + sb.append(" " + fNamesit.next().getValue()); + } + params.put(PVPConstants.MANDATE_NAT_PER_FAMILY_NAME_FRIENDLY_NAME, sb.toString()); + + sb = new StringBuilder(); + Iterator gNamesit = physicalPerson.getName().getGivenName().iterator(); + + while (gNamesit.hasNext()) { + sb.append(" " + gNamesit.next()); + } + params.put(PVPConstants.MANDATE_NAT_PER_GIVEN_NAME_FRIENDLY_NAME, sb.toString()); + + try { + DateFormat mandateFormat = new SimpleDateFormat(MandateBuilder.MANDATE_DATE_OF_BIRTH_FORMAT); + Date date = mandateFormat.parse(physicalPerson.getDateOfBirth()); + DateFormat pvpDateFormat = new SimpleDateFormat(PVPConstants.MANDATE_NAT_PER_BIRTHDATE_FORMAT_PATTERN); + String dateString = pvpDateFormat.format(date); + params.put(PVPConstants.MANDATE_NAT_PER_BIRTHDATE_FRIENDLY_NAME, dateString); + } + catch (ParseException e) { + // ignore + } + + } + + // legal person + CorporateBodyType corporation = mandateObject.getMandator().getCorporateBody(); + if (corporation != null && corporation.getIdentification().size() != 0) { + IdentificationType id = corporation.getIdentification().get(0); + params.put(PVPConstants.MANDATE_LEG_PER_SOURCE_PIN_FRIENDLY_NAME, id.getValue().getValue()); + params.put(PVPConstants.MANDATE_LEG_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME, id.getType()); + params.put(PVPConstants.MANDATE_LEG_PER_FULL_NAME_FRIENDLY_NAME, corporation.getFullName()); + } + + String oid = AttributeExtractor.extractSAMLAttributeOA(EXT_SAML_MANDATE_OID, session); + if (oid != null) { + params.put(PVPConstants.MANDATE_PROF_REP_OID_FRIENDLY_NAME, oid); + } + + String text = AttributeExtractor.extractSAMLAttributeOA(EXT_SAML_MANDATE_OIDTEXTUALDESCRIPTION, session); + + if (text != null) { + params.put(PVPConstants.MANDATE_PROF_REP_DESC_FRIENDLY_NAME, oid); + } + + // params.put("MANDATE-FULL-MANDATE-LIST", ); // not used + + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Util.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Util.java new file mode 100644 index 000000000..4d3030a0f --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Util.java @@ -0,0 +1,134 @@ +package at.gv.egovernment.moa.id.protocols.oauth20; + +import java.io.UnsupportedEncodingException; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.oauth.jsontoken.crypto.RsaSHA256Signer; +import net.oauth.jsontoken.crypto.Signer; + +import org.opensaml.xml.security.x509.BasicX509Credential; + +import at.gv.egovernment.moa.id.commons.db.dao.config.OAOAUTH20; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20CertificateErrorException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20Exception; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.KeyStoreUtils; +import at.gv.egovernment.moa.util.StringUtils; + +import com.google.gson.JsonObject; + +public class OAuth20Util { + + public static final String REGEX_HTTPS = "^(https?)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"; + public static final String REGEX_FILE = "^(file):/.[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"; + + /** + * Simple helper function to add parameter to a url + * + * @param url + * @param name + * @param value + * @throws UnsupportedEncodingException + */ + public static void addParameterToURL(final StringBuilder url, final String name, final String value) + throws UnsupportedEncodingException { + if (url.indexOf("?") < 0) { + url.append("?"); + } else { + url.append("&"); + } + // URLEncoder.encode(value, "UTF-8") + url.append(name).append("=").append(value); + } + + public static boolean isUrl(final String url) { + Pattern urlPattern; + if (url.startsWith("file")) { + urlPattern = Pattern.compile(REGEX_FILE, Pattern.CASE_INSENSITIVE); + } else { + urlPattern = Pattern.compile(REGEX_HTTPS, Pattern.CASE_INSENSITIVE); + } + + Matcher matcher = urlPattern.matcher(url); + return matcher.find(); + } + + public static void addProperytiesToJsonObject(JsonObject jsonObject, Map params) { + for (Map.Entry param : params.entrySet()) { + if (param.getKey() != null && !"".equals(param.getKey()) && param.getValue() != null && !"".equals(param.getValue())) { + + // check for integer + try { + int i = Integer.parseInt(String.valueOf(param.getValue())); + jsonObject.addProperty(param.getKey(), i); + continue; + } + catch (NumberFormatException e) { + } + + // check for long + try { + long l = Long.parseLong(String.valueOf(param.getValue())); + jsonObject.addProperty(param.getKey(), l); + continue; + } + catch (NumberFormatException e) { + } + + // string + if (param.getValue() instanceof String) { + jsonObject.addProperty(param.getKey(), String.valueOf(param.getValue())); + } + } + } + } + + public static Signer loadSigner(String issuer) throws OAuth20Exception { + OAuth20Configuration globalConfig = OAuth20Configuration.getInstance(); + + if (StringUtils.isEmpty(globalConfig.getJWTKeyStore())) { + throw new OAuth20CertificateErrorException("keystore"); + } + + if (StringUtils.isEmpty(globalConfig.getJWTKeyName())) { + throw new OAuth20CertificateErrorException("key name"); + } + + try { + KeyStore ks = KeyStoreUtils.loadKeyStore(globalConfig.getJWTKeyStore(), globalConfig.getJWTKeyStorePassword()); + + X509Certificate certificate = (X509Certificate) ks.getCertificate(globalConfig.getJWTKeyName()); + + PrivateKey privateKey = (PrivateKey) ks.getKey(globalConfig.getJWTKeyName(), globalConfig.getJWTKeyPassword() + .toCharArray()); + BasicX509Credential credential = new BasicX509Credential(); + credential.setEntityCertificate(certificate); + credential.setPrivateKey(privateKey); + + //Logger.debug("Going to use X509Certificate:"); + Logger.debug(certificate); + //Logger.debug("Going to use private key:"); + Logger.debug(privateKey); + + return new RsaSHA256Signer(issuer, globalConfig.getJWTKeyName(), (RSAPrivateKey) credential.getPrivateKey()); + + } + catch (Exception e) { + throw new OAuth20CertificateErrorException("keystore"); + } + + } + + public static boolean isValidStateValue(String state) { + Pattern urlPattern = Pattern.compile("javascript|<|>|&|;", Pattern.CASE_INSENSITIVE); + Matcher matcher = urlPattern.matcher(state); + return !matcher.find(); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20AccessDeniedException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20AccessDeniedException.java new file mode 100644 index 000000000..e4abd5bd1 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20AccessDeniedException.java @@ -0,0 +1,12 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20AccessDeniedException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20AccessDeniedException() { + super(OAuth20Constants.ERROR_ACCESS_DENIED, "oauth20.05", new Object[] {}); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20CertificateErrorException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20CertificateErrorException.java new file mode 100644 index 000000000..6f5a41ca5 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20CertificateErrorException.java @@ -0,0 +1,12 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20CertificateErrorException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20CertificateErrorException(final String name) { + super(OAuth20Constants.ERROR_SERVER_ERROR, "oauth20.09", new Object[] { name }); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20Exception.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20Exception.java new file mode 100644 index 000000000..1c4cb20ac --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20Exception.java @@ -0,0 +1,49 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; + +public class OAuth20Exception extends RuntimeException { + + private static final long serialVersionUID = 1L; + + private String messageId; + + private String errorCode; + + public OAuth20Exception(final String errorCode, final String messageId, final Object[] parameters) { + super(MOAIDMessageProvider.getInstance().getMessage(messageId, parameters)); + this.errorCode = errorCode; + this.messageId = messageId; + } + + /** + * @return the messageId + */ + public String getMessageId() { + return messageId; + } + + /** + * @param messageId + * the messageId to set + */ + public void setMessageId(String messageId) { + this.messageId = messageId; + } + + /** + * @return the errorCode + */ + public String getErrorCode() { + return errorCode; + } + + /** + * @param errorCode + * the errorCode to set + */ + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidClientException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidClientException.java new file mode 100644 index 000000000..2a2ec4498 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidClientException.java @@ -0,0 +1,12 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20InvalidClientException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20InvalidClientException() { + super(OAuth20Constants.ERROR_INVALID_CLIENT, "oauth20.05", new Object[] {}); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidGrantException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidGrantException.java new file mode 100644 index 000000000..288667104 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidGrantException.java @@ -0,0 +1,12 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20InvalidGrantException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20InvalidGrantException() { + super(OAuth20Constants.ERROR_INVALID_GRANT, "oauth20.07", new Object[] {}); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidRequestException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidRequestException.java new file mode 100644 index 000000000..30c1cb1cc --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20InvalidRequestException.java @@ -0,0 +1,13 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20InvalidRequestException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20InvalidRequestException() { + super(OAuth20Constants.ERROR_INVALID_REQUEST, "oauth20.04", new Object[] {}); + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20ResponseTypeException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20ResponseTypeException.java new file mode 100644 index 000000000..5dd0a13c3 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20ResponseTypeException.java @@ -0,0 +1,12 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20ResponseTypeException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20ResponseTypeException() { + super(OAuth20Constants.ERROR_UNSUPPORTED_RESPONSE_TYPE, "oauth20.03", new Object[] {}); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20ServerErrorException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20ServerErrorException.java new file mode 100644 index 000000000..59855d511 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20ServerErrorException.java @@ -0,0 +1,12 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20ServerErrorException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20ServerErrorException() { + super(OAuth20Constants.ERROR_SERVER_ERROR, "oauth20.06", new Object[] {}); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20UnauthorizedClientException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20UnauthorizedClientException.java new file mode 100644 index 000000000..28cc44968 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20UnauthorizedClientException.java @@ -0,0 +1,12 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20UnauthorizedClientException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20UnauthorizedClientException() { + super(OAuth20Constants.ERROR_UNAUTHORIZED_CLIENT, "oauth20.08", new Object[] {}); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20WrongParameterException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20WrongParameterException.java new file mode 100644 index 000000000..24d151869 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/exceptions/OAuth20WrongParameterException.java @@ -0,0 +1,12 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.exceptions; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; + +public class OAuth20WrongParameterException extends OAuth20Exception { + private static final long serialVersionUID = 1L; + + public OAuth20WrongParameterException(final String name) { + super(OAuth20Constants.ERROR_INVALID_REQUEST, "oauth20.02", new Object[] { name }); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20AuthRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20AuthRequest.java new file mode 100644 index 000000000..8aac75413 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20AuthRequest.java @@ -0,0 +1,134 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.requests; + +import javax.servlet.http.HttpServletRequest; + +import at.gv.egovernment.moa.id.commons.db.dao.config.OAOAUTH20; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Util; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20AccessDeniedException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20Exception; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20ResponseTypeException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20WrongParameterException; + +public class OAuth20AuthRequest extends OAuth20BaseRequest { + + private static final long serialVersionUID = 1L; + + private String responseType; + private String state; + private String redirectUri; + private String scope; + private String clientID; + + /** + * @return the responseType + */ + public String getResponseType() { + return responseType; + } + + /** + * @param responseType + * the responseType to set + */ + public void setResponseType(String responseType) { + this.responseType = responseType; + } + + /** + * @return the state + */ + public String getState() { + return state; + } + + /** + * @param state + * the state to set + */ + public void setState(String state) { + this.state = state; + } + + /** + * @return the redirectUri + */ + public String getRedirectUri() { + return redirectUri; + } + + /** + * @param redirectUri + * the redirectUri to set + */ + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + /** + * @return the scope + */ + public String getScope() { + return scope; + } + + /** + * @param scope + * the scope to set + */ + public void setScope(String scope) { + this.scope = scope; + } + + /** + * @return the clientID + */ + public String getClientID() { + return clientID; + } + + /** + * @param clientID + * the clientID to set + */ + public void setClientID(String clientID) { + this.clientID = clientID; + } + + @Override + protected void populateSpecialParameters(HttpServletRequest request) throws OAuth20Exception { + this.setResponseType(this.getParam(request, OAuth20Constants.PARAM_RESPONSE_TYPE, true)); + this.setState(this.getParam(request, OAuth20Constants.PARAM_STATE, true)); + this.setRedirectUri(this.getParam(request, OAuth20Constants.PARAM_REDIRECT_URI, true)); + this.setClientID(this.getParam(request, OAuth20Constants.PARAM_CLIENT_ID, true)); + this.setScope(this.getParam(request, OAuth20Constants.PARAM_SCOPE, false)); + + // check for response type + if (!this.responseType.equals(OAuth20Constants.RESPONSE_CODE)) { + throw new OAuth20ResponseTypeException(); + } + + // check state for invalid characters (like < > & ; ... javascript ... to prevent xss) + if (!OAuth20Util.isValidStateValue(this.getState())) { + throw new OAuth20WrongParameterException(OAuth20Constants.PARAM_STATE); + } + + // check if client id and redirect uri are ok + try { + // OAOAUTH20 cannot be null at this point. check was done in base request + OAOAUTH20 oAuthConfig = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(this.getOAURL()) + .getoAuth20Config(); + + if (!this.getClientID().equals(oAuthConfig.getOAuthClientId()) + || !this.getRedirectUri().equals(oAuthConfig.getOAuthRedirectUri())) { + throw new OAuth20AccessDeniedException(); + } + } + catch (ConfigurationException e) { + throw new OAuth20WrongParameterException(OAuth20Constants.PARAM_CLIENT_ID); + } + + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20BaseRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20BaseRequest.java new file mode 100644 index 000000000..05362c977 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20BaseRequest.java @@ -0,0 +1,118 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.requests; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; + +import at.gv.egovernment.moa.id.commons.db.dao.config.OAOAUTH20; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.moduls.RequestImpl; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Protocol; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20Exception; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20InvalidRequestException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20ServerErrorException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20WrongParameterException; +import at.gv.egovernment.moa.id.util.ParamValidatorUtils; +import at.gv.egovernment.moa.logging.Logger; + +public abstract class OAuth20BaseRequest extends RequestImpl { + + private static final long serialVersionUID = 1L; + + protected Set allowedParameters = new HashSet(); + + protected String getParam(final HttpServletRequest request, final String name, final boolean isNeeded) throws OAuth20Exception { + String param = request.getParameter(name); + Logger.debug("Reading param " + name + " from HttpServletRequest with value " + param); + + if (isNeeded && StringUtils.isEmpty(param)) { + throw new OAuth20WrongParameterException(name); + } + + this.allowedParameters.add(name); + + return param; + } + + protected void populateParameters(final HttpServletRequest request) throws OAuth20Exception { + + // moa id - load oa with client id! + try { + String oaURL = StringEscapeUtils.escapeHtml(this.getParam(request, OAuth20Constants.PARAM_CLIENT_ID, true)); + if (!ParamValidatorUtils.isValidOA(oaURL)) { + throw new OAuth20WrongParameterException(OAuth20Constants.PARAM_CLIENT_ID); + } + this.setOAURL(oaURL); + OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL); + + if (oaParam == null) { + throw new OAuth20WrongParameterException(OAuth20Constants.PARAM_CLIENT_ID); + } + this.setTarget(oaParam.getTarget()); + + OAOAUTH20 config = oaParam.getoAuth20Config(); + if (config == null) { + throw new OAuth20InvalidRequestException(); + } + if (StringUtils.isEmpty(config.getOAuthClientSecret()) || StringUtils.isEmpty(config.getOAuthClientId()) + || StringUtils.isEmpty(config.getOAuthRedirectUri())) { + throw new OAuth20ServerErrorException(); + } + } + catch (ConfigurationException e) { + throw new OAuth20WrongParameterException(OAuth20Constants.PARAM_CLIENT_ID); + } + + // oAuth + this.populateSpecialParameters(request); + + // cleanup parameters + this.checkAllowedParameters(request); + } + + private void checkAllowedParameters(final HttpServletRequest request) { + Logger.debug("Going to check for allowed parameters"); + this.allowedParameters.add(OAuth20Constants.PARAM_MOA_ACTION); + this.allowedParameters.add(OAuth20Constants.PARAM_MOA_MOD); + + @SuppressWarnings("rawtypes") + Iterator iter = request.getParameterMap().keySet().iterator(); + while (iter.hasNext()) { + String name = (String) iter.next(); + if (!this.allowedParameters.contains(name)) { + + Logger.debug("Found wrong parameter: " + name); + throw new OAuth20WrongParameterException(name); + } + } + + } + + protected abstract void populateSpecialParameters(final HttpServletRequest request) throws OAuth20Exception; + + public static OAuth20BaseRequest newInstance(final String action, final HttpServletRequest request) throws OAuth20Exception { + OAuth20BaseRequest res; + + if (action.equals(OAuth20Protocol.AUTH_ACTION)) { + res = new OAuth20AuthRequest(); + } else if (action.equals(OAuth20Protocol.TOKEN_ACTION)) { + res = new OAuth20TokenRequest(); + } else { + throw new OAuth20InvalidRequestException(); + } + + res.setAction(action); + res.setModule(OAuth20Protocol.NAME); + + res.populateParameters(request); + return res; + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20TokenRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20TokenRequest.java new file mode 100644 index 000000000..6d69f8238 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/requests/OAuth20TokenRequest.java @@ -0,0 +1,118 @@ +package at.gv.egovernment.moa.id.protocols.oauth20.requests; + +import javax.servlet.http.HttpServletRequest; + +import at.gv.egovernment.moa.id.commons.db.dao.config.OAOAUTH20; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20AccessDeniedException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20Exception; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20InvalidGrantException; +import at.gv.egovernment.moa.id.protocols.oauth20.exceptions.OAuth20WrongParameterException; + +public class OAuth20TokenRequest extends OAuth20BaseRequest { + + private static final long serialVersionUID = 1L; + + private String code; + private String grantType; + private String clientID; + private String clientSecret; + + /** + * @return the code + */ + public String getCode() { + return code; + } + + /** + * @param code + * the code to set + */ + public void setCode(String code) { + this.code = code; + } + + /** + * @return the grantType + */ + public String getGrantType() { + return grantType; + } + + /** + * @param grantType + * the grantType to set + */ + public void setGrantType(String grantType) { + this.grantType = grantType; + } + + /** + * @return the clientID + */ + public String getClientID() { + return clientID; + } + + /** + * @param clientID + * the clientID to set + */ + public void setClientID(String clientID) { + this.clientID = clientID; + } + + /** + * @return the clientSecret + */ + public String getClientSecret() { + return clientSecret; + } + + /** + * @param clientSecret + * the clientSecret to set + */ + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + @Override + protected void populateSpecialParameters(HttpServletRequest request) throws OAuth20Exception { + this.setCode(this.getParam(request, OAuth20Constants.RESPONSE_CODE, true)); + this.setGrantType(this.getParam(request, OAuth20Constants.PARAM_GRANT_TYPE, true)); + this.setClientID(this.getParam(request, OAuth20Constants.PARAM_CLIENT_ID, true)); + this.setClientSecret(this.getParam(request, OAuth20Constants.PARAM_CLIENT_SECRET, true)); + + // check for grant type + if (!this.getGrantType().equals(OAuth20Constants.PARAM_GRANT_TYPE_VALUE_AUTHORIZATION_CODE)) { + throw new OAuth20InvalidGrantException(); + } + + // check if client id and secret are ok + try { + // OAOAUTH20 cannot be null at this point. check was done in base request + OAOAUTH20 oAuthConfig = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(this.getOAURL()) + .getoAuth20Config(); + + if (!this.getClientID().equals(oAuthConfig.getOAuthClientId())) { + throw new OAuth20AccessDeniedException(); + } + + if (!this.getClientSecret().equals(oAuthConfig.getOAuthClientSecret())) { + throw new OAuth20AccessDeniedException(); + } + + } + catch (ConfigurationException e) { + throw new OAuth20WrongParameterException(OAuth20Constants.PARAM_CLIENT_ID); + } + + //add valid parameters + this.allowedParameters.add(OAuth20Constants.PARAM_SCOPE); + this.allowedParameters.add(OAuth20Constants.PARAM_REDIRECT_URI); + } +} diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index 6b664f692..37e35b6ce 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -217,4 +217,15 @@ pvp2.11=Binding {0} wird nicht unterstuetzt pvp2.12=NameID Format {0} wird nicht unterstuetzt pvp2.13=Interner Server Fehler pvp2.14=SAML Anfrage verweigert -pvp2.15=Keine Metadateninformation gefunden +pvp2.15=Keine Metadateninformation gefunden + + +oauth20.01=Fehlerhafte redirect url +oauth20.02=Fehlender Parameter "{0}" +oauth20.03=Angeforderter response_type ist nicht erlaubt +oauth20.04=Die Art der Anmeldung wird nicht unterstuetzt +oauth20.05=Der angegebene Benutzer ist nicht berechtigt +oauth20.06=Die angegebene OA kann nicht verwendet werden +oauth20.07=Angeforderter grant_type ist nicht erlaubt +oauth20.08=Nicht berechtigt für Token-Request +oauth20.09=Zertifikat fuer JSON Web-Token ist falsch konfiguriert. Fehler bei "{0}" diff --git a/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/CertTest.java b/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/CertTest.java new file mode 100644 index 000000000..6452d5ae6 --- /dev/null +++ b/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/CertTest.java @@ -0,0 +1,86 @@ +package test.at.gv.egovernment.moa.id.auth.oauth; + +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; + +import net.oauth.jsontoken.crypto.RsaSHA256Signer; +import net.oauth.jsontoken.crypto.RsaSHA256Verifier; + +import org.opensaml.xml.security.x509.BasicX509Credential; +import org.testng.annotations.Test; + +import at.gv.egovernment.moa.util.KeyStoreUtils; +import at.gv.egovernment.moa.util.StringUtils; +import eu.stork.vidp.messages.exception.SAMLException; + +public class CertTest { + + /** KeyStore Path */ + private String keyStorePath = "file:/D:/dev/work/exthex/workspace/OAuthTesting/resources/keys/test_keystore.jks"; + + /** KeyStore Password */ + private String keyStorePassword = "test12"; + + /** Specific Key Name as Credential */ + private String keyName = "1"; + + /** Key password */ + private String keyPassword = "test12"; + + + + + @Test(enabled = false) + public void loadCert() throws Exception { + + if (StringUtils.isEmpty(this.keyStorePath)) throw new SAMLException("No keyStorePath specified"); + + // KeyStorePassword optional + // if (StringUtils.isEmpty(this.keyStorePassword)) + // throw new SAMLException("No keyStorePassword specified"); + + if (StringUtils.isEmpty(this.keyName)) throw new SAMLException("No keyName specified"); + + // KeyStorePassword optional + // if (StringUtils.isEmpty(this.keyPassword)) + // throw new SAMLException("No keyPassword specified"); + + KeyStore ks = null; + try { + ks = KeyStoreUtils.loadKeyStore(this.keyStorePath, this.keyStorePassword); + } + catch (Exception e) { + e.printStackTrace(); + } + + // return new KeyStoreX509CredentialAdapter(ks, keyName, keyPwd.toCharArray()); + BasicX509Credential credential = null; + try { + java.security.cert.X509Certificate certificate = (X509Certificate) ks.getCertificate(this.keyName); + + PrivateKey privateKey = (PrivateKey) ks.getKey(this.keyName, this.keyPassword.toCharArray()); + credential = new BasicX509Credential(); + credential.setEntityCertificate(certificate); + credential.setPrivateKey(privateKey); + + System.out.println(privateKey); + + } + catch (Exception e) { + e.printStackTrace(); + + } + System.out.println(credential); + + String data = "someData"; + + RsaSHA256Signer signer = new RsaSHA256Signer("signer1", keyName, (RSAPrivateKey) credential.getPrivateKey()); + + byte[] signedData = signer.sign(data.getBytes()); + + RsaSHA256Verifier verifier = new RsaSHA256Verifier(credential.getPublicKey()); + verifier.verifySignature(data.getBytes(), signedData); + } +} diff --git a/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20ErrorsTests.java b/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20ErrorsTests.java new file mode 100644 index 000000000..64179d75a --- /dev/null +++ b/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20ErrorsTests.java @@ -0,0 +1,190 @@ +package test.at.gv.egovernment.moa.id.auth.oauth; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Util; + +import com.google.api.client.extensions.java6.auth.oauth2.VerificationCodeReceiver; +import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; + +public class OAuth20ErrorsTests { + + final static Logger log = LoggerFactory.getLogger(OAuth20ErrorsTests.class); + + private static VerificationCodeReceiver receiver; + + // base uri + private static String OAUTH2_BASE_URI = "http://localhost:8080/moa-id-auth/dispatcher"; + // auth action + private static String OAUTH2_AUTH_URI = OAUTH2_BASE_URI + "?mod=id_oauth20&action=AUTH"; + // token action + private static String OAUTH2_TOKEN_URI = OAUTH2_BASE_URI + "?mod=id_oauth20&action=TOKEN"; + + // client id + private static String CLIENT_ID = "http://test"; + // client secret + private static String CLIENT_SECRET = "d435cf0a-3933-48f7-b142-339710c8f070"; + // OAuth 2.0 scopes + private static List SCOPES = Arrays.asList("testScope1", "testScope2"); + // state + private static String STATE = "testState"; + // code + private static String CODE = "code"; + // redirect uri + private static String REDIRECT_URI = "http://localhost:59542/Callback"; + + @BeforeMethod + public void beforeTest() throws Exception { + receiver = new LocalServerReceiver.Builder().setPort(59542).build(); + // REDIRECT_URI = receiver.getRedirectUri(); + // start + receiver.getRedirectUri(); + } + + @AfterMethod + public void afterTest() { + try { + receiver.stop(); + } + catch (IOException e) { + } + } + + private void checkParam(final String paramString, final String paramName) { + String[] help = paramString.split("="); + Assert.assertEquals(help[0], paramName); + Assert.assertTrue(StringUtils.isNotEmpty(help[1])); + } + + private void checkParams(final String queryString) { + // System.out.println("QueryString: " + queryString); + + System.out.println("Result url: " + queryString); + + String[] params = queryString.split("&"); + + this.checkParam(params[0], OAuth20Constants.PARAM_ERROR); + this.checkParam(params[1], OAuth20Constants.PARAM_ERROR_DESCRIPTION); + // this.checkParam(params[2], OAuth20Constants.PARAM_ERROR_URI); + // this.checkParam(params[3], OAuth20Constants.PARAM_STATE); + this.checkParam(params[2], OAuth20Constants.PARAM_STATE); + } + + class OAuthRequestParameters { + String redirectUri; + String clientId; + String responseType; + String scope; + String state; + String error; + + public OAuthRequestParameters(String redirectUri, String clientId, String responseType, String scope, String state, + String error) { + this.redirectUri = redirectUri; + this.clientId = clientId; + this.responseType = responseType; + this.scope = scope; + this.state = state; + this.error = error; + } + } + + @DataProvider(name = "parameter") + public Object[][] parameterProvider() { + // parameter is missing + // OAuthRequestParameters p0 = new OAuthRequestParameters(null, OA_URL, CLIENT_ID, CODE, + // "testScope1", null, + // "User authorization failed (invalid_request)"); + // OAuthRequestParameters p1 = new OAuthRequestParameters(REDIRECT_URI, CLIENT_ID, CODE, + // "testScope1", STATE, + // "User authorization failed (invalid_request)"); + OAuthRequestParameters p2 = new OAuthRequestParameters(REDIRECT_URI, null, CODE, "testScope1", STATE, + "User authorization failed (invalid_request)"); + OAuthRequestParameters p3 = new OAuthRequestParameters(REDIRECT_URI, CLIENT_ID, null, "testScope1", STATE, + "User authorization failed (invalid_request)"); + OAuthRequestParameters p4 = new OAuthRequestParameters(REDIRECT_URI, CLIENT_ID, CODE, null, STATE, null); + OAuthRequestParameters p5 = new OAuthRequestParameters(REDIRECT_URI, CLIENT_ID, CODE, "testScope1", null, + "User authorization failed (invalid_request)"); + + // wrong response type + OAuthRequestParameters p6 = new OAuthRequestParameters(REDIRECT_URI, CLIENT_ID, "WRONG_CODE", "testScope1", STATE, + "User authorization failed (unsupported_response_type)"); + // wrong client id + OAuthRequestParameters p7 = new OAuthRequestParameters(REDIRECT_URI, "wrongClient", CODE, "testScope1", STATE, + "User authorization failed (invalid_request)"); + // wrong redirect uri + // OAuthRequestParameters p9 = new OAuthRequestParameters("wrongURI", OA_URL, "wrongClient", + // CODE, "testScope1", STATE, + // "User authorization failed (access_denied)"); + + return new Object[][] { { p2 }, { p3 }, { p4 }, { p5 }, { p6 }, { p7 } }; + } + + @Test(dataProvider = "parameter", enabled = false) + public void testMissingParams(OAuthRequestParameters p) throws Exception { + StringBuilder url = new StringBuilder(); + url.append(OAUTH2_AUTH_URI); + + if (StringUtils.isNotEmpty(p.redirectUri)) OAuth20Util.addParameterToURL(url, "redirect_uri", p.redirectUri); + if (StringUtils.isNotEmpty(p.clientId)) OAuth20Util.addParameterToURL(url, "client_id", p.clientId); + if (StringUtils.isNotEmpty(p.responseType)) OAuth20Util.addParameterToURL(url, "response_type", p.responseType); + if (StringUtils.isNotEmpty(p.scope)) OAuth20Util.addParameterToURL(url, "scope", p.scope); + if (StringUtils.isNotEmpty(p.state)) OAuth20Util.addParameterToURL(url, "state", p.state); + + String finalUrl = url.toString(); + System.out.println("Calling: " + finalUrl); + + HttpClient client = new HttpClient(); + GetMethod get = new GetMethod(finalUrl); + int res = client.executeMethod(get); + Assert.assertEquals(res, HttpServletResponse.SC_OK); + + // assert + + if (p.error == null) { + Assert.assertFalse(get.getQueryString().contains("error")); + // receiver.waitForCode(); + } else { + // check if all error params are returned + this.checkParams(get.getQueryString()); + try { + receiver.waitForCode(); + Assert.assertTrue(false); + } + catch (Exception e) { + Assert.assertEquals(e.getMessage(), p.error); + } + } + } + + @Test(enabled = false) + public void testTokenErrorResponse() throws Exception { + HttpClient client = new HttpClient(); + GetMethod get = new GetMethod(OAUTH2_TOKEN_URI + "&client_id=" + CLIENT_ID + "&client_secret=" + CLIENT_SECRET + + "&code=test&grant_type=authorization_code"); + int res = client.executeMethod(get); + + System.out.println(res); + System.out.println(get.getResponseBodyAsString()); + } +} diff --git a/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20GoogleClientTestCase.java b/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20GoogleClientTestCase.java new file mode 100644 index 000000000..7cf2ac82b --- /dev/null +++ b/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20GoogleClientTestCase.java @@ -0,0 +1,136 @@ +package test.at.gv.egovernment.moa.id.auth.oauth; + +import java.awt.Desktop; +import java.awt.Desktop.Action; +import java.io.IOException; +import java.math.BigInteger; +import java.net.URI; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.google.api.client.auth.oauth2.AuthorizationCodeFlow; +import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl; +import com.google.api.client.auth.oauth2.BearerToken; +import com.google.api.client.auth.oauth2.ClientParametersAuthentication; +import com.google.api.client.auth.oauth2.TokenResponse; +import com.google.api.client.auth.openidconnect.IdToken; +import com.google.api.client.extensions.java6.auth.oauth2.VerificationCodeReceiver; +import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; +import com.google.api.client.http.GenericUrl; +import com.google.api.client.http.HttpExecuteInterceptor; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; + +public class OAuth20GoogleClientTestCase { + + final static Logger log = LoggerFactory.getLogger(OAuth20GoogleClientTestCase.class); + + // private static FileDataStoreFactory DATA_STORE_FACTORY; + + // Global instance of the HTTP transport. + private static HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + // Global instance of the JSON factory. + private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); + + private static String ISS = "https://localhost/moa-id-auth/"; + + // base uri + //private static String OAUTH2_BASE_URI = ISS + "dispatcher"; + // auth action + //private static String OAUTH2_AUTH_URI = OAUTH2_BASE_URI + "?mod=id_oauth20&action=AUTH"; + private static String OAUTH2_AUTH_URI = ISS + "oauth2/auth"; + + // token action + //private static String OAUTH2_TOKEN_URI = OAUTH2_BASE_URI + "?mod=id_oauth20&action=TOKEN"; + private static String OAUTH2_TOKEN_URI = ISS + "oauth2/token"; + + // client id + private static String CLIENT_ID = "http://test"; + // client secret + private static String CLIENT_SECRET = "d435cf0a-3933-48f7-b142-339710c8f070"; + // OAuth 2.0 scopes + private static final List SCOPES = Arrays.asList("profile", "eID", "eID_gov", "mandate"); + + // open browser for bku login + private void openURL(String url) { + Assert.assertNotNull(url); + System.out.println(url); + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + if (desktop.isSupported(Action.BROWSE)) { + try { + desktop.browse(URI.create(url)); + return; + } + catch (IOException e) { + // handled below + } + } + } + // Finally just ask user to open in their browser using copy-paste + + log.info("Please open the following URL in your browser:"); + log.info(url); + } + + private TokenResponse authorize() throws Exception { + // set up a receiver for the callback + VerificationCodeReceiver receiver = new LocalServerReceiver.Builder().setPort(59542).build(); + + // create AuthorizationCodeFlow + GenericUrl token_uri = new GenericUrl(OAUTH2_TOKEN_URI); + HttpExecuteInterceptor credentials = new ClientParametersAuthentication(CLIENT_ID, CLIENT_SECRET); + AuthorizationCodeFlow flow = new AuthorizationCodeFlow.Builder(BearerToken.queryParameterAccessMethod(), HTTP_TRANSPORT, + JSON_FACTORY, token_uri, credentials, CLIENT_ID, OAUTH2_AUTH_URI).setScopes(SCOPES).build(); + // .setDataStoreFactory(DATA_STORE_FACTORY) + + // create AuthorizationCodeRequestUrl + try { + String redirectUri = receiver.getRedirectUri(); + String state = new BigInteger(130, new SecureRandom()).toString(32); + AuthorizationCodeRequestUrl authorizationUrl = flow.newAuthorizationUrl().setRedirectUri(redirectUri).setState(state); + + // open in browser + this.openURL(authorizationUrl.build()); + + // receive authorization code and exchange it for an access token + String code = receiver.waitForCode(); + System.out.println(code); + TokenResponse response = flow.newTokenRequest(code).setRedirectUri(redirectUri).execute(); + return response; + } + finally { + // if anything fails, stop the receiver + receiver.stop(); + } + + } + + // eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJpc3MiOiJodHRwczovL2xvY2FsaG9zdC9tb2EtaWQtYXV0aC8iLCJleHAiOi02MzE5MDMsInN1YiI6IncveThQY2pNTHBFTGZmUHRTSDNtbmd6M24rRVx1MDAzZCIsImJpcnRoZGF0ZSI6IjE5ODUtMDItMDEiLCJmYW1pbHlfbmFtZSI6IkhpZXNzIiwiZ2l2ZW5fbmFtZSI6Ik1pY2hhZWwiLCJpYXQiOi02MzIyMDN9.Z_jveITHlTtktPOOV3n_sMbg50YQ4YcOEcSUs_RJ-4FGedj1sVxk9gmlUQcBPfQaBrPgC6RoiPLTy8CKu2PBClEyv9c9HdzIGqBjWzaTSNASx_QL5bfG4EQ8VZmSEI9d0whzlaBgkUFNfhx-Q2ZVh-g8SJ-0JO0zFR18OSRNTxPTJ4PPl0APqn2H-98sU331_zQKiZxNOvl_6OG26VoIYwEuW5m_N5tsf4lLAlqYcdHR3iNTeu8AkAOvlEwv7Z3BeeOiP4u-OWuc6VusWBPxaI2NwmDIoorpyIxY-wEFb4CWICuyk61Wlq1SCNdl-f-ODwJBK3rlj0IMlYbAjKSB0g + private void verifyIdToken(TokenResponse response) throws Exception { + String id_token = (String) response.getUnknownKeys().get("id_token"); + log.info("going to parse id token: {}", id_token); + + IdToken idToken = IdToken.parse(JSON_FACTORY, id_token); + Assert.assertTrue(idToken.verifyIssuer(ISS)); + + log.info(idToken.getPayload().toPrettyString()); + } + + @Test(enabled = false) + public void testServerFlow() throws Exception { + TokenResponse response = this.authorize(); + log.info(response.toPrettyString()); + + this.verifyIdToken(response); + } + +} diff --git a/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20UtilTest.java b/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20UtilTest.java new file mode 100644 index 000000000..83b92dbad --- /dev/null +++ b/id/server/idserverlib/src/test/java/test/at/gv/egovernment/moa/id/auth/oauth/OAuth20UtilTest.java @@ -0,0 +1,48 @@ +package test.at.gv.egovernment.moa.id.auth.oauth; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Util; + +public class OAuth20UtilTest { + + @Test + public void validateURL() { + Assert.assertTrue(OAuth20Util.isUrl("file:/D:/dev/work/exthex/workspace/OAuthTesting/resources/keys/test_keystore.jks")); + Assert.assertTrue(OAuth20Util.isUrl("https://www.google.at/")); + Assert.assertTrue(OAuth20Util.isUrl("http://test")); + Assert.assertTrue(OAuth20Util.isUrl("http://localhost:59542/Callback")); + + + Assert.assertFalse(OAuth20Util.isUrl("http://")); + Assert.assertFalse(OAuth20Util.isUrl("123http://test")); + Assert.assertFalse(OAuth20Util.isUrl("test")); + } + + @Test + public void validateState() { + // check state for invalid characters (like < > & ; ... javascript ... to prevent xss) + + Assert.assertFalse(OAuth20Util.isValidStateValue("javascript")); + Assert.assertFalse(OAuth20Util.isValidStateValue("")); + Assert.assertFalse(OAuth20Util.isValidStateValue("Tasst")); + Assert.assertFalse(OAuth20Util.isValidStateValue("Tes&t")); + Assert.assertFalse(OAuth20Util.isValidStateValue("Tes;t")); + Assert.assertTrue(OAuth20Util.isValidStateValue("secure_state")); + } + + + @Test + public void testExp() { + Pattern urlPattern = Pattern.compile("/oauth2/auth\\?(.*)$", Pattern.CASE_INSENSITIVE); + Matcher matcher = urlPattern.matcher("https://localhost/moa-id-auth/oauth2/auth?client_id=http://test&redirect_uri=http://localhost:59542/Callback&response_type=code&scope=profile%20eID%20eID_gov%20mandate&state=7gfnabf112ogg9segnnrfpi83q"); + System.out.println(matcher.find()); + } + +} diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/db/dao/session/AuthenticatedSessionStore.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/db/dao/session/AuthenticatedSessionStore.java index ed865d70f..97cc20d9f 100644 --- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/db/dao/session/AuthenticatedSessionStore.java +++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/db/dao/session/AuthenticatedSessionStore.java @@ -12,14 +12,14 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Lob; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; import org.hibernate.annotations.DynamicUpdate; diff --git a/id/server/moa-id-commons/src/main/resources/config/moaid_config_2.0.xsd b/id/server/moa-id-commons/src/main/resources/config/moaid_config_2.0.xsd index 085f187ff..481f12091 100644 --- a/id/server/moa-id-commons/src/main/resources/config/moaid_config_2.0.xsd +++ b/id/server/moa-id-commons/src/main/resources/config/moaid_config_2.0.xsd @@ -540,6 +540,7 @@ + @@ -872,6 +873,7 @@ + @@ -897,6 +899,15 @@ + + + + + + + + + -- cgit v1.2.3