package at.gv.egovernment.moa.id.protocols.oauth20.protocol; import java.io.IOException; import java.net.URLEncoder; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.google.gson.JsonObject; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.IModulInfo; import at.gv.egiz.eaaf.core.exceptions.EAAFException; import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException; import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractAuthProtocolModulController; import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; 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.OAuth20Exception; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @Controller public class OAuth20Protocol extends AbstractAuthProtocolModulController 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"; public static final List DEFAULTREQUESTEDATTRFORINTERFEDERATION = Arrays.asList( new String[] { PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME, PVPConstants.BPK_NAME }); @Autowired(required=true) AuthConfiguration moaAuthConfig; public String getName() { return NAME; } @Override public String getAuthProtocolIdentifier() { return PATH; } /** * */ public OAuth20Protocol() { super(); Logger.debug("Registering servlet " + getClass().getName() + " with mappings '/oauth2/auth' and '/oauth2/token'."); } //OpenID Connect auth request @RequestMapping(value = "/oauth2/auth", method = {RequestMethod.POST, RequestMethod.GET}) public void openIDConnectAuthRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException, IOException { if (!moaAuthConfig.getAllowedProtocols().isOAUTHActive()) { Logger.info("OpenID-Connect is deaktivated!"); throw new ProtocolNotActiveException("auth.22", new java.lang.Object[] { NAME }); } OAuth20AuthRequest pendingReq = applicationContext.getBean(OAuth20AuthRequest.class); try { pendingReq.initialize(req, authConfig); pendingReq.setModule(OAuth20Protocol.NAME); pendingReq.populateParameters(req, authConfig); } catch (EAAFException e) { Logger.info("OpenID-Connect request has a validation error: " + e.getMessage()); throw new InvalidProtocolRequestException(e.getErrorId(), e.getParams(), e); } revisionsLogger.logEvent(MOAIDEventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); revisionsLogger.logEvent(MOAIDEventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); revisionsLogger.logEvent( pendingReq.getUniqueSessionIdentifier(), pendingReq.getUniqueTransactionIdentifier(), MOAIDEventConstants.TRANSACTION_IP, req.getRemoteAddr()); //process request performAuthentication(req, resp, (RequestImpl)pendingReq); } //openID Connect tokken request @RequestMapping(value = "/oauth2/token", method = {RequestMethod.POST, RequestMethod.GET}) public void OpenIDConnectTokkenRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException, IOException, InvalidProtocolRequestException { if (!moaAuthConfig.getAllowedProtocols().isOAUTHActive()) { Logger.info("OpenID-Connect is deaktivated!"); throw new ProtocolNotActiveException("auth.22", new java.lang.Object[] { NAME }); } OAuth20TokenRequest pendingReq = applicationContext.getBean(OAuth20TokenRequest.class); try { pendingReq.initialize(req, authConfig); pendingReq.setModule(OAuth20Protocol.NAME); pendingReq.populateParameters(req, authConfig); } catch (EAAFException e) { Logger.info("OpenID-Connect request has a validation error: " + e.getMessage()); throw new InvalidProtocolRequestException(e.getErrorId(), e.getParams(), e); } revisionsLogger.logEvent(MOAIDEventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); revisionsLogger.logEvent(MOAIDEventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); revisionsLogger.logEvent( pendingReq.getUniqueSessionIdentifier(), pendingReq.getUniqueTransactionIdentifier(), MOAIDEventConstants.TRANSACTION_IP, req.getRemoteAddr()); //process request performAuthentication(req, resp, (RequestImpl)pendingReq); } /* * (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 { // get error code and description String errorCode; String errorDescription; String errorUri = protocolRequest.getAuthURL() +"/" + OAuth20Constants.ERRORPAGE; String moaError = null; if (e instanceof OAuth20Exception) { errorCode = ((OAuth20Exception) e).getErrorCode(); errorDescription = URLEncoder.encode(((OAuth20Exception) e).getMessageId() + ": " + e.getMessage(), "UTF-8"); moaError = statusMessager.mapInternalErrorToExternalError(((OAuth20Exception) e).getMessageId()); } else { errorCode = OAuth20Constants.ERROR_SERVER_ERROR; errorDescription = URLEncoder.encode(e.getMessage(), "UTF-8"); moaError = statusMessager.getResponseErrorCode(e); } String paramRedirect = null; String state = null; boolean isAuthRequest = false; if (protocolRequest != null) { if (protocolRequest instanceof OAuth20AuthRequest) { isAuthRequest = true; paramRedirect = ((OAuth20AuthRequest) protocolRequest).getRedirectUri(); state = ((OAuth20AuthRequest) protocolRequest).getState(); } else { isAuthRequest = false; } } else { String action = request.getParameter("action"); if (MiscUtil.isNotEmpty(action)) { if (action.equals(AUTH_ACTION)) { paramRedirect = request.getParameter(OAuth20Constants.PARAM_REDIRECT_URI); state = request.getParameter(OAuth20Constants.PARAM_STATE); isAuthRequest = true; } } else { throw new MOAIDException("oauth20.01", new Object[] {}); } } // if (action.equals(AUTH_ACTION)) { if (isAuthRequest) { Logger.debug("Going to throw O OAuth20Exception for auth request"); StringBuilder url = new StringBuilder(); // 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[] {}); } OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR, errorCode); OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR_DESCRIPTION, errorDescription); OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_STATE, state); if (MiscUtil.isNotEmpty(moaError)) OAuth20Util.addParameterToURL(url, OAuth20Constants.PARAM_ERROR_URI, URLEncoder.encode(errorUri + "#" + moaError, "UTF-8")); String redirectURL = protocolRequest.getAuthURL() + RedirectServlet.SERVICE_ENDPOINT; redirectURL = addURLParameter(redirectURL, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(url.toString(), "UTF-8")); response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_FOUND); response.addHeader("Location", redirectURL); Logger.debug("REDIRECT TO: " + redirectURL); return true; } else { Logger.debug("Going to throw O OAuth20Exception for token request"); Map params = new HashMap(); params.put(OAuth20Constants.PARAM_ERROR, errorCode); params.put(OAuth20Constants.PARAM_ERROR_DESCRIPTION, errorDescription); params.put(OAuth20Constants.PARAM_ERROR_URI, URLEncoder.encode(errorUri + "#" + moaError, "UTF-8")); // create response JsonObject jsonObject = new JsonObject(); OAuth20Util.addProperytiesToJsonObject(jsonObject, params); byte[] jsonResponse = jsonObject.toString().getBytes("UTF-8"); Logger.debug("JSON Response: " + new String(jsonResponse)); // write respone to http response response.setContentType("application/json"); response.setContentLength(jsonResponse.length); response.setStatus(HttpServletResponse.SC_BAD_REQUEST); response.getOutputStream().write(jsonResponse); 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; } protected static String addURLParameter(String url, String paramname, String paramvalue) { String param = paramname + "=" + paramvalue; if (url.indexOf("?") < 0) return url + "?" + param; else return url + "&" + param; } }