diff options
Diffstat (limited to 'id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20TokenAction.java')
-rw-r--r-- | id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20TokenAction.java | 346 |
1 files changed, 346 insertions, 0 deletions
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<T1, T2> { + 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<String, Object> params = new HashMap<String, Object>(); + 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<String, String> 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<String, String> 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<String, Object> params = new HashMap<String, Object>(); + 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<String, String>(token.serializeAndSign(), resultScopes.toString()); + } + + private void fillScopeProfile(Map<String, Object> params, AuthenticationData authData) { + params.put("given_name", authData.getGivenName()); + params.put("family_name", authData.getFamilyName()); + params.put("birthdate", authData.getDateOfBirth()); + } + + private void fillScopeOpenId(Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<FamilyName> 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<String> 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 + + } +} |